@tybys/wasm-util 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,6 +8,51 @@ WebAssembly related utils for browser environment
8
8
 
9
9
  All example code below need to be bundled by ES module bundlers like `webpack` / `rollup`, or specify import map in browser native ES module runtime.
10
10
 
11
+ ### WASI polyfill for browser
12
+
13
+ The API is similar to the `require('wasi').WASI` in Node.js.
14
+
15
+ You can use `memfs-browser` to provide filesystem capability.
16
+
17
+ - Example: [https://github.com/toyobayashi/wasi-wabt](https://github.com/toyobayashi/wasi-wabt)
18
+ - Demo: [https://toyobayashi.github.io/wasi-wabt/](https://toyobayashi.github.io/wasi-wabt/)
19
+
20
+ ```js
21
+ import { load, WASI } from '@tybys/wasm-util'
22
+ import { Volumn, createFsFromVolume } from 'memfs-browser'
23
+
24
+ const fs = createFsFromVolume(Volume.from({
25
+ '/home/wasi': null
26
+ }))
27
+
28
+ const wasi = new WASI({
29
+ args: ['chrome', 'file.wasm'],
30
+ env: {
31
+ NODE_ENV: 'development',
32
+ WASI_SDK_PATH: '/opt/wasi-sdk'
33
+ },
34
+ preopens: {
35
+ '/': '/'
36
+ },
37
+ filesystem: { type: 'memfs', fs },
38
+
39
+ // redirect stdout / stderr
40
+
41
+ // print (text) { console.log(text) },
42
+ // printErr (text) { console.error(text) }
43
+ })
44
+
45
+ const imports = {
46
+ wasi_snapshot_preview1: wasi.wasiImport
47
+ }
48
+
49
+ const { module, instance } = await load('/path/to/file.wasm', imports)
50
+ wasi.start(instance)
51
+ // wasi.initialize(instance)
52
+ ```
53
+
54
+ Implemented syscalls: [wasi_snapshot_preview1](#wasi_snapshot_preview1)
55
+
11
56
  ### `load` / `loadSync`
12
57
 
13
58
  `loadSync` has 4KB wasm size limit in browser.
@@ -99,49 +144,7 @@ await p
99
144
  console.log(Date.now() - now >= 200)
100
145
  ```
101
146
 
102
- ### WASI polyfill for browser
103
-
104
- The API is similar to the `require('wasi').WASI` in Node.js.
105
-
106
- You can use `memfs-browser` to provide filesystem capability.
107
-
108
- ```js
109
- import { load, WASI } from '@tybys/wasm-util'
110
- import { Volumn, createFsFromVolume } from 'memfs-browser'
111
-
112
- const fs = createFsFromVolume(Volume.from({
113
- '/home/wasi': null
114
- }))
115
-
116
- const wasi = new WASI({
117
- args: ['chrome', 'file.wasm'],
118
- env: {
119
- NODE_ENV: 'development',
120
- WASI_SDK_PATH: '/opt/wasi-sdk'
121
- },
122
- preopens: {
123
- '/': '/'
124
- },
125
- filesystem: { type: 'memfs', fs },
126
-
127
- // redirect stdout / stderr
128
-
129
- // print (text) { console.log(text) },
130
- // printErr (text) { console.error(text) }
131
- })
132
-
133
- const imports = {
134
- wasi_snapshot_preview1: wasi.wasiImport
135
- }
136
-
137
- const { module, instance } = await load('/path/to/file.wasm', imports)
138
- wasi.start(instance)
139
- // wasi.initialize(instance)
140
- ```
141
-
142
- Implemented syscalls:
143
-
144
- #### wasi_snapshot_preview1
147
+ ### wasi_snapshot_preview1
145
148
 
146
149
  - [x] args_get
147
150
  - [x] args_sizes_get
@@ -64,7 +64,7 @@ export declare function load(urlOrBuffer: string | URL | BufferSource, imports?:
64
64
  export declare function loadSync(buffer: BufferSource, imports?: WebAssembly.Imports, asyncify?: AsyncifyOptions): WebAssembly.WebAssemblyInstantiatedSource;
65
65
 
66
66
  /** @public */
67
- export declare class Memory extends WebAssembly.Memory {
67
+ export declare class Memory extends WebAssemblyMemory {
68
68
  constructor(descriptor: WebAssembly.MemoryDescriptor);
69
69
  get HEAP8(): Int8Array;
70
70
  get HEAPU8(): Uint8Array;
@@ -79,6 +79,11 @@ export declare class Memory extends WebAssembly.Memory {
79
79
  get view(): DataView;
80
80
  }
81
81
 
82
+ /** @public */
83
+ export declare type PromisifyExports<T, U> = T extends Record<string, any> ? {
84
+ [P in keyof T]: T[P] extends Callable ? U extends Array<keyof T> ? P extends U[number] ? AsyncifyExportFunction<T[P]> : T[P] : AsyncifyExportFunction<T[P]> : T[P];
85
+ } : T;
86
+
82
87
  /** @public */
83
88
  export declare class WASI {
84
89
  private [kSetMemory];
@@ -108,6 +113,24 @@ export declare interface WASIOptions {
108
113
  };
109
114
  }
110
115
 
116
+ /** @public */
117
+ export declare const WebAssemblyMemory: {
118
+ new (descriptor: WebAssembly.MemoryDescriptor): WebAssembly.Memory;
119
+ prototype: WebAssembly.Memory;
120
+ };
121
+
122
+ /** @public */
123
+ export declare function wrapAsyncExport<T extends Function = any>(f: Function): T;
124
+
125
+ /** @public */
126
+ export declare function wrapAsyncImport(f: Function, parameterType: WebAssembly.ValueType[], returnType: WebAssembly.ValueType[]): Function;
127
+
128
+ /** @public */
129
+ export declare function wrapExports<T extends WebAssembly.Exports>(exports: T): PromisifyExports<T, void>;
130
+
131
+ /** @public */
132
+ export declare function wrapExports<T extends WebAssembly.Exports, U extends Array<keyof T>>(exports: T, needWrap: U): PromisifyExports<T, U>;
133
+
111
134
  export { }
112
135
 
113
136
  export as namespace wasmUtil;
@@ -1,3 +1,12 @@
1
+ const _WebAssembly = typeof WebAssembly !== 'undefined'
2
+ ? WebAssembly
3
+ : typeof WXWebAssembly !== 'undefined'
4
+ ? WXWebAssembly
5
+ : undefined;
6
+ if (!_WebAssembly) {
7
+ throw new Error('WebAssembly is not supported in this environment');
8
+ }
9
+
1
10
  function validateObject(value, name) {
2
11
  if (value === null || typeof value !== 'object') {
3
12
  throw new TypeError(`${name} must be an object. Received ${value === null ? 'null' : typeof value}`);
@@ -30,6 +39,17 @@ function validateUndefined(value, name) {
30
39
  }
31
40
  function isPromiseLike(obj) {
32
41
  return !!(obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function');
42
+ }
43
+ function wrapInstanceExports(exports, mapFn) {
44
+ const newExports = Object.create(null);
45
+ Object.keys(exports).forEach(name => {
46
+ const exportValue = exports[name];
47
+ Object.defineProperty(newExports, name, {
48
+ enumerable: true,
49
+ value: mapFn(exportValue, name)
50
+ });
51
+ });
52
+ return newExports;
33
53
  }
34
54
 
35
55
  const ignoreNames = [
@@ -69,7 +89,7 @@ class Asyncify {
69
89
  if (this.exports) {
70
90
  throw new Error('Asyncify has been initialized');
71
91
  }
72
- if (!(memory instanceof WebAssembly.Memory)) {
92
+ if (!(memory instanceof _WebAssembly.Memory)) {
73
93
  throw new TypeError('Require WebAssembly.Memory object');
74
94
  }
75
95
  const exports = instance.exports;
@@ -104,7 +124,7 @@ class Asyncify {
104
124
  new Int32Array(memory.buffer, this.dataPtr).set([address.start, address.end]);
105
125
  }
106
126
  this.exports = this.wrapExports(exports, options.wrapExports);
107
- const asyncifiedInstance = Object.create(WebAssembly.Instance.prototype);
127
+ const asyncifiedInstance = Object.create(_WebAssembly.Instance.prototype);
108
128
  Object.defineProperty(asyncifiedInstance, 'exports', { value: this.exports });
109
129
  // Object.setPrototypeOf(instance, Instance.prototype)
110
130
  return asyncifiedInstance;
@@ -163,20 +183,13 @@ class Asyncify {
163
183
  });
164
184
  }
165
185
  wrapExports(exports, needWrap) {
166
- const newExports = Object.create(null);
167
- Object.keys(exports).forEach(name => {
168
- const exportValue = exports[name];
186
+ return wrapInstanceExports(exports, (exportValue, name) => {
169
187
  let ignore = ignoreNames.indexOf(name) !== -1 || typeof exportValue !== 'function';
170
188
  if (Array.isArray(needWrap)) {
171
189
  ignore = ignore || (needWrap.indexOf(name) === -1);
172
190
  }
173
- Object.defineProperty(newExports, name, {
174
- enumerable: true,
175
- value: ignore ? exportValue : this.wrapExportFunction(exportValue)
176
- });
191
+ return ignore ? exportValue : this.wrapExportFunction(exportValue);
177
192
  });
178
- // wrappedExports.set(exports, newExports)
179
- return newExports;
180
193
  }
181
194
  }
182
195
  // /** @public */
@@ -194,9 +207,12 @@ class Asyncify {
194
207
  // Object.defineProperty(Instance.prototype, 'exports', { enumerable: true })
195
208
 
196
209
  async function fetchWasm(urlOrBuffer, imports) {
210
+ if (typeof wx !== 'undefined' && typeof __wxConfig !== 'undefined') {
211
+ return await _WebAssembly.instantiate(urlOrBuffer, imports);
212
+ }
197
213
  const response = await fetch(urlOrBuffer);
198
214
  const buffer = await response.arrayBuffer();
199
- const source = await WebAssembly.instantiate(buffer, imports);
215
+ const source = await _WebAssembly.instantiate(buffer, imports);
200
216
  return source;
201
217
  }
202
218
  /** @public */
@@ -213,7 +229,7 @@ async function load(urlOrBuffer, imports, asyncify) {
213
229
  imports = asyncifyHelper.wrapImports(imports);
214
230
  }
215
231
  if (urlOrBuffer instanceof ArrayBuffer || ArrayBuffer.isView(urlOrBuffer)) {
216
- source = await WebAssembly.instantiate(urlOrBuffer, imports);
232
+ source = await _WebAssembly.instantiate(urlOrBuffer, imports);
217
233
  if (asyncify) {
218
234
  const memory = source.instance.exports.memory || ((_a = imports.env) === null || _a === void 0 ? void 0 : _a.memory);
219
235
  return { module: source.module, instance: asyncifyHelper.init(memory, source.instance, asyncify) };
@@ -223,9 +239,9 @@ async function load(urlOrBuffer, imports, asyncify) {
223
239
  if (typeof urlOrBuffer !== 'string' && !(urlOrBuffer instanceof URL)) {
224
240
  throw new TypeError('Invalid source');
225
241
  }
226
- if (typeof WebAssembly.instantiateStreaming === 'function') {
242
+ if (typeof _WebAssembly.instantiateStreaming === 'function') {
227
243
  try {
228
- source = await WebAssembly.instantiateStreaming(fetch(urlOrBuffer), imports);
244
+ source = await _WebAssembly.instantiateStreaming(fetch(urlOrBuffer), imports);
229
245
  }
230
246
  catch (_) {
231
247
  source = await fetchWasm(urlOrBuffer, imports);
@@ -255,8 +271,8 @@ function loadSync(buffer, imports, asyncify) {
255
271
  asyncifyHelper = new Asyncify();
256
272
  imports = asyncifyHelper.wrapImports(imports);
257
273
  }
258
- const module = new WebAssembly.Module(buffer);
259
- const instance = new WebAssembly.Instance(module, imports);
274
+ const module = new _WebAssembly.Module(buffer);
275
+ const instance = new _WebAssembly.Instance(module, imports);
260
276
  const source = { instance, module };
261
277
  if (asyncify) {
262
278
  const memory = source.instance.exports.memory || ((_a = imports.env) === null || _a === void 0 ? void 0 : _a.memory);
@@ -842,7 +858,9 @@ class FileDescriptorTable {
842
858
  }
843
859
 
844
860
  /** @public */
845
- class Memory extends WebAssembly.Memory {
861
+ const WebAssemblyMemory = _WebAssembly.Memory;
862
+ /** @public */
863
+ class Memory extends WebAssemblyMemory {
846
864
  // eslint-disable-next-line @typescript-eslint/no-useless-constructor
847
865
  constructor(descriptor) {
848
866
  super(descriptor);
@@ -861,7 +879,7 @@ class Memory extends WebAssembly.Memory {
861
879
  }
862
880
  /** @public */
863
881
  function extendMemory(memory) {
864
- if (Object.getPrototypeOf(memory) === WebAssembly.Memory.prototype) {
882
+ if (Object.getPrototypeOf(memory) === _WebAssembly.Memory.prototype) {
865
883
  Object.setPrototypeOf(memory, Memory.prototype);
866
884
  }
867
885
  return memory;
@@ -972,7 +990,7 @@ function readStdin() {
972
990
  class WASI$1 {
973
991
  constructor(args, env, preopens, stdio, filesystem, print, printErr) {
974
992
  this._setMemory = function _setMemory(m) {
975
- if (!(m instanceof WebAssembly.Memory)) {
993
+ if (!(m instanceof _WebAssembly.Memory)) {
976
994
  throw new TypeError('"instance.exports.memory" property must be a WebAssembly.Memory');
977
995
  }
978
996
  _memory.set(this, extendMemory(m));
@@ -1279,6 +1297,9 @@ class WASI$1 {
1279
1297
  let buffer;
1280
1298
  let nread = 0;
1281
1299
  if (fd === 0) {
1300
+ if (typeof window === 'undefined' || typeof window.prompt !== 'function') {
1301
+ return 58 /* WasiErrno.ENOTSUP */;
1302
+ }
1282
1303
  buffer = readStdin();
1283
1304
  nread = buffer ? copyMemory(ioVecs, buffer) : 0;
1284
1305
  }
@@ -1876,4 +1897,42 @@ function wasiReturnOnProcExit(rval) {
1876
1897
  throw kExitCode;
1877
1898
  }
1878
1899
 
1879
- export { Asyncify, Memory, WASI, extendMemory, load, loadSync };
1900
+ function checkWebAssemblyFunction() {
1901
+ const WebAssemblyFunction = _WebAssembly.Function;
1902
+ if (typeof WebAssemblyFunction !== 'function') {
1903
+ throw new Error('WebAssembly.Function is not supported in this environment.' +
1904
+ ' If you are using V8 based browser like Chrome, try to specify' +
1905
+ ' --js-flag="--wasm-staging --experimental-wasm-stack-switching"');
1906
+ }
1907
+ return WebAssemblyFunction;
1908
+ }
1909
+ /** @public */
1910
+ function wrapAsyncImport(f, parameterType, returnType) {
1911
+ const WebAssemblyFunction = checkWebAssemblyFunction();
1912
+ if (typeof f !== 'function') {
1913
+ throw new TypeError('Function required');
1914
+ }
1915
+ const parameters = parameterType.slice(0);
1916
+ parameters.unshift('externref');
1917
+ return new WebAssemblyFunction({ parameters, results: returnType }, f, { suspending: 'first' });
1918
+ }
1919
+ /** @public */
1920
+ function wrapAsyncExport(f) {
1921
+ const WebAssemblyFunction = checkWebAssemblyFunction();
1922
+ if (typeof f !== 'function') {
1923
+ throw new TypeError('Function required');
1924
+ }
1925
+ return new WebAssemblyFunction({ parameters: [...WebAssemblyFunction.type(f).parameters.slice(1)], results: ['externref'] }, f, { promising: 'first' });
1926
+ }
1927
+ /** @public */
1928
+ function wrapExports(exports, needWrap) {
1929
+ return wrapInstanceExports(exports, (exportValue, name) => {
1930
+ let ignore = typeof exportValue !== 'function';
1931
+ if (Array.isArray(needWrap)) {
1932
+ ignore = ignore || (needWrap.indexOf(name) === -1);
1933
+ }
1934
+ return ignore ? exportValue : wrapAsyncExport(exportValue);
1935
+ });
1936
+ }
1937
+
1938
+ export { Asyncify, Memory, WASI, WebAssemblyMemory, extendMemory, load, loadSync, wrapAsyncExport, wrapAsyncImport, wrapExports };
@@ -1,3 +1,12 @@
1
+ const _WebAssembly = typeof WebAssembly !== 'undefined'
2
+ ? WebAssembly
3
+ : typeof WXWebAssembly !== 'undefined'
4
+ ? WXWebAssembly
5
+ : undefined;
6
+ if (!_WebAssembly) {
7
+ throw new Error('WebAssembly is not supported in this environment');
8
+ }
9
+
1
10
  function validateObject(value, name) {
2
11
  if (value === null || typeof value !== 'object') {
3
12
  throw new TypeError(`${name} must be an object. Received ${value === null ? 'null' : typeof value}`);
@@ -30,6 +39,17 @@ function validateUndefined(value, name) {
30
39
  }
31
40
  function isPromiseLike(obj) {
32
41
  return !!(obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function');
42
+ }
43
+ function wrapInstanceExports(exports, mapFn) {
44
+ const newExports = Object.create(null);
45
+ Object.keys(exports).forEach(name => {
46
+ const exportValue = exports[name];
47
+ Object.defineProperty(newExports, name, {
48
+ enumerable: true,
49
+ value: mapFn(exportValue, name)
50
+ });
51
+ });
52
+ return newExports;
33
53
  }
34
54
 
35
55
  const ignoreNames = [
@@ -69,7 +89,7 @@ class Asyncify {
69
89
  if (this.exports) {
70
90
  throw new Error('Asyncify has been initialized');
71
91
  }
72
- if (!(memory instanceof WebAssembly.Memory)) {
92
+ if (!(memory instanceof _WebAssembly.Memory)) {
73
93
  throw new TypeError('Require WebAssembly.Memory object');
74
94
  }
75
95
  const exports = instance.exports;
@@ -104,7 +124,7 @@ class Asyncify {
104
124
  new Int32Array(memory.buffer, this.dataPtr).set([address.start, address.end]);
105
125
  }
106
126
  this.exports = this.wrapExports(exports, options.wrapExports);
107
- const asyncifiedInstance = Object.create(WebAssembly.Instance.prototype);
127
+ const asyncifiedInstance = Object.create(_WebAssembly.Instance.prototype);
108
128
  Object.defineProperty(asyncifiedInstance, 'exports', { value: this.exports });
109
129
  // Object.setPrototypeOf(instance, Instance.prototype)
110
130
  return asyncifiedInstance;
@@ -163,20 +183,13 @@ class Asyncify {
163
183
  });
164
184
  }
165
185
  wrapExports(exports, needWrap) {
166
- const newExports = Object.create(null);
167
- Object.keys(exports).forEach(name => {
168
- const exportValue = exports[name];
186
+ return wrapInstanceExports(exports, (exportValue, name) => {
169
187
  let ignore = ignoreNames.indexOf(name) !== -1 || typeof exportValue !== 'function';
170
188
  if (Array.isArray(needWrap)) {
171
189
  ignore = ignore || (needWrap.indexOf(name) === -1);
172
190
  }
173
- Object.defineProperty(newExports, name, {
174
- enumerable: true,
175
- value: ignore ? exportValue : this.wrapExportFunction(exportValue)
176
- });
191
+ return ignore ? exportValue : this.wrapExportFunction(exportValue);
177
192
  });
178
- // wrappedExports.set(exports, newExports)
179
- return newExports;
180
193
  }
181
194
  }
182
195
  // /** @public */
@@ -194,9 +207,12 @@ class Asyncify {
194
207
  // Object.defineProperty(Instance.prototype, 'exports', { enumerable: true })
195
208
 
196
209
  async function fetchWasm(urlOrBuffer, imports) {
210
+ if (typeof wx !== 'undefined' && typeof __wxConfig !== 'undefined') {
211
+ return await _WebAssembly.instantiate(urlOrBuffer, imports);
212
+ }
197
213
  const response = await fetch(urlOrBuffer);
198
214
  const buffer = await response.arrayBuffer();
199
- const source = await WebAssembly.instantiate(buffer, imports);
215
+ const source = await _WebAssembly.instantiate(buffer, imports);
200
216
  return source;
201
217
  }
202
218
  /** @public */
@@ -213,7 +229,7 @@ async function load(urlOrBuffer, imports, asyncify) {
213
229
  imports = asyncifyHelper.wrapImports(imports);
214
230
  }
215
231
  if (urlOrBuffer instanceof ArrayBuffer || ArrayBuffer.isView(urlOrBuffer)) {
216
- source = await WebAssembly.instantiate(urlOrBuffer, imports);
232
+ source = await _WebAssembly.instantiate(urlOrBuffer, imports);
217
233
  if (asyncify) {
218
234
  const memory = source.instance.exports.memory || ((_a = imports.env) === null || _a === void 0 ? void 0 : _a.memory);
219
235
  return { module: source.module, instance: asyncifyHelper.init(memory, source.instance, asyncify) };
@@ -223,9 +239,9 @@ async function load(urlOrBuffer, imports, asyncify) {
223
239
  if (typeof urlOrBuffer !== 'string' && !(urlOrBuffer instanceof URL)) {
224
240
  throw new TypeError('Invalid source');
225
241
  }
226
- if (typeof WebAssembly.instantiateStreaming === 'function') {
242
+ if (typeof _WebAssembly.instantiateStreaming === 'function') {
227
243
  try {
228
- source = await WebAssembly.instantiateStreaming(fetch(urlOrBuffer), imports);
244
+ source = await _WebAssembly.instantiateStreaming(fetch(urlOrBuffer), imports);
229
245
  }
230
246
  catch (_) {
231
247
  source = await fetchWasm(urlOrBuffer, imports);
@@ -255,8 +271,8 @@ function loadSync(buffer, imports, asyncify) {
255
271
  asyncifyHelper = new Asyncify();
256
272
  imports = asyncifyHelper.wrapImports(imports);
257
273
  }
258
- const module = new WebAssembly.Module(buffer);
259
- const instance = new WebAssembly.Instance(module, imports);
274
+ const module = new _WebAssembly.Module(buffer);
275
+ const instance = new _WebAssembly.Instance(module, imports);
260
276
  const source = { instance, module };
261
277
  if (asyncify) {
262
278
  const memory = source.instance.exports.memory || ((_a = imports.env) === null || _a === void 0 ? void 0 : _a.memory);
@@ -842,7 +858,9 @@ class FileDescriptorTable {
842
858
  }
843
859
 
844
860
  /** @public */
845
- class Memory extends WebAssembly.Memory {
861
+ const WebAssemblyMemory = _WebAssembly.Memory;
862
+ /** @public */
863
+ class Memory extends WebAssemblyMemory {
846
864
  // eslint-disable-next-line @typescript-eslint/no-useless-constructor
847
865
  constructor(descriptor) {
848
866
  super(descriptor);
@@ -861,7 +879,7 @@ class Memory extends WebAssembly.Memory {
861
879
  }
862
880
  /** @public */
863
881
  function extendMemory(memory) {
864
- if (Object.getPrototypeOf(memory) === WebAssembly.Memory.prototype) {
882
+ if (Object.getPrototypeOf(memory) === _WebAssembly.Memory.prototype) {
865
883
  Object.setPrototypeOf(memory, Memory.prototype);
866
884
  }
867
885
  return memory;
@@ -972,7 +990,7 @@ function readStdin() {
972
990
  class WASI$1 {
973
991
  constructor(args, env, preopens, stdio, filesystem, print, printErr) {
974
992
  this._setMemory = function _setMemory(m) {
975
- if (!(m instanceof WebAssembly.Memory)) {
993
+ if (!(m instanceof _WebAssembly.Memory)) {
976
994
  throw new TypeError('"instance.exports.memory" property must be a WebAssembly.Memory');
977
995
  }
978
996
  _memory.set(this, extendMemory(m));
@@ -1279,6 +1297,9 @@ class WASI$1 {
1279
1297
  let buffer;
1280
1298
  let nread = 0;
1281
1299
  if (fd === 0) {
1300
+ if (typeof window === 'undefined' || typeof window.prompt !== 'function') {
1301
+ return 58 /* WasiErrno.ENOTSUP */;
1302
+ }
1282
1303
  buffer = readStdin();
1283
1304
  nread = buffer ? copyMemory(ioVecs, buffer) : 0;
1284
1305
  }
@@ -1876,4 +1897,42 @@ function wasiReturnOnProcExit(rval) {
1876
1897
  throw kExitCode;
1877
1898
  }
1878
1899
 
1879
- export { Asyncify, Memory, WASI, extendMemory, load, loadSync };
1900
+ function checkWebAssemblyFunction() {
1901
+ const WebAssemblyFunction = _WebAssembly.Function;
1902
+ if (typeof WebAssemblyFunction !== 'function') {
1903
+ throw new Error('WebAssembly.Function is not supported in this environment.' +
1904
+ ' If you are using V8 based browser like Chrome, try to specify' +
1905
+ ' --js-flag="--wasm-staging --experimental-wasm-stack-switching"');
1906
+ }
1907
+ return WebAssemblyFunction;
1908
+ }
1909
+ /** @public */
1910
+ function wrapAsyncImport(f, parameterType, returnType) {
1911
+ const WebAssemblyFunction = checkWebAssemblyFunction();
1912
+ if (typeof f !== 'function') {
1913
+ throw new TypeError('Function required');
1914
+ }
1915
+ const parameters = parameterType.slice(0);
1916
+ parameters.unshift('externref');
1917
+ return new WebAssemblyFunction({ parameters, results: returnType }, f, { suspending: 'first' });
1918
+ }
1919
+ /** @public */
1920
+ function wrapAsyncExport(f) {
1921
+ const WebAssemblyFunction = checkWebAssemblyFunction();
1922
+ if (typeof f !== 'function') {
1923
+ throw new TypeError('Function required');
1924
+ }
1925
+ return new WebAssemblyFunction({ parameters: [...WebAssemblyFunction.type(f).parameters.slice(1)], results: ['externref'] }, f, { promising: 'first' });
1926
+ }
1927
+ /** @public */
1928
+ function wrapExports(exports, needWrap) {
1929
+ return wrapInstanceExports(exports, (exportValue, name) => {
1930
+ let ignore = typeof exportValue !== 'function';
1931
+ if (Array.isArray(needWrap)) {
1932
+ ignore = ignore || (needWrap.indexOf(name) === -1);
1933
+ }
1934
+ return ignore ? exportValue : wrapAsyncExport(exportValue);
1935
+ });
1936
+ }
1937
+
1938
+ export { Asyncify, Memory, WASI, WebAssemblyMemory, extendMemory, load, loadSync, wrapAsyncExport, wrapAsyncImport, wrapExports };