Skip to content

Commit

Permalink
lib: move setupAllowedFlags() into per_thread.js
Browse files Browse the repository at this point in the history
Because most of its code (the getter) has nothing to do with
the actual bootstrapping and it is run per-thread.

PR-URL: #24704
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Christopher Hiller <boneskull@boneskull.com>
  • Loading branch information
joyeecheung authored and BridgeAR committed Dec 5, 2018
1 parent 0894899 commit d77cf92
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 124 deletions.
125 changes: 1 addition & 124 deletions lib/internal/bootstrap/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@

perf.markMilestone(NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);

setupAllowedFlags();
perThreadSetup.setupAllowedFlags();

startExecution();
}
Expand Down Expand Up @@ -739,128 +739,5 @@
new vm.Script(source, { displayErrors: true, filename });
}

function setupAllowedFlags() {
// This builds process.allowedNodeEnvironmentFlags
// from data in the config binding

const replaceUnderscoresRegex = /_/g;
const leadingDashesRegex = /^--?/;
const trailingValuesRegex = /=.*$/;

// Save references so user code does not interfere
const replace = Function.call.bind(String.prototype.replace);
const has = Function.call.bind(Set.prototype.has);
const test = Function.call.bind(RegExp.prototype.test);

const get = () => {
const {
envSettings: { kAllowedInEnvironment }
} = internalBinding('options');
const { options, aliases } = NativeModule.require('internal/options');

const allowedNodeEnvironmentFlags = [];
for (const [name, info] of options) {
if (info.envVarSettings === kAllowedInEnvironment) {
allowedNodeEnvironmentFlags.push(name);
}
}

for (const [ from, expansion ] of aliases) {
let isAccepted = true;
for (const to of expansion) {
if (!to.startsWith('-') || to === '--') continue;
const recursiveExpansion = aliases.get(to);
if (recursiveExpansion) {
if (recursiveExpansion[0] === to)
recursiveExpansion.splice(0, 1);
expansion.push(...recursiveExpansion);
continue;
}
isAccepted = options.get(to).envVarSettings === kAllowedInEnvironment;
if (!isAccepted) break;
}
if (isAccepted) {
let canonical = from;
if (canonical.endsWith('='))
canonical = canonical.substr(0, canonical.length - 1);
if (canonical.endsWith(' <arg>'))
canonical = canonical.substr(0, canonical.length - 4);
allowedNodeEnvironmentFlags.push(canonical);
}
}

const trimLeadingDashes = (flag) => replace(flag, leadingDashesRegex, '');

// Save these for comparison against flags provided to
// process.allowedNodeEnvironmentFlags.has() which lack leading dashes.
// Avoid interference w/ user code by flattening `Set.prototype` into
// each object.
const nodeFlags = Object.defineProperties(
new Set(allowedNodeEnvironmentFlags.map(trimLeadingDashes)),
Object.getOwnPropertyDescriptors(Set.prototype)
);

class NodeEnvironmentFlagsSet extends Set {
constructor(...args) {
super(...args);

// the super constructor consumes `add`, but
// disallow any future adds.
this.add = () => this;
}

delete() {
// noop, `Set` API compatible
return false;
}

clear() {
// noop
}

has(key) {
// This will return `true` based on various possible
// permutations of a flag, including present/missing leading
// dash(es) and/or underscores-for-dashes.
// Strips any values after `=`, inclusive.
// TODO(addaleax): It might be more flexible to run the option parser
// on a dummy option set and see whether it rejects the argument or
// not.
if (typeof key === 'string') {
key = replace(key, replaceUnderscoresRegex, '-');
if (test(leadingDashesRegex, key)) {
key = replace(key, trailingValuesRegex, '');
return has(this, key);
}
return has(nodeFlags, key);
}
return false;
}
}

Object.freeze(NodeEnvironmentFlagsSet.prototype.constructor);
Object.freeze(NodeEnvironmentFlagsSet.prototype);

return process.allowedNodeEnvironmentFlags = Object.freeze(
new NodeEnvironmentFlagsSet(
allowedNodeEnvironmentFlags
));
};

Object.defineProperty(process, 'allowedNodeEnvironmentFlags', {
get,
set(value) {
Object.defineProperty(this, 'allowedNodeEnvironmentFlags', {
value,
configurable: true,
enumerable: true,
writable: true
});
},
enumerable: true,
configurable: true
});
}

