-
Notifications
You must be signed in to change notification settings - Fork 23.1k
Reference for stage 3 explicit-resource-management #38027
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
2f5f8f1
Reference for stage 3 explicit-resource-management
Josh-Cena 6487bf1
DisposableStack
Josh-Cena f81283d
Iterator disposal
Josh-Cena cd11b5d
AsyncDisposableStack
Josh-Cena 97ece0b
await using example
Josh-Cena 0b550d8
Example for using
Josh-Cena b231823
Final updates
Josh-Cena c1e3cf6
Apply suggestions from code review
Josh-Cena 588c692
Consistently use the name "disposer" instead
Josh-Cena d709dc4
Address more reviews
Josh-Cena 8f04dc3
Migrate sidebar
Josh-Cena f85a967
Merge branch 'main' into explicit-resource-management
Josh-Cena a22061b
Fill in holes
Josh-Cena f86945f
Update files/en-us/web/javascript/reference/global_objects/symbol/asy…
Josh-Cena 7adca23
Update files/en-us/web/javascript/guide/resource_management/index.md
Josh-Cena 863d425
Fixes
Josh-Cena 6569214
Update index.md
Josh-Cena b5e44e7
Apply suggestions from code review
Josh-Cena f5abc7f
Update index.md
Josh-Cena 3f1e9cf
Update index.md
Josh-Cena 60ec9c3
Update index.md
Josh-Cena 00f7a04
Update index.md
Josh-Cena 074f10f
Update index.md
Josh-Cena 68041d6
Update index.md
Josh-Cena File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
447 changes: 447 additions & 0 deletions
447
files/en-us/web/javascript/guide/resource_management/index.md
Large diffs are not rendered by default.
Oops, something went wrong.
69 changes: 69 additions & 0 deletions
69
...-us/web/javascript/reference/global_objects/asyncdisposablestack/adopt/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| --- | ||
| title: AsyncDisposableStack.prototype.adopt() | ||
| slug: Web/JavaScript/Reference/Global_Objects/AsyncDisposableStack/adopt | ||
| page-type: javascript-instance-method | ||
| browser-compat: javascript.builtins.AsyncDisposableStack.adopt | ||
| sidebar: jsref | ||
| --- | ||
|
|
||
| The **`adopt()`** method of {{jsxref("AsyncDisposableStack")}} instances registers a value that doesn't implement the async disposable protocol to the stack by providing a custom disposer function. | ||
|
|
||
| See {{jsxref("DisposableStack.prototype.adopt()")}} for general information about the `adopt()` method. | ||
|
|
||
| ## Syntax | ||
|
|
||
| ```js-nolint | ||
| adopt(value, onDispose) | ||
| ``` | ||
|
|
||
| ### Parameters | ||
|
|
||
| - `value` | ||
| - : Any value to be registered to the stack. | ||
| - `onDispose` | ||
| - : A function that will be called when the stack is disposed. The function receives `value` as its only argument, and it can return a promise which gets awaited. | ||
|
|
||
| ### Return value | ||
|
|
||
| The same `value` that was passed in. | ||
|
|
||
| ### Exceptions | ||
|
|
||
| - {{jsxref("TypeError")}} | ||
| - : Thrown if `onDispose` is not a function. | ||
| - {{jsxref("ReferenceError")}} | ||
| - : Thrown if the stack is already disposed. | ||
|
|
||
| ## Examples | ||
|
|
||
| ### Using adopt() | ||
|
|
||
| This function creates a file handle (as a Node.js [`FileHandle`](https://nodejs.org/api/fs.html#class-filehandle)), that gets closed when the function completes. We suppose that the file handle does not implement the async disposable protocol (in reality it does), so we use `adopt()` to register it to the stack. Because the `handle.close()` method returns a promise, we need to use an `AsyncDisposableStack` so that the disposal gets awaited. | ||
|
|
||
| ```js | ||
| async function readFile(path) { | ||
| await using disposer = new AsyncDisposableStack(); | ||
| const handle = disposer.adopt( | ||
| fs.open(path), | ||
| async (handle) => await handle.close(), | ||
| ); | ||
| const data = await handle.read(); | ||
| // The handle.close() method is called and awaited here before exiting | ||
| return data; | ||
| } | ||
| ``` | ||
|
|
||
| ## Specifications | ||
|
|
||
| {{Specifications}} | ||
|
|
||
| ## Browser compatibility | ||
|
|
||
| {{Compat}} | ||
|
|
||
| ## See also | ||
|
|
||
| - [JavaScript resource management](/en-US/docs/Web/JavaScript/Guide/Resource_management) | ||
| - {{jsxref("AsyncDisposableStack")}} | ||
| - {{jsxref("AsyncDisposableStack.prototype.defer()")}} | ||
| - {{jsxref("AsyncDisposableStack.prototype.use()")}} |
49 changes: 49 additions & 0 deletions
49
...ipt/reference/global_objects/asyncdisposablestack/asyncdisposablestack/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| --- | ||
| title: AsyncDisposableStack() constructor | ||
| slug: Web/JavaScript/Reference/Global_Objects/AsyncDisposableStack/AsyncDisposableStack | ||
| page-type: javascript-constructor | ||
| browser-compat: javascript.builtins.AsyncDisposableStack.AsyncDisposableStack | ||
| sidebar: jsref | ||
| --- | ||
|
|
||
| The **`AsyncDisposableStack()`** constructor creates {{jsxref("AsyncDisposableStack")}} objects. | ||
|
|
||
| ## Syntax | ||
|
|
||
| ```js-nolint | ||
| new AsyncDisposableStack() | ||
| ``` | ||
|
|
||
| > [!NOTE] | ||
| > `AsyncDisposableStack()` can only be constructed with [`new`](/en-US/docs/Web/JavaScript/Reference/Operators/new). Attempting to call it without `new` throws a {{jsxref("TypeError")}}. | ||
|
|
||
| ### Parameters | ||
|
|
||
| None. | ||
|
|
||
| ### Return value | ||
|
|
||
| A new `AsyncDisposableStack` object. | ||
|
|
||
| ## Examples | ||
|
|
||
| ### Creating an AsyncDisposableStack | ||
|
|
||
| ```js | ||
| const disposer = new AsyncDisposableStack(); | ||
| disposer.defer(() => console.log("Disposed!")); | ||
| await disposer.disposeAsync(); | ||
| // Logs: Disposed! | ||
| ``` | ||
|
|
||
| ## Specifications | ||
|
|
||
| {{Specifications}} | ||
|
|
||
| ## Browser compatibility | ||
|
|
||
| {{Compat}} | ||
|
|
||
| ## See also | ||
|
|
||
| - [JavaScript resource management](/en-US/docs/Web/JavaScript/Guide/Resource_management) |
64 changes: 64 additions & 0 deletions
64
...-us/web/javascript/reference/global_objects/asyncdisposablestack/defer/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| --- | ||
| title: AsyncDisposableStack.prototype.defer() | ||
| slug: Web/JavaScript/Reference/Global_Objects/AsyncDisposableStack/defer | ||
| page-type: javascript-instance-method | ||
| browser-compat: javascript.builtins.AsyncDisposableStack.defer | ||
| sidebar: jsref | ||
| --- | ||
|
|
||
| The **`defer()`** method of {{jsxref("AsyncDisposableStack")}} instances takes a callback function to be called and awaited when the stack is disposed. | ||
|
|
||
| See {{jsxref("DisposableStack.prototype.defer()")}} for general information about the `defer()` method. | ||
|
|
||
| ## Syntax | ||
|
|
||
| ```js-nolint | ||
| defer(onDispose) | ||
| ``` | ||
|
|
||
| ### Parameters | ||
|
|
||
| - `onDispose` | ||
| - : A function that will be called when the stack is disposed. The function receives no arguments and can return a promise which gets awaited. | ||
|
|
||
| ### Return value | ||
|
|
||
| None ({{jsxref("undefined")}}). | ||
|
|
||
| ### Exceptions | ||
|
|
||
| - {{jsxref("TypeError")}} | ||
| - : Thrown if `onDispose` is not a function. | ||
| - {{jsxref("ReferenceError")}} | ||
| - : Thrown if the stack is already disposed. | ||
|
|
||
| ## Examples | ||
|
|
||
| ### Using defer() | ||
|
|
||
| One use case of `defer()` is to do something unrelated to resource freeing during scope exit, such as logging a message. | ||
|
|
||
| ```js | ||
| async function doSomething() { | ||
| await using disposer = new AsyncDisposableStack(); | ||
| disposer.defer(async () => { | ||
| await fs.writeFile("log.txt", "All resources freed successfully"); | ||
| }); | ||
| // Other code that claims and frees more data | ||
| } | ||
| ``` | ||
|
|
||
| ## Specifications | ||
|
|
||
| {{Specifications}} | ||
|
|
||
| ## Browser compatibility | ||
|
|
||
| {{Compat}} | ||
|
|
||
| ## See also | ||
|
|
||
| - [JavaScript resource management](/en-US/docs/Web/JavaScript/Guide/Resource_management) | ||
| - {{jsxref("AsyncDisposableStack")}} | ||
| - {{jsxref("AsyncDisposableStack.prototype.adopt()")}} | ||
| - {{jsxref("AsyncDisposableStack.prototype.use()")}} |
92 changes: 92 additions & 0 deletions
92
.../javascript/reference/global_objects/asyncdisposablestack/disposeasync/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| --- | ||
| title: AsyncDisposableStack.prototype.disposeAsync() | ||
| slug: Web/JavaScript/Reference/Global_Objects/AsyncDisposableStack/disposeAsync | ||
| page-type: javascript-instance-method | ||
| browser-compat: javascript.builtins.AsyncDisposableStack.disposeAsync | ||
| sidebar: jsref | ||
| --- | ||
|
|
||
| The **`disposeAsync()`** method of {{jsxref("AsyncDisposableStack")}} instances disposes this stack by calling all disposers registered to it in reverse order of registration, awaiting for each one's completion before calling the next one. If the stack is already disposed, this method does nothing. | ||
|
|
||
| It performs the same action as `await using disposer = new AsyncDisposableStack()` at scope exit. It can be used if you need to clean up at a point other than scope exit. | ||
|
|
||
| ## Syntax | ||
|
|
||
| ```js-nolint | ||
| disposeAsync() | ||
| ``` | ||
|
|
||
| ### Parameters | ||
|
|
||
| None. | ||
|
|
||
| ### Return value | ||
|
|
||
| A new {{jsxref("Promise")}} that resolves with `undefined` when all registered disposers have completed in sequence. | ||
|
|
||
| ### Exceptions | ||
|
|
||
| `disposeAsync()` never synchronously throws an error. The returned promise may reject with one of the following errors: | ||
|
|
||
| - {{jsxref("SuppressedError")}} | ||
| - : Thrown if multiple disposers in the stack threw an error. If only one error is thrown, it is rethrown as-is. Otherwise, for each additional error, a new {{jsxref("SuppressedError")}} is created, with the original error as the `suppressed` property, and the new error as the `error` property. | ||
|
|
||
| ## Examples | ||
|
|
||
| ### Disposing a stack | ||
|
|
||
| Here we push three disposers to the stack, using the {{jsxref("AsyncDisposableStack/use", "use()")}}, {{jsxref("AsyncDisposableStack/adopt", "adopt()")}}, and {{jsxref("AsyncDisposableStack/defer", "defer()")}} methods. When `disposeAsync()` is called, the disposers are called in reverse order of registration. | ||
|
|
||
| Note that usually you don't need to call `disposeAsync()` manually. Declare the stack with {{jsxref("Statements/await_using", "await using")}}, and its [`[Symbol.asyncDispose]()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncDisposableStack/Symbol.asyncDispose) method will be automatically called when the stack goes out of scope. | ||
|
|
||
| ```js | ||
| class Resource { | ||
| #doDisposal() { | ||
| // Imagine more meaningful disposal logic here | ||
| return new Promise((resolve) => { | ||
| setTimeout(resolve, 1000); | ||
| }); | ||
| } | ||
| async dispose() { | ||
| await this.#doDisposal(); | ||
| console.log("Resource disposed"); | ||
| } | ||
| async [Symbol.asyncDispose]() { | ||
| await this.#doDisposal(); | ||
| console.log("Resource disposed via Symbol.asyncDispose"); | ||
| } | ||
| } | ||
|
|
||
| async function doSomething() { | ||
| const disposer = new AsyncDisposableStack(); | ||
| const resource = disposer.use(new Resource()); | ||
| const resource2 = disposer.adopt(new Resource(), (resource) => | ||
| resource.dispose(), | ||
| ); | ||
| disposer.defer(() => console.log("Deferred disposer")); | ||
| disposer.disposeAsync(); | ||
| // Logs in order: | ||
| // Deferred disposer | ||
| // Resource disposed | ||
| // Resource disposed via Symbol.dispose | ||
| } | ||
|
|
||
| doSomething(); | ||
| ``` | ||
|
|
||
| ## Specifications | ||
|
|
||
| {{Specifications}} | ||
|
|
||
| ## Browser compatibility | ||
|
|
||
| {{Compat}} | ||
|
|
||
| ## See also | ||
|
|
||
| - [JavaScript resource management](/en-US/docs/Web/JavaScript/Guide/Resource_management) | ||
| - {{jsxref("AsyncDisposableStack")}} | ||
| - {{jsxref("AsyncDisposableStack.prototype.adopt()")}} | ||
| - {{jsxref("AsyncDisposableStack.prototype.defer()")}} | ||
| - {{jsxref("AsyncDisposableStack.prototype.use()")}} | ||
| - [`AsyncDisposableStack.prototype[Symbol.asyncDispose]()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncDisposableStack/Symbol.asyncDispose) | ||
36 changes: 36 additions & 0 deletions
36
.../web/javascript/reference/global_objects/asyncdisposablestack/disposed/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| --- | ||
| title: AsyncDisposableStack.prototype.disposed | ||
| slug: Web/JavaScript/Reference/Global_Objects/AsyncDisposableStack/disposed | ||
| page-type: javascript-instance-accessor-property | ||
| browser-compat: javascript.builtins.AsyncDisposableStack.disposed | ||
| sidebar: jsref | ||
| --- | ||
|
|
||
| The **`disposed`** accessor property of {{jsxref("AsyncDisposableStack")}} instances returns a boolean indicating whether or not this `AsyncDisposableStack` has been disposed or moved by doing any of the following: | ||
|
|
||
| - Calling its {{jsxref("AsyncDisposableStack/disposeAsync", "disposeAsync()")}} method | ||
| - Calling its {{jsxref("AsyncDisposableStack/move", "move()")}} method | ||
| - Declaring it with {{jsxref("Statements/await_using", "await using")}} and letting the variable go out of scope, which automatically calls the [`[Symbol.asyncDispose]()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncDisposableStack/Symbol.asyncDispose) method. | ||
|
|
||
| ## Examples | ||
|
|
||
| ### Checking if a stack is disposed | ||
|
|
||
| ```js | ||
| const disposer = new AsyncDisposableStack(); | ||
| console.log(disposer.disposed); // false | ||
| await disposer.disposeAsync(); | ||
| console.log(disposer.disposed); // true | ||
| ``` | ||
|
|
||
| ## Specifications | ||
|
|
||
| {{Specifications}} | ||
|
|
||
| ## Browser compatibility | ||
|
|
||
| {{Compat}} | ||
|
|
||
| ## See also | ||
|
|
||
| - [JavaScript resource management](/en-US/docs/Web/JavaScript/Guide/Resource_management) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.