blob: ad7f48f9e363993d48e57281e179d3f8d0b08a28 [file] [log] [blame]
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
const jsRuntimeBlobPart1 = r'''
// Returns whether the `js-string` built-in is supported.
function detectJsStringBuiltins() {
let bytes = [
0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0,
0, 2, 23, 1, 14, 119, 97, 115, 109, 58, 106, 115, 45,
115, 116, 114, 105, 110, 103, 4, 99, 97, 115, 116, 0, 0
];
return WebAssembly.validate(
new Uint8Array(bytes), {builtins: ['js-string']});
}
// Compile a dart2wasm-generated Wasm module using
// `WebAssembly.compileStreaming`, with the flags needed by dart2wasm. `source`
// needs to have a type expected by `WebAssembly.compileStreaming`.
//
// Pass the output of this to `instantiate` below to instantiate the compiled
// module.
export const compileStreaming = (source) => {
return WebAssembly.compileStreaming(
source,
detectJsStringBuiltins() ? {builtins: ['js-string']} : {}
);
}
// Compile a dart2wasm-generated Wasm module using `WebAssembly.compile`, with
// the flags needed by dart2wasm. `source` needs to have a type expected by
// `WebAssembly.compileStreaming`.
//
// Pass the output of this to `instantiate` below to instantiate the compiled
// module.
export const compile = (bytes) => {
return WebAssembly.compile(
bytes,
detectJsStringBuiltins() ? {builtins: ['js-string']} : {}
);
}
// `modulePromise` is a promise to the `WebAssembly.module` object to be
// instantiated.
// `importObjectPromise` is a promise to an object that contains any additional
// imports needed by the module that aren't provided by the standard runtime.
// The fields on this object will be merged into the importObject with which
// the module will be instantiated.
// This function returns a promise to the instantiated module.
export const instantiate = async (modulePromise, importObjectPromise) => {
let dartInstance;
''';
const jsRuntimeBlobPart3 = r'''
// Prints to the console
function printToConsole(value) {
if (typeof dartPrint == "function") {
dartPrint(value);
return;
}
if (typeof console == "object" && typeof console.log != "undefined") {
console.log(value);
return;
}
if (typeof print == "function") {
print(value);
return;
}
throw "Unable to print message: " + js;
}
// Converts a Dart List to a JS array. Any Dart objects will be converted, but
// this will be cheap for JSValues.
function arrayFromDartList(constructor, list) {
const exports = dartInstance.exports;
const read = exports.$listRead;
const length = exports.$listLength(list);
const array = new constructor(length);
for (let i = 0; i < length; i++) {
array[i] = read(list, i);
}
return array;
}
// A special symbol attached to functions that wrap Dart functions.
const jsWrappedDartFunctionSymbol = Symbol("JSWrappedDartFunction");
function finalizeWrapper(dartFunction, wrapped) {
wrapped.dartFunction = dartFunction;
wrapped[jsWrappedDartFunctionSymbol] = true;
return wrapped;
}
// Imports
const dart2wasm = {
''';
// We break inside the 'dart2wasm' object to enable injection of methods. We
// could use interpolation, but then we'd have to escape characters.
const jsRuntimeBlobPart4 = r'''
};
const baseImports = {
dart2wasm: dart2wasm,
''';
// We break inside of `baseImports` to inject internalized strings.
const jsRuntimeBlobPart5 = r'''
Math: Math,
Date: Date,
Object: Object,
Array: Array,
Reflect: Reflect,
};
const jsStringPolyfill = {
"charCodeAt": (s, i) => s.charCodeAt(i),
"compare": (s1, s2) => {
if (s1 < s2) return -1;
if (s1 > s2) return 1;
return 0;
},
"concat": (s1, s2) => s1 + s2,
"equals": (s1, s2) => s1 === s2,
"fromCharCode": (i) => String.fromCharCode(i),
"length": (s) => s.length,
"substring": (s, a, b) => s.substring(a, b),
};
dartInstance = await WebAssembly.instantiate(await modulePromise, {
...baseImports,
...(await importObjectPromise),
"wasm:js-string": jsStringPolyfill,
});
return dartInstance;
}
// Call the main function for the instantiated module
// `moduleInstance` is the instantiated dart2wasm module
// `args` are any arguments that should be passed into the main function.
export const invoke = (moduleInstance, ...args) => {
moduleInstance.exports.$invokeMain(args);
}
''';