Skip to content

Commit ae801f2

Browse files
committed
add tests and wildcards
1 parent 1f1e8d8 commit ae801f2

14 files changed

+247
-51
lines changed

lib/internal/errors.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,9 @@ E('ERR_MANIFEST_DEPENDENCY_MISSING',
10391039
E('ERR_MANIFEST_INTEGRITY_MISMATCH',
10401040
'Manifest resource %s has multiple entries but integrity lists do not match',
10411041
SyntaxError);
1042+
E('ERR_MANIFEST_INVALID_RESOURCE_FIELD',
1043+
'Manifest resource %s has invalid property value for %s',
1044+
TypeError);
10421045
E('ERR_MANIFEST_TDZ', 'Manifest initialization has not yet run', Error);
10431046
E('ERR_MANIFEST_UNKNOWN_ONERROR',
10441047
'Manifest specified unknown error behavior "%s".',

lib/internal/modules/cjs/helpers.js

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,28 @@
22

33
const { Object } = primordials;
44
const {
5-
ERR_MANIFEST_DEPENDENCY_MISSING
5+
ERR_MANIFEST_DEPENDENCY_MISSING,
6+
ERR_UNKNOWN_BUILTIN_MODULE
67
} = require('internal/errors').codes;
8+
const { NativeModule } = require('internal/bootstrap/loaders');
9+
const { getOptionValue } = require('internal/options');
10+
const experimentalModules = getOptionValue('--experimental-modules');
711

812
const { validateString } = require('internal/validators');
913
const path = require('path');
1014
const { pathToFileURL, fileURLToPath } = require('internal/url');
1115
const { URL } = require('url');
1216

17+
const debug = require('internal/util/debuglog').debuglog('module');
18+
19+
function loadNativeModule(filename, request, experimentalModules) {
20+
const mod = NativeModule.map.get(filename);
21+
if (mod && mod.canBeRequiredByUsers) {
22+
debug('load native module %s', request);
23+
return mod.compileForPublicLoader(experimentalModules);
24+
}
25+
}
26+
1327
// Invoke with makeRequireFunction(module) where |module| is the Module object
1428
// to use as the context for the require() function.
1529
// Use redirects to set up a mapping from a policy and restrict dependencies
@@ -20,23 +34,33 @@ function makeRequireFunction(mod, redirects) {
2034
if (redirects) {
2135
const { map, reaction } = redirects;
2236
require = function require(path) {
23-
if (map.has(path)) {
37+
let missing = true;
38+
if (map === true) {
39+
missing = false;
40+
} else if (map.has(path)) {
2441
const redirect = map.get(path);
2542
if (redirect === true) {
26-
return mod.require(path);
27-
} else if (redirect) {
43+
missing = false;
44+
} else if (typeof redirect === 'string') {
2845
const parsed = new URL(redirect);
2946
if (parsed.protocol === 'node:') {
30-
return mod.require(parsed.pathname);
47+
const specifier = parsed.pathname;
48+
const mod = loadNativeModule(
49+
specifier,
50+
redirect,
51+
experimentalModules);
52+
if (mod) return mod;
53+
throw new ERR_UNKNOWN_BUILTIN_MODULE(specifier);
3154
} else if (parsed.protocol === 'file:') {
3255
return mod.require(fileURLToPath(parsed));
3356
}
3457
}
3558
}
36-
reaction(new ERR_MANIFEST_DEPENDENCY_MISSING(
37-
path,
38-
mod.filename || mod.id));
39-
// In the case of log just fall back to same behavior as `true`
59+
if (missing) {
60+
reaction(new ERR_MANIFEST_DEPENDENCY_MISSING(
61+
mod.filename || mod.id,
62+
path));
63+
}
4064
return mod.require(path);
4165
};
4266
} else {
@@ -143,6 +167,7 @@ function normalizeReferrerURL(referrer) {
143167
module.exports = {
144168
addBuiltinLibsToObject,
145169
builtinLibs,
170+
loadNativeModule,
146171
makeRequireFunction,
147172
normalizeReferrerURL,
148173
stripBOM,

lib/internal/modules/cjs/loader.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const {
4040
makeRequireFunction,
4141
normalizeReferrerURL,
4242
stripBOM,
43+
loadNativeModule
4344
} = require('internal/modules/cjs/helpers');
4445
const { getOptionValue } = require('internal/options');
4546
const preserveSymlinks = getOptionValue('--preserve-symlinks');
@@ -531,11 +532,8 @@ Module._load = function(request, parent, isMain) {
531532
return cachedModule.exports;
532533
}
533534

534-
const mod = NativeModule.map.get(filename);
535-
if (mod && mod.canBeRequiredByUsers) {
536-
debug('load native module %s', request);
537-
return mod.compileForPublicLoader(experimentalModules);
538-
}
535+
const mod = loadNativeModule(filename, request, experimentalModules);
536+
if (mod) return mod;
539537

540538
// Don't call updateChildren(), Module constructor already does.
541539
const module = new Module(filename, parent);

lib/internal/modules/esm/translators.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ const {
99
StringPrototype
1010
} = primordials;
1111

12-
const { NativeModule } = require('internal/bootstrap/loaders');
1312
const {
14-
stripBOM
13+
stripBOM,
14+
loadNativeModule
1515
} = require('internal/modules/cjs/helpers');
1616
const CJSModule = require('internal/modules/cjs/loader').Module;
1717
const internalURLModule = require('internal/url');
@@ -93,11 +93,10 @@ translators.set('builtin', async function builtinStrategy(url) {
9393
debug(`Translating BuiltinModule ${url}`);
9494
// Slice 'node:' scheme
9595
const id = url.slice(5);
96-
const module = NativeModule.map.get(id);
96+
const module = loadNativeModule(id, url, true);
9797
if (!module) {
9898
throw new ERR_UNKNOWN_BUILTIN_MODULE(id);
9999
}
100-
module.compileForPublicLoader(true);
101100
return createDynamicModule(
102101
[], [...module.exportKeys, 'default'], url, (reflect) => {
103102
debug(`Loading BuiltinModule ${url}`);

lib/internal/policy/manifest.js

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const {
1414
const {
1515
ERR_MANIFEST_ASSERT_INTEGRITY,
1616
ERR_MANIFEST_INTEGRITY_MISMATCH,
17+
ERR_MANIFEST_INVALID_RESOURCE_FIELD,
1718
ERR_MANIFEST_UNKNOWN_ONERROR,
1819
} = require('internal/errors').codes;
1920
const debug = require('internal/util/debuglog').debuglog('policy');
@@ -83,41 +84,50 @@ class Manifest {
8384
if (RegExpPrototype.test(kRelativeURLStringPattern, url)) {
8485
url = new URL(url, manifestURL).href;
8586
}
86-
const integrity = manifestEntries[i][1].integrity;
87+
let integrity = manifestEntries[i][1].integrity;
88+
if (!integrity) integrity = null;
8789
if (integrity != null) {
8890
debug(`Manifest contains integrity for url ${originalURL}`);
91+
if (typeof integrity === 'string') {
92+
const sri = Object.freeze(SRI.parse(integrity));
93+
if (url in integrities) {
94+
const old = integrities[url];
95+
let mismatch = false;
8996

90-
const sri = Object.freeze(SRI.parse(integrity));
91-
if (url in integrities) {
92-
const old = integrities[url];
93-
let mismatch = false;
94-
95-
if (old.length !== sri.length) {
96-
mismatch = true;
97-
} else {
98-
compare:
99-
for (var sriI = 0; sriI < sri.length; sriI++) {
100-
for (var oldI = 0; oldI < old.length; oldI++) {
101-
if (sri[sriI].algorithm === old[oldI].algorithm &&
102-
BufferEquals(sri[sriI].value, old[oldI].value) &&
103-
sri[sriI].options === old[oldI].options) {
104-
continue compare;
97+
if (old.length !== sri.length) {
98+
mismatch = true;
99+
} else {
100+
compare:
101+
for (var sriI = 0; sriI < sri.length; sriI++) {
102+
for (var oldI = 0; oldI < old.length; oldI++) {
103+
if (sri[sriI].algorithm === old[oldI].algorithm &&
104+
BufferEquals(sri[sriI].value, old[oldI].value) &&
105+
sri[sriI].options === old[oldI].options) {
106+
continue compare;
107+
}
105108
}
109+
mismatch = true;
110+
break compare;
106111
}
107-
mismatch = true;
108-
break compare;
109112
}
110-
}
111113

112-
if (mismatch) {
113-
throw new ERR_MANIFEST_INTEGRITY_MISMATCH(url);
114+
if (mismatch) {
115+
throw new ERR_MANIFEST_INTEGRITY_MISMATCH(url);
116+
}
114117
}
118+
integrities[url] = sri;
119+
} else if (integrity === true) {
120+
integrities[url] = true;
121+
} else {
122+
throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD(url, 'integrity');
115123
}
116-
integrities[url] = sri;
117124
}
118125

119-
const dependencyMap = manifestEntries[i][1].dependencies;
120-
if (dependencyMap) {
126+
let dependencyMap = manifestEntries[i][1].dependencies;
127+
if (dependencyMap === null || dependencyMap === undefined) {
128+
dependencyMap = {};
129+
}
130+
if (typeof dependencyMap === 'object' && !Array.isArray(dependencyMap)) {
121131
dependencies[url] = new SafeMap(Object.entries(dependencyMap).map(
122132
([ from, to ]) => {
123133
if (to === true) {
@@ -131,6 +141,10 @@ class Manifest {
131141
return [from, new URL(to).href];
132142
})
133143
);
144+
} else if (dependencyMap === true) {
145+
dependencies[url] = true;
146+
} else {
147+
throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD(url, 'dependencies');
134148
}
135149
}
136150
Object.freeze(integrities);
@@ -142,11 +156,13 @@ class Manifest {
142156

143157
getRedirects(requester) {
144158
const dependencies = kDependencies.get(this);
145-
if (!dependencies[requester]) return null;
146-
return {
147-
map: dependencies[requester],
148-
reaction: kReactions.get(this)
149-
};
159+
if (dependencies && requester in dependencies) {
160+
return {
161+
map: dependencies[requester],
162+
reaction: kReactions.get(this)
163+
};
164+
}
165+
return null;
150166
}
151167

152168
assertIntegrity(url, content) {
@@ -156,6 +172,7 @@ class Manifest {
156172

157173
if (integrities && url in integrities) {
158174
const integrityEntries = integrities[url];
175+
if (integrityEntries === true) return true;
159176
// Avoid clobbered Symbol.iterator
160177
for (var i = 0; i < integrityEntries.length; i++) {
161178
const {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"resources": {
3+
"../parent.js": {
4+
"integrity": true,
5+
"dependencies": {}
6+
},
7+
"../dep.js": {
8+
"integrity": true
9+
}
10+
}
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"resources": {
3+
"../parent.js": {
4+
"integrity": true
5+
},
6+
"../dep.js": {
7+
"integrity": true
8+
}
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"resources": {
3+
"../parent.js": {
4+
"integrity": true,
5+
"dependencies": {
6+
"./dep.js": "node:util"
7+
}
8+
}
9+
}
10+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"resources": {
3+
"../parent.js": {
4+
"integrity": true,
5+
"dependencies": {
6+
"./dep.js": "../dep.js"
7+
}
8+
},
9+
"../dep.js": {
10+
"integrity": true
11+
}
12+
}
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"resources": {
3+
"../parent.js": {
4+
"integrity": true,
5+
"dependencies": {
6+
"./dep.js": "node:404"
7+
}
8+
}
9+
}
10+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"resources": {
3+
"../parent.js": {
4+
"integrity": true,
5+
"dependencies": true
6+
},
7+
"../dep.js": {
8+
"integrity": true
9+
}
10+
}
11+
}

test/fixtures/policy/parent.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
// Included in parent-policy.json
3+
require('./dep.js');

0 commit comments

Comments
 (0)