Skip to content

Commit

Permalink
add tests and wildcards
Browse files Browse the repository at this point in the history
  • Loading branch information
bmeck committed Jul 22, 2019
1 parent 1f1e8d8 commit ae801f2
Show file tree
Hide file tree
Showing 14 changed files with 247 additions and 51 deletions.
3 changes: 3 additions & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,9 @@ E('ERR_MANIFEST_DEPENDENCY_MISSING',
E('ERR_MANIFEST_INTEGRITY_MISMATCH',
'Manifest resource %s has multiple entries but integrity lists do not match',
SyntaxError);
E('ERR_MANIFEST_INVALID_RESOURCE_FIELD',
'Manifest resource %s has invalid property value for %s',
TypeError);
E('ERR_MANIFEST_TDZ', 'Manifest initialization has not yet run', Error);
E('ERR_MANIFEST_UNKNOWN_ONERROR',
'Manifest specified unknown error behavior "%s".',
Expand Down
43 changes: 34 additions & 9 deletions lib/internal/modules/cjs/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,28 @@

const { Object } = primordials;
const {
ERR_MANIFEST_DEPENDENCY_MISSING
ERR_MANIFEST_DEPENDENCY_MISSING,
ERR_UNKNOWN_BUILTIN_MODULE
} = require('internal/errors').codes;
const { NativeModule } = require('internal/bootstrap/loaders');
const { getOptionValue } = require('internal/options');
const experimentalModules = getOptionValue('--experimental-modules');

const { validateString } = require('internal/validators');
const path = require('path');
const { pathToFileURL, fileURLToPath } = require('internal/url');
const { URL } = require('url');

const debug = require('internal/util/debuglog').debuglog('module');

function loadNativeModule(filename, request, experimentalModules) {
const mod = NativeModule.map.get(filename);
if (mod && mod.canBeRequiredByUsers) {
debug('load native module %s', request);
return mod.compileForPublicLoader(experimentalModules);
}
}

// Invoke with makeRequireFunction(module) where |module| is the Module object
// to use as the context for the require() function.
// Use redirects to set up a mapping from a policy and restrict dependencies
Expand All @@ -20,23 +34,33 @@ function makeRequireFunction(mod, redirects) {
if (redirects) {
const { map, reaction } = redirects;
require = function require(path) {
if (map.has(path)) {
let missing = true;
if (map === true) {
missing = false;
} else if (map.has(path)) {
const redirect = map.get(path);
if (redirect === true) {
return mod.require(path);
} else if (redirect) {
missing = false;
} else if (typeof redirect === 'string') {
const parsed = new URL(redirect);
if (parsed.protocol === 'node:') {
return mod.require(parsed.pathname);
const specifier = parsed.pathname;
const mod = loadNativeModule(
specifier,
redirect,
experimentalModules);
if (mod) return mod;
throw new ERR_UNKNOWN_BUILTIN_MODULE(specifier);
} else if (parsed.protocol === 'file:') {
return mod.require(fileURLToPath(parsed));
}
}
}
reaction(new ERR_MANIFEST_DEPENDENCY_MISSING(
path,
mod.filename || mod.id));
// In the case of log just fall back to same behavior as `true`
if (missing) {
reaction(new ERR_MANIFEST_DEPENDENCY_MISSING(
mod.filename || mod.id,
path));
}
return mod.require(path);
};
} else {
Expand Down Expand Up @@ -143,6 +167,7 @@ function normalizeReferrerURL(referrer) {
module.exports = {
addBuiltinLibsToObject,
builtinLibs,
loadNativeModule,
makeRequireFunction,
normalizeReferrerURL,
stripBOM,
Expand Down
8 changes: 3 additions & 5 deletions lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const {
makeRequireFunction,
normalizeReferrerURL,
stripBOM,
loadNativeModule
} = require('internal/modules/cjs/helpers');
const { getOptionValue } = require('internal/options');
const preserveSymlinks = getOptionValue('--preserve-symlinks');
Expand Down Expand Up @@ -531,11 +532,8 @@ Module._load = function(request, parent, isMain) {
return cachedModule.exports;
}

const mod = NativeModule.map.get(filename);
if (mod && mod.canBeRequiredByUsers) {
debug('load native module %s', request);
return mod.compileForPublicLoader(experimentalModules);
}
const mod = loadNativeModule(filename, request, experimentalModules);
if (mod) return mod;

// Don't call updateChildren(), Module constructor already does.
const module = new Module(filename, parent);
Expand Down
7 changes: 3 additions & 4 deletions lib/internal/modules/esm/translators.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ const {
StringPrototype
} = primordials;

const { NativeModule } = require('internal/bootstrap/loaders');
const {
stripBOM
stripBOM,
loadNativeModule
} = require('internal/modules/cjs/helpers');
const CJSModule = require('internal/modules/cjs/loader').Module;
const internalURLModule = require('internal/url');
Expand Down Expand Up @@ -93,11 +93,10 @@ translators.set('builtin', async function builtinStrategy(url) {
debug(`Translating BuiltinModule ${url}`);
// Slice 'node:' scheme
const id = url.slice(5);
const module = NativeModule.map.get(id);
const module = loadNativeModule(id, url, true);
if (!module) {
throw new ERR_UNKNOWN_BUILTIN_MODULE(id);
}
module.compileForPublicLoader(true);
return createDynamicModule(
[], [...module.exportKeys, 'default'], url, (reflect) => {
debug(`Loading BuiltinModule ${url}`);
Expand Down
75 changes: 46 additions & 29 deletions lib/internal/policy/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const {
const {
ERR_MANIFEST_ASSERT_INTEGRITY,
ERR_MANIFEST_INTEGRITY_MISMATCH,
ERR_MANIFEST_INVALID_RESOURCE_FIELD,
ERR_MANIFEST_UNKNOWN_ONERROR,
} = require('internal/errors').codes;
const debug = require('internal/util/debuglog').debuglog('policy');
Expand Down Expand Up @@ -83,41 +84,50 @@ class Manifest {
if (RegExpPrototype.test(kRelativeURLStringPattern, url)) {
url = new URL(url, manifestURL).href;
}
const integrity = manifestEntries[i][1].integrity;
let integrity = manifestEntries[i][1].integrity;
if (!integrity) integrity = null;
if (integrity != null) {
debug(`Manifest contains integrity for url ${originalURL}`);
if (typeof integrity === 'string') {
const sri = Object.freeze(SRI.parse(integrity));
if (url in integrities) {
const old = integrities[url];
let mismatch = false;

const sri = Object.freeze(SRI.parse(integrity));
if (url in integrities) {
const old = integrities[url];
let mismatch = false;

if (old.length !== sri.length) {
mismatch = true;
} else {
compare:
for (var sriI = 0; sriI < sri.length; sriI++) {
for (var oldI = 0; oldI < old.length; oldI++) {
if (sri[sriI].algorithm === old[oldI].algorithm &&
BufferEquals(sri[sriI].value, old[oldI].value) &&
sri[sriI].options === old[oldI].options) {
continue compare;
if (old.length !== sri.length) {
mismatch = true;
} else {
compare:
for (var sriI = 0; sriI < sri.length; sriI++) {
for (var oldI = 0; oldI < old.length; oldI++) {
if (sri[sriI].algorithm === old[oldI].algorithm &&
BufferEquals(sri[sriI].value, old[oldI].value) &&
sri[sriI].options === old[oldI].options) {
continue compare;
}
}
mismatch = true;
break compare;
}
mismatch = true;
break compare;
}
}

if (mismatch) {
throw new ERR_MANIFEST_INTEGRITY_MISMATCH(url);
if (mismatch) {
throw new ERR_MANIFEST_INTEGRITY_MISMATCH(url);
}
}
integrities[url] = sri;
} else if (integrity === true) {
integrities[url] = true;
} else {
throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD(url, 'integrity');
}
integrities[url] = sri;
}

const dependencyMap = manifestEntries[i][1].dependencies;
if (dependencyMap) {
let dependencyMap = manifestEntries[i][1].dependencies;
if (dependencyMap === null || dependencyMap === undefined) {
dependencyMap = {};
}
if (typeof dependencyMap === 'object' && !Array.isArray(dependencyMap)) {
dependencies[url] = new SafeMap(Object.entries(dependencyMap).map(
([ from, to ]) => {
if (to === true) {
Expand All @@ -131,6 +141,10 @@ class Manifest {
return [from, new URL(to).href];
})
);
} else if (dependencyMap === true) {
dependencies[url] = true;
} else {
throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD(url, 'dependencies');
}
}
Object.freeze(integrities);
Expand All @@ -142,11 +156,13 @@ class Manifest {

getRedirects(requester) {
const dependencies = kDependencies.get(this);
if (!dependencies[requester]) return null;
return {
map: dependencies[requester],
reaction: kReactions.get(this)
};
if (dependencies && requester in dependencies) {
return {
map: dependencies[requester],
reaction: kReactions.get(this)
};
}
return null;
}

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

if (integrities && url in integrities) {
const integrityEntries = integrities[url];
if (integrityEntries === true) return true;
// Avoid clobbered Symbol.iterator
for (var i = 0; i < integrityEntries.length; i++) {
const {
Expand Down
11 changes: 11 additions & 0 deletions test/fixtures/policy/dependencies/dependencies-empty-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"resources": {
"../parent.js": {
"integrity": true,
"dependencies": {}
},
"../dep.js": {
"integrity": true
}
}
}
10 changes: 10 additions & 0 deletions test/fixtures/policy/dependencies/dependencies-missing-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"resources": {
"../parent.js": {
"integrity": true
},
"../dep.js": {
"integrity": true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"resources": {
"../parent.js": {
"integrity": true,
"dependencies": {
"./dep.js": "node:util"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"resources": {
"../parent.js": {
"integrity": true,
"dependencies": {
"./dep.js": "../dep.js"
}
},
"../dep.js": {
"integrity": true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"resources": {
"../parent.js": {
"integrity": true,
"dependencies": {
"./dep.js": "node:404"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"resources": {
"../parent.js": {
"integrity": true,
"dependencies": true
},
"../dep.js": {
"integrity": true
}
}
}
3 changes: 3 additions & 0 deletions test/fixtures/policy/parent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict';
// Included in parent-policy.json
require('./dep.js');
Loading

0 comments on commit ae801f2

Please sign in to comment.