Skip to content

[explicit-resource-management] Add remaining tests specific to await using statement semantics #4480

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-let-and-const-declarations-runtime-semantics-evaluation
description: Invokes [Symbol.asyncDispose] getter
info: |
RS: Evaluation
AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;

1. Perform ? BindingEvaluation of BindingList with argument async-dispose.
2. Return empty.

RS: BindingEvaluation
LexicalBinding : BindingIdentifier Initializer

...
5. Return ? InitializeReferencedBinding(lhs, value, hint).

InitializeReferencedBinding ( V, W )

...
4. Return ? base.InitializeBinding(V.[[ReferencedName]], W).

InitializeBinding ( N, V, hint )

...
2. If hint is not normal, perform ? AddDisposableResource(envRec.[[DisposeCapability]], V, hint).
...

AddDisposableResource ( disposeCapability, V, hint [, method ] )

1. If method is not present then,
a. If V is either null or undefined and hint is sync-dispose, then
i. Return unused.
b. Let resource be ? CreateDisposableResource(V, hint).
2. Else,
...
3. Append resource to disposeCapability.[[DisposableResourceStack]].
4. Return unused.

CreateDisposableResource ( V, hint [ , method ] )

1. If method is not present, then
a. If V is either null or undefined, then
...
b. Else,
i. If V is not an Object, throw a TypeError exception.
ii. Set method to ? GetDisposeMethod(V, hint).
iii. If method is undefined, throw a TypeError exception.
...

GetDisposeMethod ( V, hint )

1. If hint is async-dispose, then
a. Let method be ? GetMethod(V, @@asyncDispose).
b. If method is undefined, then
i. Set method to ? GetMethod(V, @@dispose).
2. Else,
a. Let method be ? GetMethod(V, @@dispose).
3. Return method.

GetMethod ( V, P )

1. Let func be ? GetV(V, P).
2. If func is either undefined or null, return undefined.
3. ...

flags: [async]
includes: [asyncHelpers.js]
features: [explicit-resource-management]
---*/

