From ef6834961744610575963a2a2c208d1bbf8538dc Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 29 Nov 2018 04:01:06 +0800 Subject: [PATCH] lib: move setupAllowedFlags() into per_thread.js Because most of its code (the getter) has nothing to do with the actual bootstrapping and it is run per-thread. PR-URL: https://github.com/nodejs/node/pull/24704 Reviewed-By: Anna Henningsen Reviewed-By: Christopher Hiller --- lib/internal/bootstrap/node.js | 125 +---------------------------- lib/internal/process/per_thread.js | 125 +++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 124 deletions(-) diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index b91b69247c33ad..d02f4084553bbf 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -209,7 +209,7 @@ perf.markMilestone(NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE); - setupAllowedFlags(); + perThreadSetup.setupAllowedFlags(); // There are various modes that Node can run in. The most common two // are running from a script and running the REPL - but there are a few @@ -617,128 +617,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(' ')) - 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(); }); diff --git a/lib/internal/process/per_thread.js b/lib/internal/process/per_thread.js index 3842582da6c8d0..28f1881d6f7150 100644 --- a/lib/internal/process/per_thread.js +++ b/lib/internal/process/per_thread.js @@ -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(' ')) + 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,