Skip to content

Commit 527407c

Browse files
joyeecheungMylesBorins
authored andcommitted
src: cache the result of GetOptions() in JS land
Instead of calling into C++ each time we need to check the value of a command line option, cache the option map in a new `internal/options` module for faster access to the values in JS land. PR-URL: #24091 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Refael Ackermann <refack@gmail.com>
1 parent 3e14212 commit 527407c

14 files changed

+47
-42
lines changed

lib/crypto.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const {
3434
ERR_CRYPTO_FIPS_FORCED,
3535
ERR_CRYPTO_FIPS_UNAVAILABLE
3636
} = require('internal/errors').codes;
37-
const constants = process.binding('constants').crypto;
37+
const constants = internalBinding('constants').crypto;
3838
const {
3939
fipsMode,
4040
fipsForced

lib/internal/bash_completion.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
'use strict';
2-
const { getOptions } = internalBinding('options');
2+
const { options, aliases } = require('internal/options');
33

44
function print(stream) {
5-
const { options, aliases } = getOptions();
65
const all_opts = [...options.keys(), ...aliases.keys()];
76

87
stream.write(`_node_complete() {

lib/internal/bootstrap/loaders.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,7 @@
217217

218218
NativeModule.isInternal = function(id) {
219219
return id.startsWith('internal/') ||
220-
(id === 'worker_threads' &&
221-
!internalBinding('options').getOptions('--experimental-worker'));
220+
(id === 'worker_threads' && !config.experimentalWorker);
222221
};
223222
}
224223

lib/internal/bootstrap/node.js

+8-8
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,13 @@
113113
NativeModule.require('internal/inspector_async_hook').setup();
114114
}
115115

116-
const { getOptions } = internalBinding('options');
117-
const helpOption = getOptions('--help');
118-
const completionBashOption = getOptions('--completion-bash');
119-
const experimentalModulesOption = getOptions('--experimental-modules');
120-
const experimentalVMModulesOption = getOptions('--experimental-vm-modules');
121-
const experimentalWorkerOption = getOptions('--experimental-worker');
116+
const { getOptionValue } = NativeModule.require('internal/options');
117+
const helpOption = getOptionValue('--help');
118+
const completionBashOption = getOptionValue('--completion-bash');
119+
const experimentalModulesOption = getOptionValue('--experimental-modules');
120+
const experimentalVMModulesOption =
121+
getOptionValue('--experimental-vm-modules');
122+
const experimentalWorkerOption = getOptionValue('--experimental-worker');
122123
if (helpOption) {
123124
NativeModule.require('internal/print_help').print(process.stdout);
124125
return;
@@ -631,10 +632,9 @@
631632

632633
const get = () => {
633634
const {
634-
getOptions,
635635
envSettings: { kAllowedInEnvironment }
636636
} = internalBinding('options');
637-
const { options, aliases } = getOptions();
637+
const { options, aliases } = NativeModule.require('internal/options');
638638

639639
const allowedNodeEnvironmentFlags = [];
640640
for (const [name, info] of options) {

lib/internal/modules/cjs/helpers.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const {
99
CHAR_HASH,
1010
} = require('internal/constants');
1111

12-
const { getOptions } = internalBinding('options');
12+
const { getOptionValue } = require('internal/options');
1313

1414
// Invoke with makeRequireFunction(module) where |module| is the Module object
1515
// to use as the context for the require() function.
@@ -107,7 +107,7 @@ const builtinLibs = [
107107
'v8', 'vm', 'zlib'
108108
];
109109

110-
if (getOptions('--experimental-worker')) {
110+
if (getOptionValue('--experimental-worker')) {
111111
builtinLibs.push('worker_threads');
112112
builtinLibs.sort();
113113
}

lib/internal/modules/cjs/loader.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ const {
4040
stripBOM,
4141
stripShebang
4242
} = require('internal/modules/cjs/helpers');
43-
const options = internalBinding('options');
44-
const preserveSymlinks = options.getOptions('--preserve-symlinks');
45-
const preserveSymlinksMain = options.getOptions('--preserve-symlinks-main');
46-
const experimentalModules = options.getOptions('--experimental-modules');
43+
const { getOptionValue } = require('internal/options');
44+
const preserveSymlinks = getOptionValue('--preserve-symlinks');
45+
const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
46+
const experimentalModules = getOptionValue('--experimental-modules');
4747

4848
const {
4949
ERR_INVALID_ARG_TYPE,

lib/internal/modules/esm/default_resolve.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ const internalFS = require('internal/fs/utils');
66
const { NativeModule } = require('internal/bootstrap/loaders');
77
const { extname } = require('path');
88
const { realpathSync } = require('fs');
9-
const { getOptions } = internalBinding('options');
10-
const preserveSymlinks = getOptions('--preserve-symlinks');
11-
const preserveSymlinksMain = getOptions('--preserve-symlinks-main');
9+
const { getOptionValue } = require('internal/options');
10+
const preserveSymlinks = getOptionValue('--preserve-symlinks');
11+
const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
1212
const {
1313
ERR_MISSING_MODULE,
1414
ERR_MODULE_RESOLUTION_LEGACY,

lib/internal/options.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
3+
const { getOptions } = internalBinding('options');
4+
const { options, aliases } = getOptions();
5+
6+
function getOptionValue(option) {
7+
const result = options.get(option);
8+
if (!result) {
9+
return undefined;
10+
}
11+
return result.value;
12+
}
13+
14+
module.exports = {
15+
options,
16+
aliases,
17+
getOptionValue
18+
};

lib/internal/print_help.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
2-
const { getOptions, types } = internalBinding('options');
2+
3+
const { types } = internalBinding('options');
34

45
const typeLookup = [];
56
for (const key of Object.keys(types))
@@ -132,7 +133,7 @@ function format({ options, aliases = new Map(), firstColumn, secondColumn }) {
132133
}
133134

134135
function print(stream) {
135-
const { options, aliases } = getOptions();
136+
const { options, aliases } = require('internal/options');
136137

137138
// Use 75 % of the available width, and at least 70 characters.
138139
const width = Math.max(70, (stream.columns || 0) * 0.75);

lib/internal/process/esm_loader.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ exports.setup = function() {
4848

4949
let ESMLoader = new Loader();
5050
const loaderPromise = (async () => {
51-
const userLoader = internalBinding('options').getOptions('--loader');
51+
const userLoader = require('internal/options').getOptionValue('--loader');
5252
if (userLoader) {
5353
const hooks = await ESMLoader.import(
5454
userLoader, pathToFileURL(`${process.cwd()}/`).href);

lib/repl.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ const {
7171
ERR_SCRIPT_EXECUTION_INTERRUPTED
7272
} = require('internal/errors').codes;
7373
const { sendInspectorCommand } = require('internal/util/inspector');
74-
const experimentalREPLAwait = internalBinding('options').getOptions(
74+
const experimentalREPLAwait = require('internal/options').getOptionValue(
7575
'--experimental-repl-await'
7676
);
7777
const { isRecoverableError } = require('internal/repl/recoverable');

lib/vm.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ module.exports = {
402402
compileFunction,
403403
};
404404

405-
if (internalBinding('options').getOptions('--experimental-vm-modules')) {
405+
if (require('internal/options').getOptionValue('--experimental-vm-modules')) {
406406
const { SourceTextModule } = require('internal/vm/source_text_module');
407407
module.exports.SourceTextModule = SourceTextModule;
408408
}

node.gyp

+1
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@
134134
'lib/internal/modules/esm/translators.js',
135135
'lib/internal/safe_globals.js',
136136
'lib/internal/net.js',
137+
'lib/internal/options.js',
137138
'lib/internal/print_help.js',
138139
'lib/internal/process/esm_loader.js',
139140
'lib/internal/process/main_thread_only.js',

src/node_options.cc

+2-15
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,8 @@ HostPort SplitHostPort(const std::string& arg,
367367
ParseAndValidatePort(arg.substr(colon + 1), errors) };
368368
}
369369

370-
// Usage: Either:
371-
// - getOptions() to get all options + metadata or
372-
// - getOptions(string) to get the value of a particular option
370+
// Return a map containing all the options and their metadata as well
371+
// as the aliases
373372
void GetOptions(const FunctionCallbackInfo<Value>& args) {
374373
Mutex::ScopedLock lock(per_process_opts_mutex);
375374
Environment* env = Environment::GetCurrent(args);
@@ -390,13 +389,8 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
390389

391390
const auto& parser = PerProcessOptionsParser::instance;
392391

393-
std::string filter;
394-
if (args[0]->IsString()) filter = *node::Utf8Value(isolate, args[0]);
395-
396392
Local<Map> options = Map::New(isolate);
397393
for (const auto& item : parser.options_) {
398-
if (!filter.empty() && item.first != filter) continue;
399-
400394
Local<Value> value;
401395
const auto& option_info = item.second;
402396
auto field = option_info.field;
@@ -445,11 +439,6 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
445439
}
446440
CHECK(!value.IsEmpty());
447441

448-
if (!filter.empty()) {
449-
args.GetReturnValue().Set(value);
450-
return;
451-
}
452-
453442
Local<Value> name = ToV8Value(context, item.first).ToLocalChecked();
454443
Local<Object> info = Object::New(isolate);
455444
Local<Value> help_text;
@@ -471,8 +460,6 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
471460
}
472461
}
473462

474-
if (!filter.empty()) return;
475-
476463
Local<Value> aliases;
477464
if (!ToV8Value(context, parser.aliases_).ToLocal(&aliases)) return;
478465

0 commit comments

Comments
 (0)