Skip to content

Commit d78a9da

Browse files
committed
module: support Wasm without file extension within module scope
1 parent 500ea04 commit d78a9da

File tree

5 files changed

+70
-1
lines changed

5 files changed

+70
-1
lines changed

lib/internal/modules/esm/formats.js

+23
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
const {
44
RegExpPrototypeExec,
5+
Uint8Array,
56
} = primordials;
67
const { getOptionValue } = require('internal/options');
78

9+
const { closeSync, openSync, readSync } = require('fs');
10+
811
const experimentalWasmModules = getOptionValue('--experimental-wasm-modules');
912

1013
const extensionFormatMap = {
@@ -35,7 +38,27 @@ function mimeToFormat(mime) {
3538
return null;
3639
}
3740

41+
function guessExtensionlessModule(url) {
42+
if (!experimentalWasmModules)
43+
return 'module';
44+
45+
const magic = new Uint8Array(4);
46+
let fd;
47+
try {
48+
fd = openSync(url);
49+
readSync(fd, magic);
50+
if (magic[0] === 0x00 && magic[1] === 0x61 && magic[2] === 0x73 && magic[3] === 0x6d) {
51+
return 'wasm';
52+
}
53+
} finally {
54+
if (fd) closeSync(fd);
55+
}
56+
57+
return 'module';
58+
}
59+
3860
module.exports = {
3961
extensionFormatMap,
62+
guessExtensionlessModule,
4063
mimeToFormat,
4164
};

lib/internal/modules/esm/get_format.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const {
1010
const { getOptionValue } = require('internal/options');
1111
const {
1212
extensionFormatMap,
13+
guessExtensionlessModule,
1314
mimeToFormat,
1415
} = require('internal/modules/esm/formats');
1516

@@ -73,10 +74,17 @@ function extname(url) {
7374
*/
7475
function getFileProtocolModuleFormat(url, context, ignoreErrors) {
7576
const ext = extname(url);
76-
if (ext === '.js' || ext === '') {
77+
if (ext === '.js') {
7778
return getPackageType(url) === 'module' ? 'module' : 'commonjs';
7879
}
7980

81+
if (ext === '') {
82+
if (getPackageType(url) === 'module') {
83+
return guessExtensionlessModule(url);
84+
}
85+
return 'commonjs';
86+
}
87+
8088
const format = extensionFormatMap[ext];
8189
if (format) return format;
8290

Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { strictEqual } from 'assert';
2+
3+
export function jsFn () {
4+
state = 'WASM JS Function Executed';
5+
return 42;
6+
}
7+
8+
export let state = 'JS Function Executed';
9+
10+
export function jsInitFn () {
11+
strictEqual(state, 'JS Function Executed');
12+
state = 'WASM Start Executed';
13+
}

test/parallel/test-esm-wasm.mjs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Flags: --experimental-wasm-modules
2+
import { mustCall } from '../common/index.mjs';
3+
import { path } from '../common/fixtures.mjs';
4+
import { strictEqual } from 'assert';
5+
import { spawn } from 'child_process';
6+
7+
{
8+
const entry = path('/es-modules/package-type-module/noext-wasm');
9+
10+
// Run a module that does not have extension.
11+
// This is to ensure that "type": "module" applies to extensionless files.
12+
13+
const child = spawn(process.execPath, ['--experimental-wasm-modules', entry]);
14+
15+
let stdout = '';
16+
child.stdout.setEncoding('utf8');
17+
child.stdout.on('data', (data) => {
18+
stdout += data;
19+
});
20+
child.on('close', mustCall((code, signal) => {
21+
strictEqual(code, 0);
22+
strictEqual(signal, null);
23+
strictEqual(stdout, '');
24+
}));
25+
}

0 commit comments

Comments
 (0)