Skip to content

Commit

Permalink
process: make process.config read only
Browse files Browse the repository at this point in the history
  • Loading branch information
gribnoysup committed Jun 30, 2022
1 parent 49a5e81 commit 8bf8ef5
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 79 deletions.
5 changes: 4 additions & 1 deletion doc/api/deprecations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2889,12 +2889,15 @@ Prefer [`message.socket`][] over [`message.connection`][].

<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/43627
description: End-of-Life.
- version: v16.0.0
pr-url: https://github.com/nodejs/node/pull/36902
description: Runtime deprecation.
-->

Type: Runtime
Type: End-of-Life

The `process.config` property provides access to Node.js compile-time settings.
However, the property is mutable and therefore subject to tampering. The ability
Expand Down
20 changes: 8 additions & 12 deletions doc/api/process.md
Original file line number Diff line number Diff line change
Expand Up @@ -1041,17 +1041,21 @@ This feature is not available in [`Worker`][] threads.
<!-- YAML
added: v0.7.7
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/43627
description: The object returned by `process.config` is read-only. Modifying
it in strict mode will throw an error.
- version: v16.0.0
pr-url: https://github.com/nodejs/node/pull/36902
description: Modifying process.config has been deprecated.
-->

* {Object}

The `process.config` property returns an `Object` containing the JavaScript
representation of the configure options used to compile the current Node.js
executable. This is the same as the `config.gypi` file that was produced when
running the `./configure` script.
The `process.config` property returns a read-only `Object` containing the
JavaScript representation of the configure options used to compile the current
Node.js executable. This is the same as the `config.gypi` file that was produced
when running the `./configure` script.

An example of the possible output looks like:

Expand Down Expand Up @@ -1085,14 +1089,6 @@ An example of the possible output looks like:
}
```

The `process.config` property is **not** read-only and there are existing
modules in the ecosystem that are known to extend, modify, or entirely replace
the value of `process.config`.

Modifying the `process.config` property, or any child-property of the
`process.config` object has been deprecated. The `process.config` will be made
read-only in a future release.

## `process.connected`

<!-- YAML
Expand Down
70 changes: 4 additions & 66 deletions lib/internal/bootstrap/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,8 @@ const {
JSONParse,
ObjectDefineProperty,
ObjectGetPrototypeOf,
ObjectPreventExtensions,
ObjectSetPrototypeOf,
ReflectGet,
ReflectSet,
ObjectFreeze,
SymbolToStringTag,
globalThis,
} = primordials;
Expand All @@ -72,75 +70,15 @@ process._exiting = false;
// process.config is serialized config.gypi
const nativeModule = internalBinding('native_module');

// TODO(@jasnell): Once this has gone through one full major
// release cycle, remove the Proxy and setter and update the
// getter to either return a read-only object or always return
// a freshly parsed version of nativeModule.config.

const deprecationHandler = {
warned: false,
message: 'Setting process.config is deprecated. ' +
'In the future the property will be read-only.',
code: 'DEP0150',
maybeWarn() {
if (!this.warned) {
process.emitWarning(this.message, {
type: 'DeprecationWarning',
code: this.code
});
this.warned = true;
}
},

defineProperty(target, key, descriptor) {
this.maybeWarn();
return ObjectDefineProperty(target, key, descriptor);
},

deleteProperty(target, key) {
this.maybeWarn();
delete target[key];
},

preventExtensions(target) {
this.maybeWarn();
return ObjectPreventExtensions(target);
},

set(target, key, value) {
this.maybeWarn();
return ReflectSet(target, key, value);
},

get(target, key, receiver) {
const val = ReflectGet(target, key, receiver);
if (val != null && typeof val === 'object') {
// eslint-disable-next-line node-core/prefer-primordials
return new Proxy(val, deprecationHandler);
}
return val;
},

setPrototypeOf(target, proto) {
this.maybeWarn();
return ObjectSetPrototypeOf(target, proto);
}
};

// eslint-disable-next-line node-core/prefer-primordials
let processConfig = new Proxy(
JSONParse(nativeModule.config),
deprecationHandler);
const processConfig = JSONParse(nativeModule.config, (_key, value) => {
return ObjectFreeze(value);
});

ObjectDefineProperty(process, 'config', {
__proto__: null,
enumerable: true,
configurable: true,
get() { return processConfig; },
set(value) {
deprecationHandler.maybeWarn();
processConfig = value;
}
});

require('internal/worker/js_transferable').setup();
Expand Down
10 changes: 10 additions & 0 deletions test/parallel/test-process-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ assert(Object.hasOwn(process, 'config'));
// Ensure that `process.config` is an Object.
assert.strictEqual(Object(process.config), process.config);

// Ensure that you can't change config values
try {
process.config.variables = 42;
} catch (e) {
assert.strictEqual(
e.message,
"Cannot assign to read only property 'variables' of object '#<Object>'"
);
}

const configPath = path.resolve(__dirname, '..', '..', 'config.gypi');

if (!fs.existsSync(configPath)) {
Expand Down

0 comments on commit 8bf8ef5

Please sign in to comment.