Skip to content

Commit

Permalink
lib: Symbol.dispose should be enabled with experimental flag
Browse files Browse the repository at this point in the history
The TC39 explicit resource management proposal is still at stage 3 and
under active development. It must be enabled with an experimental
flag `--experimental-explicit-resource-management`. The flag implies
that the V8 option `--js-explicit-resource-management` to be enabled.

When `--experimental-explicit-resource-management` flag is not set, an
experimental warning is emitted.
  • Loading branch information
legendecas committed Aug 12, 2024
1 parent 90dea9e commit 8accb84
Show file tree
Hide file tree
Showing 20 changed files with 102 additions and 18 deletions.
12 changes: 12 additions & 0 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,14 @@ added: v22.3.0

Enable exposition of [EventSource Web API][] on the global scope.

### `--experimental-explicit-resource-management`

<!-- YAML
added: REPLACEME
-->

Use this flag to enable [Explicit Resource Management][] support.

### `--experimental-import-meta-resolve`

<!-- YAML
Expand Down Expand Up @@ -2912,6 +2920,7 @@ one is included in the list below.
* `--experimental-default-type`
* `--experimental-detect-module`
* `--experimental-eventsource`
* `--experimental-explicit-resource-management`
* `--experimental-import-meta-resolve`
* `--experimental-json-modules`
* `--experimental-loader`
Expand Down Expand Up @@ -3364,6 +3373,8 @@ documented here:

### `--jitless`

### `--js-explicit-resource-management`

### `--interpreted-frames-native-stack`

### `--prof`
Expand Down Expand Up @@ -3435,6 +3446,7 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12
[ECMAScript module]: esm.md#modules-ecmascript-modules
[EventSource Web API]: https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events
[ExperimentalWarning: `vm.measureMemory` is an experimental feature]: vm.md#vmmeasurememoryoptions
[Explicit Resource Management]: https://github.com/tc39/proposal-explicit-resource-management
[File System Permissions]: permissions.md#file-system-permissions
[Loading ECMAScript modules using `require()`]: modules.md#loading-ecmascript-modules-using-require
[Module customization hooks]: module.md#customization-hooks
Expand Down
2 changes: 2 additions & 0 deletions doc/api/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -2276,6 +2276,8 @@ mock.timers.reset();

### `timers[Symbol.dispose]()`

> Stability: 1 - Experimental
Calls `timers.reset()`.