startup();
});
125 changes: 125 additions & 0 deletions lib/internal/process/per_thread.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,132 @@ function setupUncaughtExceptionCapture(exceptionHandlerState,
};
}

const replaceUnderscoresRegex = /_/g;
const leadingDashesRegex = /^--?/;
const trailingValuesRegex = /=.*$/;

// Save references so user code does not interfere
const replace = Function.call.bind(String.prototype.replace);
const has = Function.call.bind(Set.prototype.has);
const test = Function.call.bind(RegExp.prototype.test);

// This builds the initial process.allowedNodeEnvironmentFlags
// from data in the config binding.
function buildAllowedFlags() {
const {
envSettings: { kAllowedInEnvironment }
} = internalBinding('options');
const { options, aliases } = require('internal/options');

const allowedNodeEnvironmentFlags = [];
for (const [name, info] of options) {
if (info.envVarSettings === kAllowedInEnvironment) {
allowedNodeEnvironmentFlags.push(name);
}
}

for (const [ from, expansion ] of aliases) {
let isAccepted = true;
for (const to of expansion) {
if (!to.startsWith('-') || to === '--') continue;
const recursiveExpansion = aliases.get(to);
if (recursiveExpansion) {
if (recursiveExpansion[0] === to)
recursiveExpansion.splice(0, 1);
expansion.push(...recursiveExpansion);
continue;
}
isAccepted = options.get(to).envVarSettings === kAllowedInEnvironment;
if (!isAccepted) break;
}
if (isAccepted) {
let canonical = from;
if (canonical.endsWith('='))
canonical = canonical.substr(0, canonical.length - 1);
if (canonical.endsWith(' <arg>'))
canonical = canonical.substr(0, canonical.length - 4);
allowedNodeEnvironmentFlags.push(canonical);
}
}

const trimLeadingDashes = (flag) => replace(flag, leadingDashesRegex, '');

// Save these for comparison against flags provided to
// process.allowedNodeEnvironmentFlags.has() which lack leading dashes.
// Avoid interference w/ user code by flattening `Set.prototype` into
// each object.
const nodeFlags = Object.defineProperties(
new Set(allowedNodeEnvironmentFlags.map(trimLeadingDashes)),
Object.getOwnPropertyDescriptors(Set.prototype)
);

class NodeEnvironmentFlagsSet extends Set {
constructor(...args) {
super(...args);

// the super constructor consumes `add`, but
// disallow any future adds.
this.add = () => this;
}

delete() {
// noop, `Set` API compatible
return false;
}

clear() {
// noop
}

has(key) {
// This will return `true` based on various possible
// permutations of a flag, including present/missing leading
// dash(es) and/or underscores-for-dashes.
// Strips any values after `=`, inclusive.
// TODO(addaleax): It might be more flexible to run the option parser
// on a dummy option set and see whether it rejects the argument or
// not.
if (typeof key === 'string') {
key = replace(key, replaceUnderscoresRegex, '-');
if (test(leadingDashesRegex, key)) {
key = replace(key, trailingValuesRegex, '');
return has(this, key);
}
return has(nodeFlags, key);
}
return false;
}
}

Object.freeze(NodeEnvironmentFlagsSet.prototype.constructor);
Object.freeze(NodeEnvironmentFlagsSet.prototype);

return process.allowedNodeEnvironmentFlags = Object.freeze(
new NodeEnvironmentFlagsSet(
allowedNodeEnvironmentFlags
));
}

function setupAllowedFlags() {
Object.defineProperty(process, 'allowedNodeEnvironmentFlags', {
get: buildAllowedFlags,
set(value) {
// If the user tries to set this to another value, override
// this completely to that value.
Object.defineProperty(this, 'allowedNodeEnvironmentFlags', {
value,
configurable: true,
enumerable: true,
writable: true
});
},
enumerable: true,
configurable: true
});
}

module.exports = {
setupAllowedFlags,
setupAssert,
setupCpuUsage,
setupHrtime,
Expand Down

0 comments on commit d77cf92

Please sign in to comment.