| // Copyright (c) 2022, 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''' |
| // `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 asyncBridge; |
| let dartInstance; |
| function stringFromDartString(string) { |
| const totalLength = dartInstance.exports.$stringLength(string); |
| let result = ''; |
| let index = 0; |
| while (index < totalLength) { |
| let chunkLength = Math.min(totalLength - index, 0xFFFF); |
| const array = new Array(chunkLength); |
| for (let i = 0; i < chunkLength; i++) { |
| array[i] = dartInstance.exports.$stringRead(string, index++); |
| } |
| result += String.fromCharCode(...array); |
| } |
| return result; |
| } |
| |
| function stringToDartString(string) { |
| const length = string.length; |
| let range = 0; |
| for (let i = 0; i < length; i++) { |
| range |= string.codePointAt(i); |
| } |
| if (range < 256) { |
| const dartString = dartInstance.exports.$stringAllocate1(length); |
| for (let i = 0; i < length; i++) { |
| dartInstance.exports.$stringWrite1(dartString, i, string.codePointAt(i)); |
| } |
| return dartString; |
| } else { |
| const dartString = dartInstance.exports.$stringAllocate2(length); |
| for (let i = 0; i < length; i++) { |
| dartInstance.exports.$stringWrite2(dartString, i, string.charCodeAt(i)); |
| } |
| return dartString; |
| } |
| } |
| |
| // 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 length = dartInstance.exports.$listLength(list); |
| const array = new constructor(length); |
| for (let i = 0; i < length; i++) { |
| array[i] = dartInstance.exports.$listRead(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 jsRuntimeBlobPart2 = r''' |
| }; |
| |
| const baseImports = { |
| dart2wasm: dart2wasm, |
| Math: Math, |
| Date: Date, |
| Object: Object, |
| Array: Array, |
| Reflect: Reflect, |
| }; |
| dartInstance = await WebAssembly.instantiate(await modulePromise, { |
| ...baseImports, |
| ...(await importObjectPromise), |
| }); |
| |
| // Initialize async bridge. |
| asyncBridge = new WebAssembly.Function( |
| {parameters: ['anyref', 'anyref'], results: ['externref']}, |
| dartInstance.exports.$asyncBridge, |
| {promising: 'first'}); |
| 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 = async (moduleInstance, ...args) => { |
| moduleInstance.exports.$invokeMain(moduleInstance.exports.$getMain()); |
| } |
| '''; |