@metamask/snaps-cli 3.0.5 → 4.0.1

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/CHANGELOG.md CHANGED
@@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [4.0.1]
10
+ ### Fixed
11
+ - Fix missing `global` during snap evaluation ([#2072](https://github.com/MetaMask/snaps/pull/2072))
12
+
13
+ ## [4.0.0]
14
+ ### Changed
15
+ - **BREAKING:** Synchronously initialize WASM modules ([#2024](https://github.com/MetaMask/snaps/pull/2024))
16
+ - When the `experimental.wasm` flag in the Snaps CLI is enabled, the WASM module will now be synchronously initialized, rather than being inlined as a Uint8Array.
17
+
9
18
  ## [3.0.5]
10
19
  ### Fixed
11
20
  - Include Snap icon in allowed server paths ([#2003](https://github.com/MetaMask/snaps/pull/2003))
@@ -86,7 +95,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
86
95
  - The version of the package no longer needs to match the version of all other
87
96
  MetaMask Snaps packages.
88
97
 
89
- [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-cli@3.0.5...HEAD
98
+ [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-cli@4.0.1...HEAD
99
+ [4.0.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-cli@4.0.0...@metamask/snaps-cli@4.0.1
100
+ [4.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-cli@3.0.5...@metamask/snaps-cli@4.0.0
90
101
  [3.0.5]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-cli@3.0.4...@metamask/snaps-cli@3.0.5
91
102
  [3.0.4]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-cli@3.0.3...@metamask/snaps-cli@3.0.4
92
103
  [3.0.3]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-cli@3.0.2...@metamask/snaps-cli@3.0.3
package/README.md CHANGED
@@ -422,7 +422,7 @@ can be imported in the snap, for example:
422
422
  ```typescript
423
423
  import program from './program.wasm';
424
424
 
425
- const module = await WebAssembly.instantiate(program, {});
425
+ // Program is initialised synchronously.
426
426
  // ...
427
427
  ```
428
428
 
@@ -1,36 +1,90 @@
1
- "use strict";
1
+ /* eslint-disable no-restricted-globals */ "use strict";
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- Object.defineProperty(exports, /**
6
- * A Webpack loader that inlines the WASM module as a `Uint8Array`. This makes
7
- * it possible to import the WASM module directly, and use it with the
8
- * `WebAssembly.instantiate` function.
9
- *
10
- * This is useful, because snaps are not allowed to import assets from outside
11
- * of their package. This loader allows you to inline the WASM module as a
12
- * `Uint8Array`, which can then be passed to `WebAssembly.instantiate`.
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ getImports: function() {
13
+ return getImports;
14
+ },
15
+ getModuleImports: function() {
16
+ return getModuleImports;
17
+ },
18
+ getExports: function() {
19
+ return getExports;
20
+ },
21
+ default: function() {
22
+ return _default;
23
+ },
24
+ raw: function() {
25
+ return raw;
26
+ }
27
+ });
28
+ const _utils = require("@metamask/utils");
29
+ function getImports(importMap) {
30
+ return Object.entries(importMap).map(([moduleName, exportNames])=>`import { ${exportNames.join(', ')} } from ${JSON.stringify(moduleName)};`).join('\n');
31
+ }
32
+ function getModuleImports(importMap) {
33
+ return Object.entries(importMap).map(([moduleName, exportNames])=>`${JSON.stringify(moduleName)}: { ${exportNames.join(', ')} },`).join('\n');
34
+ }
35
+ function getExports(descriptors) {
36
+ return descriptors.map((descriptor)=>{
37
+ if (descriptor.name === 'default') {
38
+ return `export default exports[${JSON.stringify(descriptor.name)}];`;
39
+ }
40
+ return `export const ${descriptor.name} = exports[${JSON.stringify(descriptor.name)}];`;
41
+ }).join('\n');
42
+ }
43
+ /**
44
+ * A Webpack loader that synchronously loads the WASM module. This makes it
45
+ * possible to import the WASM module directly.
13
46
  *
14
- * @param source - The WASM module as a string.
15
- * @returns A string that exports the WASM module as a `Uint8Array`.
47
+ * @param source - The WASM module as `Uint8Array`.
48
+ * @returns The WASM module as a JavaScript string.
16
49
  * @example
17
50
  * ```ts
18
- * import wasm from './program.wasm';
51
+ * import * as wasm from './program.wasm';
19
52
  *
20
- * const { instance } = await WebAssembly.instantiate(wasm, {});
21
53
  * // Do something with the WASM module...
22
54
  * ```
23
- */ "default", {
24
- enumerable: true,
25
- get: function() {
26
- return loader;
55
+ */ // Note: This function needs to be defined like this, so that Webpack can bind
56
+ // `this` to the loader context, and TypeScript can infer the type of `this`.
57
+ const loader = async function loader(source) {
58
+ (0, _utils.assert)(source instanceof Uint8Array, 'Expected source to be a Uint8Array.');
59
+ const bytes = new Uint8Array(source);
60
+ const wasmModule = await WebAssembly.compile(bytes);
61
+ // eslint-disable-next-line @typescript-eslint/no-shadow
62
+ const exports1 = WebAssembly.Module.exports(wasmModule);
63
+ const imports = WebAssembly.Module.imports(wasmModule).reduce((target, descriptor)=>{
64
+ var _target, _descriptor_module;
65
+ (_target = target)[_descriptor_module = descriptor.module] ?? (_target[_descriptor_module] = []);
66
+ target[descriptor.module].push(descriptor.name);
67
+ return target;
68
+ }, {});
69
+ // Add the WASM import as a dependency so that Webpack will watch it for
70
+ // changes.
71
+ for (const name of Object.keys(imports)){
72
+ this.addDependency(name);
27
73
  }
28
- });
29
- const _utils = require("@metamask/utils");
30
- function loader(source) {
31
- (0, _utils.assert)(typeof source === 'string', 'Expected source to be a string.');
32
- const bytes = (0, _utils.stringToBytes)(source);
33
- return `export default new Uint8Array(${JSON.stringify(Array.from(bytes))});`;
34
- }
74
+ return `
75
+ ${getImports(imports)}
76
+
77
+ const bytes = new Uint8Array(${JSON.stringify(Array.from(source))});
78
+ const module = new WebAssembly.Module(bytes);
79
+ const instance = new WebAssembly.Instance(module, {
80
+ ${getModuleImports(imports)}
81
+ });
82
+
83
+ const exports = instance.exports;
84
+ ${getExports(exports1)}
85
+ `;
86
+ };
87
+ const _default = loader;
88
+ const raw = true;
35
89
 
36
90
  //# sourceMappingURL=wasm.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/webpack/loaders/wasm.ts"],"sourcesContent":["import { assert, stringToBytes } from '@metamask/utils';\n\n/**\n * A Webpack loader that inlines the WASM module as a `Uint8Array`. This makes\n * it possible to import the WASM module directly, and use it with the\n * `WebAssembly.instantiate` function.\n *\n * This is useful, because snaps are not allowed to import assets from outside\n * of their package. This loader allows you to inline the WASM module as a\n * `Uint8Array`, which can then be passed to `WebAssembly.instantiate`.\n *\n * @param source - The WASM module as a string.\n * @returns A string that exports the WASM module as a `Uint8Array`.\n * @example\n * ```ts\n * import wasm from './program.wasm';\n *\n * const { instance } = await WebAssembly.instantiate(wasm, {});\n * // Do something with the WASM module...\n * ```\n */\nexport default function loader(source: unknown) {\n assert(typeof source === 'string', 'Expected source to be a string.');\n\n const bytes = stringToBytes(source);\n return `export default new Uint8Array(${JSON.stringify(Array.from(bytes))});`;\n}\n"],"names":["loader","source","assert","bytes","stringToBytes","JSON","stringify","Array","from"],"mappings":";;;;+BAEA;;;;;;;;;;;;;;;;;;CAkBC,GACD;;;eAAwBA;;;uBArBc;AAqBvB,SAASA,OAAOC,MAAe;IAC5CC,IAAAA,aAAM,EAAC,OAAOD,WAAW,UAAU;IAEnC,MAAME,QAAQC,IAAAA,oBAAa,EAACH;IAC5B,OAAO,CAAC,8BAA8B,EAAEI,KAAKC,SAAS,CAACC,MAAMC,IAAI,CAACL,QAAQ,EAAE,CAAC;AAC/E"}
1
+ {"version":3,"sources":["../../../../src/webpack/loaders/wasm.ts"],"sourcesContent":["/* eslint-disable no-restricted-globals */\n\nimport { assert } from '@metamask/utils';\nimport type { LoaderDefinitionFunction } from 'webpack';\n\n/**\n * Get the imports code for the WASM module. This code imports each of the\n * imports from the WASM module.\n *\n * @param importMap - The import map for the WASM module.\n * @returns The imports code for the WASM module.\n */\nexport function getImports(importMap: Record<string, string[]>) {\n return Object.entries(importMap)\n .map(\n ([moduleName, exportNames]) =>\n `import { ${exportNames.join(', ')} } from ${JSON.stringify(\n moduleName,\n )};`,\n )\n .join('\\n');\n}\n\n/**\n * Get the imports code to use in `WebAssembly.Instance`. This code adds each of\n * the imports to the `imports` object.\n *\n * @param importMap - The import map for the WASM module.\n * @returns The imports code for the WASM module.\n */\nexport function getModuleImports(importMap: Record<string, string[]>) {\n return Object.entries(importMap)\n .map(\n ([moduleName, exportNames]) =>\n `${JSON.stringify(moduleName)}: { ${exportNames.join(', ')} },`,\n )\n .join('\\n');\n}\n\n/**\n * Get the exports code for the WASM module. This code exports each of the\n * exports from the WASM module as a variable. This function assumes that the\n * exports are available in a variable named `exports`.\n *\n * @param descriptors - The export descriptors from the WASM module.\n * @returns The exports code for the WASM module.\n */\nexport function getExports(descriptors: WebAssembly.ModuleExportDescriptor[]) {\n return descriptors\n .map((descriptor) => {\n if (descriptor.name === 'default') {\n return `export default exports[${JSON.stringify(descriptor.name)}];`;\n }\n\n return `export const ${descriptor.name} = exports[${JSON.stringify(\n descriptor.name,\n )}];`;\n })\n .join('\\n');\n}\n\n/**\n * A Webpack loader that synchronously loads the WASM module. This makes it\n * possible to import the WASM module directly.\n *\n * @param source - The WASM module as `Uint8Array`.\n * @returns The WASM module as a JavaScript string.\n * @example\n * ```ts\n * import * as wasm from './program.wasm';\n *\n * // Do something with the WASM module...\n * ```\n */\n// Note: This function needs to be defined like this, so that Webpack can bind\n// `this` to the loader context, and TypeScript can infer the type of `this`.\nconst loader: LoaderDefinitionFunction = async function loader(\n source: unknown,\n) {\n assert(source instanceof Uint8Array, 'Expected source to be a Uint8Array.');\n\n const bytes = new Uint8Array(source);\n const wasmModule = await WebAssembly.compile(bytes);\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n const exports = WebAssembly.Module.exports(wasmModule);\n const imports = WebAssembly.Module.imports(wasmModule).reduce<\n Record<string, string[]>\n >((target, descriptor) => {\n target[descriptor.module] ??= [];\n target[descriptor.module].push(descriptor.name);\n\n return target;\n }, {});\n\n // Add the WASM import as a dependency so that Webpack will watch it for\n // changes.\n for (const name of Object.keys(imports)) {\n this.addDependency(name);\n }\n\n return `\n ${getImports(imports)}\n\n const bytes = new Uint8Array(${JSON.stringify(Array.from(source))});\n const module = new WebAssembly.Module(bytes);\n const instance = new WebAssembly.Instance(module, {\n ${getModuleImports(imports)}\n });\n\n const exports = instance.exports;\n ${getExports(exports)}\n `;\n};\n\nexport default loader;\n\n// By setting `raw` to `true`, we are telling Webpack to provide the source as a\n// `Uint8Array` instead of converting it to a string. This allows us to avoid\n// having to convert the source back to a `Uint8Array` in the loader.\nexport const raw = true;\n"],"names":["getImports","getModuleImports","getExports","raw","importMap","Object","entries","map","moduleName","exportNames","join","JSON","stringify","descriptors","descriptor","name","loader","source","assert","Uint8Array","bytes","wasmModule","WebAssembly","compile","exports","Module","imports","reduce","target","module","push","keys","addDependency","Array","from"],"mappings":"AAAA,wCAAwC;;;;;;;;;;;IAYxBA,UAAU;eAAVA;;IAkBAC,gBAAgB;eAAhBA;;IAiBAC,UAAU;eAAVA;;IAoEhB,OAAsB;eAAtB;;IAKaC,GAAG;eAAHA;;;uBAtHU;AAUhB,SAASH,WAAWI,SAAmC;IAC5D,OAAOC,OAAOC,OAAO,CAACF,WACnBG,GAAG,CACF,CAAC,CAACC,YAAYC,YAAY,GACxB,CAAC,SAAS,EAAEA,YAAYC,IAAI,CAAC,MAAM,QAAQ,EAAEC,KAAKC,SAAS,CACzDJ,YACA,CAAC,CAAC,EAEPE,IAAI,CAAC;AACV;AASO,SAAST,iBAAiBG,SAAmC;IAClE,OAAOC,OAAOC,OAAO,CAACF,WACnBG,GAAG,CACF,CAAC,CAACC,YAAYC,YAAY,GACxB,CAAC,EAAEE,KAAKC,SAAS,CAACJ,YAAY,IAAI,EAAEC,YAAYC,IAAI,CAAC,MAAM,GAAG,CAAC,EAElEA,IAAI,CAAC;AACV;AAUO,SAASR,WAAWW,WAAiD;IAC1E,OAAOA,YACJN,GAAG,CAAC,CAACO;QACJ,IAAIA,WAAWC,IAAI,KAAK,WAAW;YACjC,OAAO,CAAC,uBAAuB,EAAEJ,KAAKC,SAAS,CAACE,WAAWC,IAAI,EAAE,EAAE,CAAC;QACtE;QAEA,OAAO,CAAC,aAAa,EAAED,WAAWC,IAAI,CAAC,WAAW,EAAEJ,KAAKC,SAAS,CAChEE,WAAWC,IAAI,EACf,EAAE,CAAC;IACP,GACCL,IAAI,CAAC;AACV;AAEA;;;;;;;;;;;;CAYC,GACD,8EAA8E;AAC9E,6EAA6E;AAC7E,MAAMM,SAAmC,eAAeA,OACtDC,MAAe;IAEfC,IAAAA,aAAM,EAACD,kBAAkBE,YAAY;IAErC,MAAMC,QAAQ,IAAID,WAAWF;IAC7B,MAAMI,aAAa,MAAMC,YAAYC,OAAO,CAACH;IAE7C,wDAAwD;IACxD,MAAMI,WAAUF,YAAYG,MAAM,CAACD,OAAO,CAACH;IAC3C,MAAMK,UAAUJ,YAAYG,MAAM,CAACC,OAAO,CAACL,YAAYM,MAAM,CAE3D,CAACC,QAAQd;YACTc,SAAOd;QAAPc,CAAAA,UAAAA,OAAM,CAACd,qBAAAA,WAAWe,MAAM,CAAC,KAAzBD,OAAM,CAACd,mBAAkB,GAAK,EAAE;QAChCc,MAAM,CAACd,WAAWe,MAAM,CAAC,CAACC,IAAI,CAAChB,WAAWC,IAAI;QAE9C,OAAOa;IACT,GAAG,CAAC;IAEJ,wEAAwE;IACxE,WAAW;IACX,KAAK,MAAMb,QAAQV,OAAO0B,IAAI,CAACL,SAAU;QACvC,IAAI,CAACM,aAAa,CAACjB;IACrB;IAEA,OAAO,CAAC;IACN,EAAEf,WAAW0B,SAAS;;iCAEO,EAAEf,KAAKC,SAAS,CAACqB,MAAMC,IAAI,CAACjB,SAAS;;;MAGhE,EAAEhB,iBAAiByB,SAAS;;;;IAI9B,EAAExB,WAAWsB,UAAS;EACxB,CAAC;AACH;MAEA,WAAeR;AAKR,MAAMb,MAAM"}
@@ -1,26 +1,85 @@
1
- import { assert, stringToBytes } from '@metamask/utils';
1
+ /* eslint-disable no-restricted-globals */ import { assert } from '@metamask/utils';
2
2
  /**
3
- * A Webpack loader that inlines the WASM module as a `Uint8Array`. This makes
4
- * it possible to import the WASM module directly, and use it with the
5
- * `WebAssembly.instantiate` function.
3
+ * Get the imports code for the WASM module. This code imports each of the
4
+ * imports from the WASM module.
6
5
  *
7
- * This is useful, because snaps are not allowed to import assets from outside
8
- * of their package. This loader allows you to inline the WASM module as a
9
- * `Uint8Array`, which can then be passed to `WebAssembly.instantiate`.
6
+ * @param importMap - The import map for the WASM module.
7
+ * @returns The imports code for the WASM module.
8
+ */ export function getImports(importMap) {
9
+ return Object.entries(importMap).map(([moduleName, exportNames])=>`import { ${exportNames.join(', ')} } from ${JSON.stringify(moduleName)};`).join('\n');
10
+ }
11
+ /**
12
+ * Get the imports code to use in `WebAssembly.Instance`. This code adds each of
13
+ * the imports to the `imports` object.
14
+ *
15
+ * @param importMap - The import map for the WASM module.
16
+ * @returns The imports code for the WASM module.
17
+ */ export function getModuleImports(importMap) {
18
+ return Object.entries(importMap).map(([moduleName, exportNames])=>`${JSON.stringify(moduleName)}: { ${exportNames.join(', ')} },`).join('\n');
19
+ }
20
+ /**
21
+ * Get the exports code for the WASM module. This code exports each of the
22
+ * exports from the WASM module as a variable. This function assumes that the
23
+ * exports are available in a variable named `exports`.
10
24
  *
11
- * @param source - The WASM module as a string.
12
- * @returns A string that exports the WASM module as a `Uint8Array`.
25
+ * @param descriptors - The export descriptors from the WASM module.
26
+ * @returns The exports code for the WASM module.
27
+ */ export function getExports(descriptors) {
28
+ return descriptors.map((descriptor)=>{
29
+ if (descriptor.name === 'default') {
30
+ return `export default exports[${JSON.stringify(descriptor.name)}];`;
31
+ }
32
+ return `export const ${descriptor.name} = exports[${JSON.stringify(descriptor.name)}];`;
33
+ }).join('\n');
34
+ }
35
+ /**
36
+ * A Webpack loader that synchronously loads the WASM module. This makes it
37
+ * possible to import the WASM module directly.
38
+ *
39
+ * @param source - The WASM module as `Uint8Array`.
40
+ * @returns The WASM module as a JavaScript string.
13
41
  * @example
14
42
  * ```ts
15
- * import wasm from './program.wasm';
43
+ * import * as wasm from './program.wasm';
16
44
  *
17
- * const { instance } = await WebAssembly.instantiate(wasm, {});
18
45
  * // Do something with the WASM module...
19
46
  * ```
20
- */ export default function loader(source) {
21
- assert(typeof source === 'string', 'Expected source to be a string.');
22
- const bytes = stringToBytes(source);
23
- return `export default new Uint8Array(${JSON.stringify(Array.from(bytes))});`;
24
- }
47
+ */ // Note: This function needs to be defined like this, so that Webpack can bind
48
+ // `this` to the loader context, and TypeScript can infer the type of `this`.
49
+ const loader = async function loader(source) {
50
+ assert(source instanceof Uint8Array, 'Expected source to be a Uint8Array.');
51
+ const bytes = new Uint8Array(source);
52
+ const wasmModule = await WebAssembly.compile(bytes);
53
+ // eslint-disable-next-line @typescript-eslint/no-shadow
54
+ const exports = WebAssembly.Module.exports(wasmModule);
55
+ const imports = WebAssembly.Module.imports(wasmModule).reduce((target, descriptor)=>{
56
+ var _target, _descriptor_module;
57
+ (_target = target)[_descriptor_module = descriptor.module] ?? (_target[_descriptor_module] = []);
58
+ target[descriptor.module].push(descriptor.name);
59
+ return target;
60
+ }, {});
61
+ // Add the WASM import as a dependency so that Webpack will watch it for
62
+ // changes.
63
+ for (const name of Object.keys(imports)){
64
+ this.addDependency(name);
65
+ }
66
+ return `
67
+ ${getImports(imports)}
68
+
69
+ const bytes = new Uint8Array(${JSON.stringify(Array.from(source))});
70
+ const module = new WebAssembly.Module(bytes);
71
+ const instance = new WebAssembly.Instance(module, {
72
+ ${getModuleImports(imports)}
73
+ });
74
+
75
+ const exports = instance.exports;
76
+ ${getExports(exports)}
77
+ `;
78
+ };
79
+ export default loader;
80
+ // By setting `raw` to `true`, we are telling Webpack to provide the source as a
81
+ // `Uint8Array` instead of converting it to a string. This allows us to avoid
82
+ // having to convert the source back to a `Uint8Array` in the loader.
83
+ export const raw = true;
25
84
 
26
85
  //# sourceMappingURL=wasm.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/webpack/loaders/wasm.ts"],"sourcesContent":["import { assert, stringToBytes } from '@metamask/utils';\n\n/**\n * A Webpack loader that inlines the WASM module as a `Uint8Array`. This makes\n * it possible to import the WASM module directly, and use it with the\n * `WebAssembly.instantiate` function.\n *\n * This is useful, because snaps are not allowed to import assets from outside\n * of their package. This loader allows you to inline the WASM module as a\n * `Uint8Array`, which can then be passed to `WebAssembly.instantiate`.\n *\n * @param source - The WASM module as a string.\n * @returns A string that exports the WASM module as a `Uint8Array`.\n * @example\n * ```ts\n * import wasm from './program.wasm';\n *\n * const { instance } = await WebAssembly.instantiate(wasm, {});\n * // Do something with the WASM module...\n * ```\n */\nexport default function loader(source: unknown) {\n assert(typeof source === 'string', 'Expected source to be a string.');\n\n const bytes = stringToBytes(source);\n return `export default new Uint8Array(${JSON.stringify(Array.from(bytes))});`;\n}\n"],"names":["assert","stringToBytes","loader","source","bytes","JSON","stringify","Array","from"],"mappings":"AAAA,SAASA,MAAM,EAAEC,aAAa,QAAQ,kBAAkB;AAExD;;;;;;;;;;;;;;;;;;CAkBC,GACD,eAAe,SAASC,OAAOC,MAAe;IAC5CH,OAAO,OAAOG,WAAW,UAAU;IAEnC,MAAMC,QAAQH,cAAcE;IAC5B,OAAO,CAAC,8BAA8B,EAAEE,KAAKC,SAAS,CAACC,MAAMC,IAAI,CAACJ,QAAQ,EAAE,CAAC;AAC/E"}
1
+ {"version":3,"sources":["../../../../src/webpack/loaders/wasm.ts"],"sourcesContent":["/* eslint-disable no-restricted-globals */\n\nimport { assert } from '@metamask/utils';\nimport type { LoaderDefinitionFunction } from 'webpack';\n\n/**\n * Get the imports code for the WASM module. This code imports each of the\n * imports from the WASM module.\n *\n * @param importMap - The import map for the WASM module.\n * @returns The imports code for the WASM module.\n */\nexport function getImports(importMap: Record<string, string[]>) {\n return Object.entries(importMap)\n .map(\n ([moduleName, exportNames]) =>\n `import { ${exportNames.join(', ')} } from ${JSON.stringify(\n moduleName,\n )};`,\n )\n .join('\\n');\n}\n\n/**\n * Get the imports code to use in `WebAssembly.Instance`. This code adds each of\n * the imports to the `imports` object.\n *\n * @param importMap - The import map for the WASM module.\n * @returns The imports code for the WASM module.\n */\nexport function getModuleImports(importMap: Record<string, string[]>) {\n return Object.entries(importMap)\n .map(\n ([moduleName, exportNames]) =>\n `${JSON.stringify(moduleName)}: { ${exportNames.join(', ')} },`,\n )\n .join('\\n');\n}\n\n/**\n * Get the exports code for the WASM module. This code exports each of the\n * exports from the WASM module as a variable. This function assumes that the\n * exports are available in a variable named `exports`.\n *\n * @param descriptors - The export descriptors from the WASM module.\n * @returns The exports code for the WASM module.\n */\nexport function getExports(descriptors: WebAssembly.ModuleExportDescriptor[]) {\n return descriptors\n .map((descriptor) => {\n if (descriptor.name === 'default') {\n return `export default exports[${JSON.stringify(descriptor.name)}];`;\n }\n\n return `export const ${descriptor.name} = exports[${JSON.stringify(\n descriptor.name,\n )}];`;\n })\n .join('\\n');\n}\n\n/**\n * A Webpack loader that synchronously loads the WASM module. This makes it\n * possible to import the WASM module directly.\n *\n * @param source - The WASM module as `Uint8Array`.\n * @returns The WASM module as a JavaScript string.\n * @example\n * ```ts\n * import * as wasm from './program.wasm';\n *\n * // Do something with the WASM module...\n * ```\n */\n// Note: This function needs to be defined like this, so that Webpack can bind\n// `this` to the loader context, and TypeScript can infer the type of `this`.\nconst loader: LoaderDefinitionFunction = async function loader(\n source: unknown,\n) {\n assert(source instanceof Uint8Array, 'Expected source to be a Uint8Array.');\n\n const bytes = new Uint8Array(source);\n const wasmModule = await WebAssembly.compile(bytes);\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n const exports = WebAssembly.Module.exports(wasmModule);\n const imports = WebAssembly.Module.imports(wasmModule).reduce<\n Record<string, string[]>\n >((target, descriptor) => {\n target[descriptor.module] ??= [];\n target[descriptor.module].push(descriptor.name);\n\n return target;\n }, {});\n\n // Add the WASM import as a dependency so that Webpack will watch it for\n // changes.\n for (const name of Object.keys(imports)) {\n this.addDependency(name);\n }\n\n return `\n ${getImports(imports)}\n\n const bytes = new Uint8Array(${JSON.stringify(Array.from(source))});\n const module = new WebAssembly.Module(bytes);\n const instance = new WebAssembly.Instance(module, {\n ${getModuleImports(imports)}\n });\n\n const exports = instance.exports;\n ${getExports(exports)}\n `;\n};\n\nexport default loader;\n\n// By setting `raw` to `true`, we are telling Webpack to provide the source as a\n// `Uint8Array` instead of converting it to a string. This allows us to avoid\n// having to convert the source back to a `Uint8Array` in the loader.\nexport const raw = true;\n"],"names":["assert","getImports","importMap","Object","entries","map","moduleName","exportNames","join","JSON","stringify","getModuleImports","getExports","descriptors","descriptor","name","loader","source","Uint8Array","bytes","wasmModule","WebAssembly","compile","exports","Module","imports","reduce","target","module","push","keys","addDependency","Array","from","raw"],"mappings":"AAAA,wCAAwC,GAExC,SAASA,MAAM,QAAQ,kBAAkB;AAGzC;;;;;;CAMC,GACD,OAAO,SAASC,WAAWC,SAAmC;IAC5D,OAAOC,OAAOC,OAAO,CAACF,WACnBG,GAAG,CACF,CAAC,CAACC,YAAYC,YAAY,GACxB,CAAC,SAAS,EAAEA,YAAYC,IAAI,CAAC,MAAM,QAAQ,EAAEC,KAAKC,SAAS,CACzDJ,YACA,CAAC,CAAC,EAEPE,IAAI,CAAC;AACV;AAEA;;;;;;CAMC,GACD,OAAO,SAASG,iBAAiBT,SAAmC;IAClE,OAAOC,OAAOC,OAAO,CAACF,WACnBG,GAAG,CACF,CAAC,CAACC,YAAYC,YAAY,GACxB,CAAC,EAAEE,KAAKC,SAAS,CAACJ,YAAY,IAAI,EAAEC,YAAYC,IAAI,CAAC,MAAM,GAAG,CAAC,EAElEA,IAAI,CAAC;AACV;AAEA;;;;;;;CAOC,GACD,OAAO,SAASI,WAAWC,WAAiD;IAC1E,OAAOA,YACJR,GAAG,CAAC,CAACS;QACJ,IAAIA,WAAWC,IAAI,KAAK,WAAW;YACjC,OAAO,CAAC,uBAAuB,EAAEN,KAAKC,SAAS,CAACI,WAAWC,IAAI,EAAE,EAAE,CAAC;QACtE;QAEA,OAAO,CAAC,aAAa,EAAED,WAAWC,IAAI,CAAC,WAAW,EAAEN,KAAKC,SAAS,CAChEI,WAAWC,IAAI,EACf,EAAE,CAAC;IACP,GACCP,IAAI,CAAC;AACV;AAEA;;;;;;;;;;;;CAYC,GACD,8EAA8E;AAC9E,6EAA6E;AAC7E,MAAMQ,SAAmC,eAAeA,OACtDC,MAAe;IAEfjB,OAAOiB,kBAAkBC,YAAY;IAErC,MAAMC,QAAQ,IAAID,WAAWD;IAC7B,MAAMG,aAAa,MAAMC,YAAYC,OAAO,CAACH;IAE7C,wDAAwD;IACxD,MAAMI,UAAUF,YAAYG,MAAM,CAACD,OAAO,CAACH;IAC3C,MAAMK,UAAUJ,YAAYG,MAAM,CAACC,OAAO,CAACL,YAAYM,MAAM,CAE3D,CAACC,QAAQb;YACTa,SAAOb;QAAPa,CAAAA,UAAAA,OAAM,CAACb,qBAAAA,WAAWc,MAAM,CAAC,KAAzBD,OAAM,CAACb,mBAAkB,GAAK,EAAE;QAChCa,MAAM,CAACb,WAAWc,MAAM,CAAC,CAACC,IAAI,CAACf,WAAWC,IAAI;QAE9C,OAAOY;IACT,GAAG,CAAC;IAEJ,wEAAwE;IACxE,WAAW;IACX,KAAK,MAAMZ,QAAQZ,OAAO2B,IAAI,CAACL,SAAU;QACvC,IAAI,CAACM,aAAa,CAAChB;IACrB;IAEA,OAAO,CAAC;IACN,EAAEd,WAAWwB,SAAS;;iCAEO,EAAEhB,KAAKC,SAAS,CAACsB,MAAMC,IAAI,CAAChB,SAAS;;;MAGhE,EAAEN,iBAAiBc,SAAS;;;;IAI9B,EAAEb,WAAWW,SAAS;EACxB,CAAC;AACH;AAEA,eAAeP,OAAO;AAEtB,gFAAgF;AAChF,6EAA6E;AAC7E,qEAAqE;AACrE,OAAO,MAAMkB,MAAM,KAAK"}
@@ -1,20 +1,42 @@
1
+ import type { LoaderDefinitionFunction } from 'webpack';
1
2
  /**
2
- * A Webpack loader that inlines the WASM module as a `Uint8Array`. This makes
3
- * it possible to import the WASM module directly, and use it with the
4
- * `WebAssembly.instantiate` function.
3
+ * Get the imports code for the WASM module. This code imports each of the
4
+ * imports from the WASM module.
5
5
  *
6
- * This is useful, because snaps are not allowed to import assets from outside
7
- * of their package. This loader allows you to inline the WASM module as a
8
- * `Uint8Array`, which can then be passed to `WebAssembly.instantiate`.
6
+ * @param importMap - The import map for the WASM module.
7
+ * @returns The imports code for the WASM module.
8
+ */
9
+ export declare function getImports(importMap: Record<string, string[]>): string;
10
+ /**
11
+ * Get the imports code to use in `WebAssembly.Instance`. This code adds each of
12
+ * the imports to the `imports` object.
13
+ *
14
+ * @param importMap - The import map for the WASM module.
15
+ * @returns The imports code for the WASM module.
16
+ */
17
+ export declare function getModuleImports(importMap: Record<string, string[]>): string;
18
+ /**
19
+ * Get the exports code for the WASM module. This code exports each of the
20
+ * exports from the WASM module as a variable. This function assumes that the
21
+ * exports are available in a variable named `exports`.
22
+ *
23
+ * @param descriptors - The export descriptors from the WASM module.
24
+ * @returns The exports code for the WASM module.
25
+ */
26
+ export declare function getExports(descriptors: WebAssembly.ModuleExportDescriptor[]): string;
27
+ /**
28
+ * A Webpack loader that synchronously loads the WASM module. This makes it
29
+ * possible to import the WASM module directly.
9
30
  *
10
- * @param source - The WASM module as a string.
11
- * @returns A string that exports the WASM module as a `Uint8Array`.
31
+ * @param source - The WASM module as `Uint8Array`.
32
+ * @returns The WASM module as a JavaScript string.
12
33
  * @example
13
34
  * ```ts
14
- * import wasm from './program.wasm';
35
+ * import * as wasm from './program.wasm';
15
36
  *
16
- * const { instance } = await WebAssembly.instantiate(wasm, {});
17
37
  * // Do something with the WASM module...
18
38
  * ```
19
39
  */
20
- export default function loader(source: unknown): string;
40
+ declare const loader: LoaderDefinitionFunction;
41
+ export default loader;
42
+ export declare const raw = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/snaps-cli",
3
- "version": "3.0.5",
3
+ "version": "4.0.1",
4
4
  "description": "A CLI for developing MetaMask Snaps.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -54,8 +54,8 @@
54
54
  "@babel/plugin-transform-runtime": "^7.13.2",
55
55
  "@babel/preset-env": "^7.23.2",
56
56
  "@babel/preset-typescript": "^7.23.2",
57
- "@metamask/snaps-sdk": "^1.2.0",
58
- "@metamask/snaps-utils": "^5.0.0",
57
+ "@metamask/snaps-sdk": "^1.3.2",
58
+ "@metamask/snaps-utils": "^5.1.2",
59
59
  "@metamask/snaps-webpack-plugin": "^3.1.1",
60
60
  "@metamask/utils": "^8.2.1",
61
61
  "@swc/core": "1.3.78",
@@ -98,7 +98,7 @@
98
98
  },
99
99
  "devDependencies": {
100
100
  "@lavamoat/allow-scripts": "^2.5.1",
101
- "@metamask/auto-changelog": "^3.4.3",
101
+ "@metamask/auto-changelog": "^3.4.4",
102
102
  "@metamask/eslint-config": "^12.1.0",
103
103
  "@metamask/eslint-config-jest": "^12.1.0",
104
104
  "@metamask/eslint-config-nodejs": "^12.1.0",