Skip to content

Commit eb38365

Browse files
devsnekaduh95
authored andcommitted
lib: rework logic of stripping BOM+Shebang from commonjs
Fixes #27767 PR-URL: #27768 Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent b08601b commit eb38365

File tree

13 files changed

+100
-85
lines changed

13 files changed

+100
-85
lines changed

lib/internal/bootstrap/pre_execution.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ function initializePolicy() {
389389
}
390390

391391
function initializeCJSLoader() {
392-
require('internal/modules/cjs/loader')._initPaths();
392+
require('internal/modules/cjs/loader').Module._initPaths();
393393
}
394394

395395
function initializeESMLoader() {
@@ -438,7 +438,9 @@ function loadPreloadModules() {
438438
const preloadModules = getOptionValue('--require');
439439
if (preloadModules && preloadModules.length > 0) {
440440
const {
441-
_preloadModules
441+
Module: {
442+
_preloadModules
443+
},
442444
} = require('internal/modules/cjs/loader');
443445
_preloadModules(preloadModules);
444446
}

lib/internal/main/check_syntax.js

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ const {
1313

1414
const { pathToFileURL } = require('url');
1515

16-
const vm = require('vm');
1716
const {
18-
stripShebang, stripBOM
17+
stripShebangOrBOM,
1918
} = require('internal/modules/cjs/helpers');
2019

2120
const {
22-
_resolveFilename: resolveCJSModuleName,
23-
wrap: wrapCJSModule
21+
Module: {
22+
_resolveFilename: resolveCJSModuleName,
23+
},
24+
wrapSafe,
2425
} = require('internal/modules/cjs/loader');
2526

2627
// TODO(joyeecheung): not every one of these are necessary
@@ -49,9 +50,6 @@ if (process.argv[1] && process.argv[1] !== '-') {
4950
}
5051

5152
function checkSyntax(source, filename) {
52-
// Remove Shebang.
53-
source = stripShebang(source);
54-
5553
const { getOptionValue } = require('internal/options');
5654
const experimentalModules = getOptionValue('--experimental-modules');
5755
if (experimentalModules) {
@@ -70,10 +68,5 @@ function checkSyntax(source, filename) {
7068
}
7169
}
7270

73-
// Remove BOM.
74-
source = stripBOM(source);
75-
// Wrap it.
76-
source = wrapCJSModule(source);
77-
// Compile the script, this will throw if it fails.
78-
new vm.Script(source, { displayErrors: true, filename });
71+
wrapSafe(filename, stripShebangOrBOM(source));
7972
}

lib/internal/main/run_main_module.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const {
66

77
prepareMainThreadExecution(true);
88

9-
const CJSModule = require('internal/modules/cjs/loader');
9+
const CJSModule = require('internal/modules/cjs/loader').Module;
1010

1111
markBootstrapComplete();
1212

lib/internal/modules/cjs/helpers.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,17 @@ function stripShebang(content) {
131131
return content;
132132
}
133133

134+
// Strip either the shebang or UTF BOM of a file.
135+
// Note that this only processes one. If both occur in
136+
// either order, the one that comes second is not
137+
// significant.
138+
function stripShebangOrBOM(content) {
139+
if (content.charCodeAt(0) === 0xFEFF) {
140+
return content.slice(1);
141+
}
142+
return stripShebang(content);
143+
}
144+
134145
const builtinLibs = [
135146
'assert', 'async_hooks', 'buffer', 'child_process', 'cluster', 'crypto',
136147
'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'http2', 'https', 'net',
@@ -197,5 +208,6 @@ module.exports = {
197208
makeRequireFunction,
198209
normalizeReferrerURL,
199210
stripBOM,
200-
stripShebang
211+
stripShebang,
212+
stripShebangOrBOM,
201213
};

lib/internal/modules/cjs/loader.js

Lines changed: 56 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ const {
5151
makeRequireFunction,
5252
normalizeReferrerURL,
5353
stripBOM,
54-
stripShebang,
55-
loadNativeModule
54+
stripShebangOrBOM,
5655
} = require('internal/modules/cjs/helpers');
5756
const { getOptionValue } = require('internal/options');
5857
const enableSourceMaps = getOptionValue('--enable-source-maps');
@@ -73,7 +72,7 @@ const { validateString } = require('internal/validators');
7372
const pendingDeprecation = getOptionValue('--pending-deprecation');
7473
const experimentalExports = getOptionValue('--experimental-exports');
7574

76-
module.exports = Module;
75+
module.exports = { wrapSafe, Module };
7776

7877
let asyncESM, ModuleJob, ModuleWrap, kInstantiated;
7978

@@ -857,26 +856,10 @@ Module.prototype.require = function(id) {
857856
let resolvedArgv;
858857
let hasPausedEntry = false;
859858

860-
// Run the file contents in the correct scope or sandbox. Expose
861-
// the correct helper variables (require, module, exports) to
862-
// the file.
863-
// Returns exception, if any.
864-
Module.prototype._compile = function(content, filename) {
865-
let moduleURL;
866-
let redirects;
867-
if (manifest) {
868-
moduleURL = pathToFileURL(filename);
869-
redirects = manifest.getRedirector(moduleURL);
870-
manifest.assertIntegrity(moduleURL, content);
871-
}
872-
873-
content = stripShebang(content);
874-
maybeCacheSourceMap(filename, content, this);
875-
876-
let compiledWrapper;
859+
function wrapSafe(filename, content) {
877860
if (patched) {
878861
const wrapper = Module.wrap(content);
879-
compiledWrapper = vm.runInThisContext(wrapper, {
862+
return vm.runInThisContext(wrapper, {
880863
filename,
881864
lineOffset: 0,
882865
displayErrors: true,
@@ -885,46 +868,61 @@ Module.prototype._compile = function(content, filename) {
885868
return loader.import(specifier, normalizeReferrerURL(filename));
886869
} : undefined,
887870
});
888-
} else {
889-
let compiled;
890-
try {
891-
compiled = compileFunction(
892-
content,
893-
filename,
894-
0,
895-
0,
896-
undefined,
897-
false,
898-
undefined,
899-
[],
900-
[
901-
'exports',
902-
'require',
903-
'module',
904-
'__filename',
905-
'__dirname',
906-
]
907-
);
908-
} catch (err) {
909-
if (experimentalModules) {
910-
enrichCJSError(err);
871+
}
872+
873+
let compiledWrapper;
874+
try {
875+
compiledWrapper = compileFunction(
876+
content,
877+
filename,
878+
0,
879+
0,
880+
undefined,
881+
false,
882+
undefined,
883+
[],
884+
[
885+
'exports',
886+
'require',
887+
'module',
888+
'__filename',
889+
'__dirname',
890+
]
891+
);
892+
} catch (err) {
893+
enrichCJSError(err);
894+
throw err;
895+
}
896+
897+
if (experimentalModules) {
898+
const { callbackMap } = internalBinding('module_wrap');
899+
callbackMap.set(compiledWrapper, {
900+
importModuleDynamically: async (specifier) => {
901+
const loader = await asyncESM.loaderPromise;
902+
return loader.import(specifier, normalizeReferrerURL(filename));
911903
}
912-
throw err;
913-
}
904+
});
905+
}
914906

915-
if (experimentalModules) {
916-
const { callbackMap } = internalBinding('module_wrap');
917-
callbackMap.set(compiled.cacheKey, {
918-
importModuleDynamically: async (specifier) => {
919-
const loader = await asyncESM.loaderPromise;
920-
return loader.import(specifier, normalizeReferrerURL(filename));
921-
}
922-
});
923-
}
924-
compiledWrapper = compiled.function;
907+
return compiledWrapper;
908+
}
909+
910+
// Run the file contents in the correct scope or sandbox. Expose
911+
// the correct helper variables (require, module, exports) to
912+
// the file.
913+
// Returns exception, if any.
914+
Module.prototype._compile = function(content, filename) {
915+
if (manifest) {
916+
const moduleURL = pathToFileURL(filename);
917+
manifest.assertIntegrity(moduleURL, content);
925918
}
926919

927-
let inspectorWrapper = null;
920+
// Strip after manifest integrity check
921+
content = stripShebangOrBOM(content);
922+
923+
const compiledWrapper = wrapSafe(filename, content);
924+
925+
var inspectorWrapper = null;
928926
if (getOptionValue('--inspect-brk') && process._eval == null) {
929927
if (!resolvedArgv) {
930928
// We enter the repl if we're not given a filename argument.
@@ -988,7 +986,7 @@ Module._extensions['.js'] = function(module, filename) {
988986
}
989987
}
990988
const content = fs.readFileSync(filename, 'utf8');
991-
module._compile(stripBOM(content), filename);
989+
module._compile(content, filename);
992990
};
993991

994992

lib/internal/modules/esm/translators.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@ const {
1212
const { Buffer } = require('buffer');
1313

1414
const {
15-
stripShebang,
16-
stripBOM,
17-
loadNativeModule
15+
stripBOM
1816
} = require('internal/modules/cjs/helpers');
19-
const CJSModule = require('internal/modules/cjs/loader');
17+
const CJSModule = require('internal/modules/cjs/loader').Module;
2018
const internalURLModule = require('internal/url');
2119
const createDynamicModule = require(
2220
'internal/modules/esm/create_dynamic_module');
@@ -80,8 +78,9 @@ translators.set('module', async function moduleStrategy(url) {
8078
const source = `${await getSource(url)}`;
8179
maybeCacheSourceMap(url, source);
8280
debug(`Translating StandardModule ${url}`);
83-
const module = new ModuleWrap(stripShebang(source), url);
84-
moduleWrap.callbackMap.set(module, {
81+
const { ModuleWrap, callbackMap } = internalBinding('module_wrap');
82+
const module = new ModuleWrap(source, url);
83+
callbackMap.set(module, {
8584
initializeImportMeta,
8685
importModuleDynamically,
8786
});

lib/internal/process/execution.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function evalModule(source, print) {
5353
}
5454

5555
function evalScript(name, body, breakFirstLine, print) {
56-
const CJSModule = require('internal/modules/cjs/loader');
56+
const CJSModule = require('internal/modules/cjs/loader').Module;
5757
const { kVmBreakFirstLineSymbol } = require('internal/util');
5858

5959
const cwd = tryGetCwd();

lib/internal/util/inspector.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function sendInspectorCommand(cb, onError) {
2424
function installConsoleExtensions(commandLineApi) {
2525
if (commandLineApi.require) { return; }
2626
const { tryGetCwd } = require('internal/process/execution');
27-
const CJSModule = require('internal/modules/cjs/loader');
27+
const CJSModule = require('internal/modules/cjs/loader').Module;
2828
const { makeRequireFunction } = require('internal/modules/cjs/helpers');
2929
const consoleAPIModule = new CJSModule('<inspector console>');
3030
const cwd = tryGetCwd();

lib/module.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
'use strict';
22

3-
module.exports = require('internal/modules/cjs/loader');
3+
module.exports = require('internal/modules/cjs/loader').Module;

lib/repl.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ const path = require('path');
6565
const fs = require('fs');
6666
const { Interface } = require('readline');
6767
const { Console } = require('console');
68-
const CJSModule = require('internal/modules/cjs/loader');
68+
const CJSModule = require('internal/modules/cjs/loader').Module;
6969
const domain = require('domain');
7070
const debug = require('internal/util/debuglog').debuglog('repl');
7171
const {

0 commit comments

Comments
 (0)