### `timers.tick([milliseconds])`
Expand Down
62 changes: 44 additions & 18 deletions lib/internal/process/pre_execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const {
NumberParseInt,
ObjectDefineProperty,
ObjectFreeze,
ObjectHasOwn,
String,
StringPrototypeStartsWith,
Symbol,
Expand Down Expand Up @@ -159,29 +160,54 @@ function prepareExecution(options) {
return mainEntry;
}

function defineSymbolDisposePolyfill() {
ObjectDefineProperty(Symbol, 'dispose', {
__proto__: null,
configurable: false,
enumerable: false,
value: SymbolDispose,
writable: false,
});
ObjectDefineProperty(Symbol, 'asyncDispose', {
__proto__: null,
configurable: false,
enumerable: false,
value: SymbolAsyncDispose,
writable: false,
});
}

function setupSymbolDisposePolyfill() {
// TODO(MoLow): Remove this polyfill once Symbol.dispose and Symbol.asyncDispose are available in V8.
// eslint-disable-next-line node-core/prefer-primordials
if (typeof Symbol.dispose !== 'symbol') {
ObjectDefineProperty(Symbol, 'dispose', {
__proto__: null,
configurable: false,
enumerable: false,
value: SymbolDispose,
writable: false,
});
if (ObjectHasOwn(Symbol, 'dispose')) {
return;
}

// eslint-disable-next-line node-core/prefer-primordials
if (typeof Symbol.asyncDispose !== 'symbol') {
ObjectDefineProperty(Symbol, 'asyncDispose', {
__proto__: null,
configurable: false,
enumerable: false,
value: SymbolAsyncDispose,
writable: false,
});
if (getOptionValue('--experimental-explicit-resource-management')) {
defineSymbolDisposePolyfill();
return;
}

ObjectDefineProperty(Symbol, 'dispose', {
__proto__: null,
configurable: true,
enumerable: false,
get: () => {
emitExperimentalWarning('Symbol.dispose/Symbol.asyncDispose');
defineSymbolDisposePolyfill();
return SymbolDispose;
},
});
ObjectDefineProperty(Symbol, 'asyncDispose', {
__proto__: null,
configurable: true,
enumerable: false,
get: () => {
emitExperimentalWarning('Symbol.dispose/Symbol.asyncDispose');
defineSymbolDisposePolyfill();
return SymbolAsyncDispose;
},
});
}

function setupUserModules(forceDefaultLoader = false) {
Expand Down
13 changes: 13 additions & 0 deletions src/node_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,19 @@ PerIsolateOptionsParser::PerIsolateOptionsParser(
Implies("--experimental-shadow-realm", "--harmony-shadow-realm");
Implies("--harmony-shadow-realm", "--experimental-shadow-realm");
ImpliesNot("--no-harmony-shadow-realm", "--experimental-shadow-realm");

AddOption("--experimental-explicit-resource-management",
"",
&PerIsolateOptions::experimental_explicit_resource_management,
kAllowedInEnvvar);
AddOption("--js-explicit-resource-management", "", V8Option{});
Implies("--experimental-explicit-resource-management",
"--js-explicit-resource-management");
Implies("--js-explicit-resource-management",
"--experimental-explicit-resource-management");
ImpliesNot("--no-js-explicit-resource-management",
"--experimental-explicit-resource-management");

AddOption("--build-snapshot",
"Generate a snapshot blob when the process exits.",
&PerIsolateOptions::build_snapshot,
Expand Down
1 change: 1 addition & 0 deletions src/node_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ class PerIsolateOptions : public Options {
bool report_uncaught_exception = false;
bool report_on_signal = false;
bool experimental_shadow_realm = false;
bool experimental_explicit_resource_management = false;
std::string report_signal = "SIGUSR2";
bool build_snapshot = false;
std::string build_snapshot_config;
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-child-process-destroy.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

'use strict';
const common = require('../common');
const assert = require('assert');
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-dgram-async-dispose.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

import * as common from '../common/index.mjs';
import assert from 'node:assert';
import dgram from 'node:dgram';
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-events-add-abort-listener.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

import * as common from '../common/index.mjs';
import * as events from 'node:events';
import * as assert from 'node:assert';
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-fs-promises-file-handle-dispose.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

'use strict';

const common = require('../common');
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-http-server-async-dispose.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

'use strict';
const common = require('../common');
const assert = require('assert');
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-http2-server-async-dispose.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

'use strict';

const common = require('../common');
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-https-server-async-dispose.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

'use strict';

const common = require('../common');
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-net-server-async-dispose.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

import * as common from '../common/index.mjs';
import assert from 'node:assert';
import net from 'node:net';
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-runner-mock-timers.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

'use strict';
process.env.NODE_TEST_KNOWN_GLOBALS = 0;
const common = require('../common');
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-stream-duplex-destroy.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

'use strict';

const common = require('../common');
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-stream-readable-dispose.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

'use strict';

const common = require('../common');
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-stream-transform-destroy.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

'use strict';

const common = require('../common');
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-stream-writable-destroy.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

'use strict';

const common = require('../common');
Expand Down
2 changes: 2 additions & 0 deletions test/parallel/test-timers-dispose.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

'use strict';
const common = require('../common');
const assert = require('assert');
Expand Down
2 changes: 2 additions & 0 deletions test/sequential/test-inspector-open-dispose.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Flags: --experimental-explicit-resource-management

import * as common from '../common/index.mjs';
import assert from 'node:assert';
import net from 'node:net';
Expand Down

0 comments on commit 8accb84

Please sign in to comment.