asyncTest(async function () {
var resource = {
disposed: false,
get [Symbol.asyncDispose]() {
return async function () {
this.disposed = true;
};
}
};

{
await using _ = resource;
}

assert.sameValue(resource.disposed, true, 'Expected resource to have been disposed');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-block-runtime-semantics-evaluation
description: Initialized value is disposed with the correct 'this' value
info: |
RS: Evaluation
Block : { StatementList }

...
5. Let blockValue be the result of evaluating StatementList.
6. Set blockValue to DisposeResources(blockEnv.[[DisposeCapability]], blockValue).
...

DisposeResources ( disposeCapability, completion )

1. For each resource of disposeCapability.[[DisposableResourceStack]], in reverse list order, do
a. Let result be Dispose(resource.[[ResourceValue]], resource.[[Hint]], resource.[[DisposeMethod]]).
b. If result.[[Type]] is throw, then
i. If completion.[[Type]] is throw, then
1. Set result to result.[[Value]].
2. Let suppressed be completion.[[Value]].
3. Let error be a newly created SuppressedError object.
4. Perform ! CreateNonEnumerableDataPropertyOrThrow(error, "error", result).
5. Perform ! CreateNonEnumerableDataPropertyOrThrow(error, "suppressed", suppressed).
6. Set completion to ThrowCompletion(error).
ii. Else,
1. Set completion to result.
2. Return completion.

Dispose ( V, hint, method )

1. If method is undefined, let result be undefined.
2. Else, let result be ? Call(method, V).
...

flags: [async]
includes: [asyncHelpers.js]
features: [explicit-resource-management]
---*/

asyncTest(async function () {
var resource = {
disposed: false,
async [Symbol.asyncDispose]() {
assert.sameValue(this, resource);
}
};

{
await using _ = resource;
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-block-runtime-semantics-evaluation
description: Disposal succeeds even if [Symbol.disposeAsync] does not return a Promise.
info: |
RS: Evaluation
Block : { StatementList }

...
5. Let blockValue be the result of evaluating StatementList.
6. Set blockValue to DisposeResources(blockEnv.[[DisposeCapability]], blockValue).
...

DisposeResources ( disposeCapability, completion )

1. For each resource of disposeCapability.[[DisposableResourceStack]], in reverse list order, do
a. Let result be Dispose(resource.[[ResourceValue]], resource.[[Hint]], resource.[[DisposeMethod]]).
b. If result.[[Type]] is throw, then
i. If completion.[[Type]] is throw, then
1. Set result to result.[[Value]].
2. Let suppressed be completion.[[Value]].
3. Let error be a newly created SuppressedError object.
4. Perform ! CreateNonEnumerableDataPropertyOrThrow(error, "error", result).
5. Perform ! CreateNonEnumerableDataPropertyOrThrow(error, "suppressed", suppressed).
6. Set completion to ThrowCompletion(error).
ii. Else,
1. Set completion to result.
2. Return completion.

Dispose ( V, hint, method )

1. If method is undefined, let result be undefined.
2. Else, let result be ? Call(method, V).
3. If hint is async-dispose, then
a. ...
4. Return undefined.

flags: [async]
includes: [asyncHelpers.js]
features: [explicit-resource-management]
---*/

asyncTest(async function () {
var resource = {
disposed: false,
[Symbol.asyncDispose]() {
this.disposed = true;
}
};

{
await using _ = resource;
}

assert.sameValue(resource.disposed, true, 'Expected resource to have been disposed');
});
89 changes: 89 additions & 0 deletions test/language/statements/await-using/Symbol.dispose-getter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-let-and-const-declarations-runtime-semantics-evaluation
description: Invokes [Symbol.dispose] getter
info: |
RS: Evaluation
AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;

1. Perform ? BindingEvaluation of BindingList with argument async-dispose.
2. Return empty.

RS: BindingEvaluation
LexicalBinding : BindingIdentifier Initializer

...
5. Return ? InitializeReferencedBinding(lhs, value, hint).

InitializeReferencedBinding ( V, W )

...
4. Return ? base.InitializeBinding(V.[[ReferencedName]], W).

InitializeBinding ( N, V, hint )

...
2. If hint is not normal, perform ? AddDisposableResource(envRec.[[DisposeCapability]], V, hint).
...

AddDisposableResource ( disposeCapability, V, hint [, method ] )

1. If method is not present then,
a. If V is either null or undefined and hint is sync-dispose, then
i. Return unused.
b. Let resource be ? CreateDisposableResource(V, hint).
2. Else,
...
3. Append resource to disposeCapability.[[DisposableResourceStack]].
4. Return unused.

CreateDisposableResource ( V, hint [ , method ] )

1. If method is not present, then
a. If V is either null or undefined, then
...
b. Else,
i. If V is not an Object, throw a TypeError exception.
ii. Set method to ? GetDisposeMethod(V, hint).
iii. If method is undefined, throw a TypeError exception.
...

GetDisposeMethod ( V, hint )

1. If hint is async-dispose, then
a. Let method be ? GetMethod(V, @@asyncDispose).
b. If method is undefined, then
i. Set method to ? GetMethod(V, @@dispose).
2. Else,
a. Let method be ? GetMethod(V, @@dispose).
3. Return method.

GetMethod ( V, P )

1. Let func be ? GetV(V, P).
2. If func is either undefined or null, return undefined.
3. ...

flags: [async]
includes: [asyncHelpers.js]
features: [explicit-resource-management]
---*/

asyncTest(async function () {
var resource = {
disposed: false,
get [Symbol.dispose]() {
return function() {
this.disposed = true;
};
}
};

{
await using _ = resource;
}

assert.sameValue(resource.disposed, true, 'Expected resource to have been disposed');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-block-runtime-semantics-evaluation
description: Initialized value is disposed with the correct 'this' value
info: |
RS: Evaluation
Block : { StatementList }

...
5. Let blockValue be the result of evaluating StatementList.
6. Set blockValue to DisposeResources(blockEnv.[[DisposeCapability]], blockValue).
...

DisposeResources ( disposeCapability, completion )

1. For each resource of disposeCapability.[[DisposableResourceStack]], in reverse list order, do
a. Let result be Dispose(resource.[[ResourceValue]], resource.[[Hint]], resource.[[DisposeMethod]]).
b. If result.[[Type]] is throw, then
i. If completion.[[Type]] is throw, then
1. Set result to result.[[Value]].
2. Let suppressed be completion.[[Value]].
3. Let error be a newly created SuppressedError object.
4. Perform ! CreateNonEnumerableDataPropertyOrThrow(error, "error", result).
5. Perform ! CreateNonEnumerableDataPropertyOrThrow(error, "suppressed", suppressed).
6. Set completion to ThrowCompletion(error).
ii. Else,
1. Set completion to result.
2. Return completion.

Dispose ( V, hint, method )

1. If method is undefined, let result be undefined.
2. Else, let result be ? Call(method, V).
...

flags: [async]
includes: [asyncHelpers.js]
features: [explicit-resource-management]
---*/

asyncTest(async function() {
var resource = {
disposed: false,
[Symbol.dispose]() {
assert.sameValue(this, resource);
}
};

{
await using _ = resource;
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-disposeresources
description: >
`await using` allows a non-Promise return value from `[Symbol.asyncDispose]()`
info: |
DisposeResources ( disposeCapability, completion )

1. For each resource of disposeCapability.[[DisposableResourceStack]], in reverse list order, do
a. Let result be Dispose(resource.[[ResourceValue]], resource.[[Hint]], resource.[[DisposeMethod]]).
b. If result.[[Type]] is throw, then
i. If completion.[[Type]] is throw, then
1. Set result to result.[[Value]].
2. Let suppressed be completion.[[Value]].
3. Let error be a newly created SuppressedError object.
4. Perform ! CreateNonEnumerableDataPropertyOrThrow(error, "error", result).
5. Perform ! CreateNonEnumerableDataPropertyOrThrow(error, "suppressed", suppressed).
6. Set completion to ThrowCompletion(error).
ii. Else,
1. Set completion to result.
2. Return completion.

Dispose ( V, hint, method )

1. If method is undefined, let result be undefined.
2. Else, let result be ? Call(method, V).
3. If hint is async-dispose, then
a. Perform ? Await(result).
4. Return undefined.

flags: [async]
includes: [asyncHelpers.js]
features: [explicit-resource-management]
---*/

asyncTest(async function () {
var resource = {
[Symbol.asyncDispose]() {
}
};

{
await using _ = resource;
}
});
Loading