Uh oh!
There was an error while loading. Please reload this page.
lib: Symbol.dispose should be enabled with experimental flag - #54329
lib: Symbol.dispose should be enabled with experimental flag#54329legendecas wants to merge 1 commit into
Conversation
nodejs-github-bot
commented
Aug 12, 2024
Review requested:
|
ljharb
commented
Aug 12, 2024
Isn't Symbol.dispose already polyfilled tho? What happens to those implementations when the flag isn't provided? |
b383d03 to
1cf4567Compare
All A userland polyfill should be able to polifill |
ljharb
commented
Aug 12, 2024
What I mean is, if a flag is required to enable the proposal, then shouldn't the Symbol not exist without the flag? |
With this change, the interal symbol exists on primordial It is there for convinience of implementaion like |
There was a problem hiding this comment.
The fact that we have those symbols available allows for TypeScript to implement this correctly on their side. I don't think having these symbols in place cause any harm
benjamingr
left a comment
There was a problem hiding this comment.
Yeah I don't see the vlaue in putting this (after a year of usage) behind a flag and it already falls back gracefully to not polyfilling if Symbol.dispose is already defined by V8.
The symbol is still here. Like other active developing ECMAScript features needing a It gives a false impression that the explicit resource management proposal is shipped in the Node.js without a flag. |
mcollina
commented
Aug 12, 2024
How? Maybe I misunderstood this pr. The reasoning behind adding this in this way was that, even thought the syntax was not there, the symbol could be called by relevant tools/transpilers and we could experiment with this API. All of those API would now be behind a flag, essentially regressing support for this. I'd be ok to do that if that proposal was not moving forward, but it seems it is moving forward, so it seems a step back in removing these to add it later. |
I think a general principal to experiment an early developing globally accessible APIs/syntax should need a flag, reducing the chance of regression or broadly exposed breaking changes. I am fine leaving |
TypeScript or any other transpilers can experiment new ECMAScript features without Node.js unconditional polyfills. Like the following transpile result, it doesn't need Node.js to unconditionally polyfill a global example"use strict";var__addDisposableResource=(this&&this.__addDisposableResource)||function(env,value,async){if(value!==null&&value!==void0){if(typeofvalue!=="object"&&typeofvalue!=="function")thrownewTypeError("Object expected.");vardispose,inner;if(async){if(!Symbol.asyncDispose)thrownewTypeError("Symbol.asyncDispose is not defined.");dispose=value[Symbol.asyncDispose];}if(dispose===void0){if(!Symbol.dispose)thrownewTypeError("Symbol.dispose is not defined.");dispose=value[Symbol.dispose];if(async)inner=dispose;}if(typeofdispose!=="function")thrownewTypeError("Object not disposable.");if(inner)dispose=function(){try{inner.call(this);}catch(e){returnPromise.reject(e);}};env.stack.push({value: value,dispose: dispose,async: async});}elseif(async){env.stack.push({async: true});}returnvalue;};var__disposeResources=(this&&this.__disposeResources)||(function(SuppressedError){returnfunction(env){functionfail(e){env.error=env.hasError ? newSuppressedError(e,env.error,"An error was suppressed during disposal.") : e;env.hasError=true;}functionnext(){while(env.stack.length){varrec=env.stack.pop();try{varresult=rec.dispose&&rec.dispose.call(rec.value);if(rec.async)returnPromise.resolve(result).then(next,function(e){fail(e);returnnext();});}catch(e){fail(e);}}if(env.hasError)throwenv.error;}returnnext();};})(typeofSuppressedError==="function" ? SuppressedError : function(error,suppressed,message){vare=newError(message);returne.name="SuppressedError",e.error=error,e.suppressed=suppressed,e;});constfoo={[Symbol.dispose](){console.log('dispose');}};var_;constenv_1={stack: [],error: void0,hasError: false};try{_=__addDisposableResource(env_1,foo,false);}catch(e_1){env_1.error=e_1;env_1.hasError=true;}finally{__disposeResources(env_1);}So with a global |
benjamingr
commented
Aug 12, 2024
I'm not sure what the issue is though? It's an experimental feature, it's subject to change, we have several similar situations across Node.js (though no polyfills). We do not implement the explicit resource management proposal though. We don't have
Sure but this isn't much of a globally available API? It's like Matteo said just a hook for third-party tools (like TypeScript) to use Symbol.dispose/asyncDispose on APIs. I agree when there is breakage potential (like exposing EventTarget globally) we need a flag + a major with the flag + a major with an opt out flag in order to make migration easier for the ecosystem. But if this proposal changes/breaks we break our (intentionally experimental for over a year) APIs. We can document the implication of an API being experimental better though to make it clear what it means. |
It is globally available |
benjamingr
commented
Aug 12, 2024
@legendecas yes, we implement the minimal amount we need in order to be hookable and allow interoperability and experimentation. We do not implement the syntactic parts. This is similar to many web APIs where we implement the subset it makes sense for Node to implement in core. The way people have been using this this past year is through tools like TypeScript, it's functionally not usable without a third-party tool until V8 implements it.
Hence the "much" part :) It's very unlikely (unless I'm not considering something obvious) to conflict with existing user code or cause breakage. |
legendecas
commented
Aug 12, 2024
I think my point is that an unfinished feature is unconditionally exposed on the global. It should be experimented with a flag under active development. Like, all actively developing new ECMAScript features will require experimental flags in V8, and it will be confusing that Node.js only implement the language built-in incompletely but enabled it unconditionally.
I don't agree ECMAScript features are similar to Web APIs we implement partially by intention. This PR didn't remove |
0ab8ce9 to
c2b0107CompareUpdated to emit an experimental warning when either The experimental warning will be disabled when either |
c2b0107 to
8d499ecCompareThe 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.
8d499ec to
8accb84Comparebenjamingr
commented
Aug 12, 2024
I don't think it's good UX to add an experimental warning a year into it, but if this was a new feature I would have been fine with an experimental warning. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@## main #54329 +/- ##
==========================================
- Coverage 87.11% 87.04% -0.07%
==========================================
Files 647 647 Lines 181754 181957 +203 Branches 34885 34895 +10 ==========================================
+ Hits 158332 158393 +61 - Misses 16738 16861 +123 - Partials 6684 6703 +19
|
mcollina
left a comment
There was a problem hiding this comment.
LGTM, we should likely have been emitting a warning from the beginning for this feature.
Can you please add a test that uses the using feature?
benjamingr
commented
Aug 12, 2024
As in with --experimental-strip-types? |
mcollina
commented
Aug 12, 2024
My understanding is that --js-explicit-resource-management does actually enable the syntax. |
The flag is present but the implementation is unfinished. The syntax support is still limited and not functional on the node.js main branch. |
aduh95
commented
Aug 13, 2024
It'd be nice if passing |
legendecas
commented
Aug 13, 2024
Right, boolean flags are not possible to be distinguished whether a |
benjamingr
commented
Aug 13, 2024
I still think we shouldn't do this a year into it (for developer expectations/ux concerns), but I think in retrospect it should have had an experimental warning and we should change the process to require TSC consensus before landing new globals (especially experimental ones) since that's a cross cutting concern. |
benjamingr
commented
Aug 13, 2024
Also at the very least it should have been semver-major by default without other considerations since it added a new global |
mcollina
commented
Aug 14, 2024
I can stand by the ship being sailed on emitting the experimental warning on this one too. @nodejs/tsc what do you all think? |
MoLow
commented
Aug 16, 2024
I don't think this should land as is. It will break existing users. |
@MoLow the PR only emits experimental warnings. Enable flag |
benjamingr
commented
Aug 18, 2024
Let's not focus on this particular feature (Symbol.dispose) can we get TSC consensus/evaluation of safety on requiring TSC consensus for polyfilling/adding experimental JS APIs with (even tiny) potential breakage potential? |
legendecas
commented
Aug 27, 2024
Closed in favor of #54330. |
Explicitly document that adding an API to the global scope requires `semver-major` label. Waiving the `semver-major` requires a regular TSC consensus process. PR-URL: #54330 Refs: #54329 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com>
Explicitly document that adding an API to the global scope requires `semver-major` label. Waiving the `semver-major` requires a regular TSC consensus process. PR-URL: #54330 Refs: #54329 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com>
Explicitly document that adding an API to the global scope requires `semver-major` label. Waiving the `semver-major` requires a regular TSC consensus process. PR-URL: #54330 Refs: #54329 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com>
Explicitly document that adding an API to the global scope requires `semver-major` label. Waiving the `semver-major` requires a regular TSC consensus process. PR-URL: #54330 Refs: #54329 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com>
Explicitly document that adding an API to the global scope requires `semver-major` label. Waiving the `semver-major` requires a regular TSC consensus process. PR-URL: #54330 Refs: #54329 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com>
Explicitly document that adding an API to the global scope requires `semver-major` label. Waiving the `semver-major` requires a regular TSC consensus process. PR-URL: #54330 Refs: #54329 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com>
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 impliesthat the V8 option
--js-explicit-resource-managementto be enabled.When
--experimental-explicit-resource-managementflag is not set, anexperimental warning is emitted.
Unconditional global presense of
Symbol.disposecan be confusing thateitehr
DisposableStack,AsyncDisposableStackandSuppressedErrorare not implemented.