9
9
StringPrototype
10
10
} = primordials ;
11
11
12
+ const { Buffer } = require ( 'buffer' ) ;
13
+
12
14
const {
13
15
stripShebang,
14
16
stripBOM,
@@ -24,6 +26,8 @@ const { debuglog } = require('internal/util/debuglog');
24
26
const { promisify } = require ( 'internal/util' ) ;
25
27
const esmLoader = require ( 'internal/process/esm_loader' ) ;
26
28
const {
29
+ ERR_INVALID_URL ,
30
+ ERR_INVALID_URL_SCHEME ,
27
31
ERR_UNKNOWN_BUILTIN_MODULE
28
32
} = require ( 'internal/errors' ) . codes ;
29
33
const readFileAsync = promisify ( fs . readFile ) ;
@@ -34,6 +38,31 @@ const debug = debuglog('esm');
34
38
const translators = new SafeMap ( ) ;
35
39
exports . translators = translators ;
36
40
41
+ const DATA_URL_PATTERN = / ^ [ ^ / ] + \/ [ ^ , ; ] + ( ; b a s e 6 4 ) ? , ( [ \s \S ] * ) $ / ;
42
+ function getSource ( url ) {
43
+ const parsed = new URL ( url ) ;
44
+ if ( parsed . protocol === 'file:' ) {
45
+ return readFileAsync ( parsed ) ;
46
+ } else if ( parsed . protocol === 'data:' ) {
47
+ const match = DATA_URL_PATTERN . exec ( parsed . pathname ) ;
48
+ if ( ! match ) {
49
+ throw new ERR_INVALID_URL ( url ) ;
50
+ }
51
+ const [ , base64 , body ] = match ;
52
+ return Buffer . from ( body , base64 ? 'base64' : 'utf8' ) ;
53
+ } else {
54
+ throw new ERR_INVALID_URL_SCHEME ( [ 'file' , 'data' ] ) ;
55
+ }
56
+ }
57
+
58
+ function errPath ( url ) {
59
+ const parsed = new URL ( url ) ;
60
+ if ( parsed . protocol === 'file:' ) {
61
+ return fileURLToPath ( parsed ) ;
62
+ }
63
+ return url ;
64
+ }
65
+
37
66
function initializeImportMeta ( meta , { url } ) {
38
67
meta . url = url ;
39
68
}
@@ -45,7 +74,7 @@ async function importModuleDynamically(specifier, { url }) {
45
74
46
75
// Strategy for loading a standard JavaScript module
47
76
translators . set ( 'module' , async function moduleStrategy ( url ) {
48
- const source = `${ await readFileAsync ( new URL ( url ) ) } ` ;
77
+ const source = `${ await getSource ( url ) } ` ;
49
78
debug ( `Translating StandardModule ${ url } ` ) ;
50
79
const { ModuleWrap, callbackMap } = internalBinding ( 'module_wrap' ) ;
51
80
const module = new ModuleWrap ( stripShebang ( source ) , url ) ;
@@ -112,26 +141,32 @@ translators.set('builtin', async function builtinStrategy(url) {
112
141
translators . set ( 'json' , async function jsonStrategy ( url ) {
113
142
debug ( `Translating JSONModule ${ url } ` ) ;
114
143
debug ( `Loading JSONModule ${ url } ` ) ;
115
- const pathname = fileURLToPath ( url ) ;
116
- const modulePath = isWindows ?
117
- StringPrototype . replace ( pathname , winSepRegEx , '\\' ) : pathname ;
118
- let module = CJSModule . _cache [ modulePath ] ;
119
- if ( module && module . loaded ) {
120
- const exports = module . exports ;
121
- return createDynamicModule ( [ ] , [ 'default' ] , url , ( reflect ) => {
122
- reflect . exports . default . set ( exports ) ;
123
- } ) ;
144
+ const pathname = url . startsWith ( 'file:' ) ? fileURLToPath ( url ) : null ;
145
+ let modulePath ;
146
+ let module ;
147
+ if ( pathname ) {
148
+ modulePath = isWindows ?
149
+ StringPrototype . replace ( pathname , winSepRegEx , '\\' ) : pathname ;
150
+ module = CJSModule . _cache [ modulePath ] ;
151
+ if ( module && module . loaded ) {
152
+ const exports = module . exports ;
153
+ return createDynamicModule ( [ ] , [ 'default' ] , url , ( reflect ) => {
154
+ reflect . exports . default . set ( exports ) ;
155
+ } ) ;
156
+ }
124
157
}
125
- const content = await readFileAsync ( pathname , 'utf-8' ) ;
126
- // A require call could have been called on the same file during loading and
127
- // that resolves synchronously. To make sure we always return the identical
128
- // export, we have to check again if the module already exists or not.
129
- module = CJSModule . _cache [ modulePath ] ;
130
- if ( module && module . loaded ) {
131
- const exports = module . exports ;
132
- return createDynamicModule ( [ 'default' ] , url , ( reflect ) => {
133
- reflect . exports . default . set ( exports ) ;
134
- } ) ;
158
+ const content = `${ await getSource ( url ) } ` ;
159
+ if ( pathname ) {
160
+ // A require call could have been called on the same file during loading and
161
+ // that resolves synchronously. To make sure we always return the identical
162
+ // export, we have to check again if the module already exists or not.
163
+ module = CJSModule . _cache [ modulePath ] ;
164
+ if ( module && module . loaded ) {
165
+ const exports = module . exports ;
166
+ return createDynamicModule ( [ 'default' ] , url , ( reflect ) => {
167
+ reflect . exports . default . set ( exports ) ;
168
+ } ) ;
169
+ }
135
170
}
136
171
try {
137
172
const exports = JsonParse ( stripBOM ( content ) ) ;
@@ -144,10 +179,12 @@ translators.set('json', async function jsonStrategy(url) {
144
179
// parse error instead of just manipulating the original error message.
145
180
// That would allow to add further properties and maybe additional
146
181
// debugging information.
147
- err . message = pathname + ': ' + err . message ;
182
+ err . message = errPath ( url ) + ': ' + err . message ;
148
183
throw err ;
149
184
}
150
- CJSModule . _cache [ modulePath ] = module ;
185
+ if ( pathname ) {
186
+ CJSModule . _cache [ modulePath ] = module ;
187
+ }
151
188
return createDynamicModule ( [ ] , [ 'default' ] , url , ( reflect ) => {
152
189
debug ( `Parsing JSONModule ${ url } ` ) ;
153
190
reflect . exports . default . set ( module . exports ) ;
@@ -156,14 +193,13 @@ translators.set('json', async function jsonStrategy(url) {
156
193
157
194
// Strategy for loading a wasm module
158
195
translators . set ( 'wasm' , async function ( url ) {
159
- const pathname = fileURLToPath ( url ) ;
160
- const buffer = await readFileAsync ( pathname ) ;
196
+ const buffer = await getSource ( url ) ;
161
197
debug ( `Translating WASMModule ${ url } ` ) ;
162
198
let compiled ;
163
199
try {
164
200
compiled = await WebAssembly . compile ( buffer ) ;
165
201
} catch ( err ) {
166
- err . message = pathname + ': ' + err . message ;
202
+ err . message = errPath ( url ) + ': ' + err . message ;
167
203
throw err ;
168
204
}
169
205
0 commit comments