[explicit-resource-management] Add AsyncDisposableStack builtins

This CL adds builtin methods for developer exposed
AsyncDisposableStack object.

Bug: 42203814
Change-Id: I1f16a3bcb80c71a4f33e4ae028f1737c3502dabe
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5715141
Reviewed-by: Shu-yu Guo <syg@chromium.org>
Commit-Queue: Rezvan Mahdavi Hezaveh <rezvan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#95838}
This commit is contained in:
Rezvan Mahdavi Hezaveh 2024-08-27 11:24:40 -07:00 committed by test262-merge-bot
parent 3acb672d11
commit b69e9d5e72
16 changed files with 524 additions and 0 deletions

View File

@ -0,0 +1,26 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
Test developer exposed DisposableStack protype methods adopt() and defer().
features: [explicit-resource-management]
---*/
// adopt() method when onDispose is not callable--------
function TestAsyncDisposableStackAdoptWithNonCallableOnDispose() {
let stack = new AsyncDisposableStack();
stack.adopt(42, 43);
};
assert.throws(
TypeError, () => TestAsyncDisposableStackAdoptWithNonCallableOnDispose(),
'onDispose is not callable');
// defer() method when onDispose is not callable--------
function TestAsyncDisposableStackDeferWithNonCallableOnDispose() {
let stack = new AsyncDisposableStack();
stack.defer(42);
};
assert.throws(
TypeError, () => TestAsyncDisposableStackDeferWithNonCallableOnDispose(),
'onDispose is not callable');

View File

@ -0,0 +1,22 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Test adopt() on a disposed stack.
includes: [asyncHelpers.js]
flags: [async]
features: [explicit-resource-management]
---*/
asyncTest(async function() {
async function TestAsyncDisposableStackAdoptOnDisposedStack() {
let stack = new AsyncDisposableStack();
await stack.disposeAsync();
stack.adopt(42, function(v) {
return v
});
};
await assert.throwsAsync(
ReferenceError, () => TestAsyncDisposableStackAdoptOnDisposedStack(),
'Cannot add values to a disposed stack!');
});

View File

@ -0,0 +1,35 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
Test developer exposed AsyncDisposableStack protype methods adopt().
includes: [asyncHelpers.js, compareArray.js]
flags: [async]
features: [explicit-resource-management]
---*/
asyncTest(async function() {
let valuesNormal = [];
async function TestAsyncDisposableStackAdopt() {
let stack = new AsyncDisposableStack();
stack.adopt(42, function(v) {
valuesNormal.push(v)
});
const disposable = {
value: 1,
[Symbol.asyncDispose]() {
valuesNormal.push(43);
}
};
stack.use(disposable);
stack.adopt(44, function(v) {
valuesNormal.push(v)
});
await stack.disposeAsync();
};
await TestAsyncDisposableStackAdopt();
assert.compareArray(valuesNormal, [44, 43, 42]);
});

View File

@ -0,0 +1,29 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
Exposed AsyncDisposableStack protype methods disposeAsync() throws.
includes: [asyncHelpers.js]
flags: [async]
features: [explicit-resource-management]
---*/
asyncTest(async function() {
async function TestAsyncDisposableStackUseDisposeMethodThrows() {
{
let stack = new AsyncDisposableStack();
const disposable = {
value: 1,
[Symbol.asyncDispose]() {
throw new Test262Error('Symbol.asyncDispose is throwing!');
}
};
stack.use(disposable);
await stack.disposeAsync();
}
};
await assert.throwsAsync(
Test262Error, () => TestAsyncDisposableStackUseDisposeMethodThrows(),
'Symbol.asyncDisposeispose is throwing!');
});

View File

@ -0,0 +1,21 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Test AsyncDisposableStack constructor and prototype.
includes: [propertyHelper.js]
features: [globalThis, explicit-resource-management]
---*/
// constructor --------
assert.sameValue(
typeof AsyncDisposableStack, 'function',
'The value of `typeof AsyncDisposableStack` is "function"');
// prototype --------
verifyProperty(AsyncDisposableStack, 'prototype', {
value: AsyncDisposableStack.prototype,
writable: false,
enumerable: false,
configurable: false,
});

View File

@ -0,0 +1,21 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Test defer() on disposed stack.
includes: [asyncHelpers.js]
flags: [async]
features: [explicit-resource-management]
---*/
asyncTest(async function() {
async function TestAsyncDisposableStackDeferOnDisposedStack() {
let stack = new AsyncDisposableStack();
await stack.disposeAsync();
stack.defer(() => {});
};
await assert.throwsAsync(
ReferenceError, () => TestAsyncDisposableStackDeferOnDisposedStack(),
'Cannot add values to a disposed stack!');
});

View File

@ -0,0 +1,31 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
Test developer exposed AsyncDisposableStack protype method defer().
includes: [asyncHelpers.js, compareArray.js]
flags: [async]
features: [explicit-resource-management]
---*/
asyncTest(async function() {
let deferValuesNormal = [];
async function TestAsyncDisposableStackDefer() {
let stack = new AsyncDisposableStack();
stack.defer(() => deferValuesNormal.push(42));
const disposable = {
value: 1,
[Symbol.asyncDispose]() {
deferValuesNormal.push(43);
}
};
stack.use(disposable);
stack.defer(() => deferValuesNormal.push(44));
await stack.disposeAsync();
};
await TestAsyncDisposableStackDefer();
assert.compareArray(deferValuesNormal, [44, 43, 42]);
});

View File

@ -0,0 +1,41 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
Call disposeAsync() on a disposed AsyncDisposableStack.
includes: [asyncHelpers.js, compareArray.js]
flags: [async]
features: [explicit-resource-management]
---*/
asyncTest(async function() {
let valuesNormal = [];
async function TestAsyncDisposableStackUseDisposingTwice() {
let stack = new AsyncDisposableStack();
const firstDisposable = {
value: 1,
[Symbol.asyncDispose]() {
valuesNormal.push(42);
}
};
const secondDisposable = {
value: 2,
[Symbol.asyncDispose]() {
valuesNormal.push(43);
}
};
stack.use(firstDisposable);
stack.use(secondDisposable);
let newStack = stack.move();
await newStack.disposeAsync();
assert.sameValue(newStack.disposed, true, 'disposed should be true');
// stack is already disposed, so the next line should do nothing.
await newStack.disposeAsync();
};
await TestAsyncDisposableStackUseDisposingTwice();
assert.compareArray(valuesNormal, [43, 42]);
});

View File

@ -0,0 +1,39 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
Call disposeAsync() twice without await.
includes: [asyncHelpers.js, compareArray.js]
flags: [async]
features: [explicit-resource-management]
---*/
asyncTest(async function() {
let valuesNormal = [];
async function TestAsyncDisposableStackUseDisposingTwiceWithoutAwait() {
let stack = new AsyncDisposableStack();
const firstDisposable = {
value: 1,
[Symbol.asyncDispose]() {
valuesNormal.push(42);
}
};
const secondDisposable = {
value: 2,
[Symbol.asyncDispose]() {
valuesNormal.push(43);
}
};
stack.use(firstDisposable);
stack.use(secondDisposable);
stack.disposeAsync();
assert.sameValue(stack.disposed, true, 'disposed should be true');
stack.disposeAsync();
};
await TestAsyncDisposableStackUseDisposingTwiceWithoutAwait();
assert.compareArray(valuesNormal, [43, 42]);
});

View File

@ -0,0 +1,56 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: disposeAsync() throws a suppressed error.
includes: [asyncHelpers.js]
flags: [async]
features: [explicit-resource-management]
---*/
asyncTest(async function() {
let firstDisposeError =
new Test262Error('The first Symbol.asyncDispose is throwing!');
let secondDisposeError =
new Test262Error('The second Symbol.asyncDispose is throwing!');
async function TestAsyncDisposableStackUseTwoDisposeMethodsThrow() {
{
let stack = new AsyncDisposableStack();
const firstDisposable = {
value: 1,
[Symbol.asyncDispose]() {
throw firstDisposeError;
}
};
const secondDisposable = {
value: 1,
[Symbol.asyncDispose]() {
throw secondDisposeError;
}
};
stack.use(firstDisposable);
stack.use(secondDisposable);
await stack.disposeAsync();
}
};
await assert.throwsAsync(
SuppressedError,
() => TestAsyncDisposableStackUseTwoDisposeMethodsThrow(),
'An error was suppressed during disposal');
async function RunTestAsyncDisposableStackUseTwoDisposeMethodsThrow() {
try {
await TestAsyncDisposableStackUseTwoDisposeMethodsThrow();
} catch (error) {
assert(
error instanceof SuppressedError,
'error is an instanceof SuppressedError');
assert.sameValue(error.error, firstDisposeError, 'error.error');
assert.sameValue(
error.suppressed, secondDisposeError, 'error.suppressed');
}
}
await RunTestAsyncDisposableStackUseTwoDisposeMethodsThrow();
});

View File

@ -0,0 +1,29 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
Test developer exposed AsyncDisposableStack protype methods disposeAsync().
includes: [asyncHelpers.js, compareArray.js]
flags: [async]
features: [explicit-resource-management]
---*/
asyncTest(async function() {
let valuesNormal = [];
async function TestAsyncDisposableStackUse() {
let stack = new AsyncDisposableStack();
const disposable = {
value: 1,
[Symbol.asyncDispose]() {
valuesNormal.push(42);
}
};
stack.use(disposable);
await stack.disposeAsync();
};
await TestAsyncDisposableStackUse();
assert.compareArray(valuesNormal, [42]);
});

View File

@ -0,0 +1,41 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Test `disposed` accessor property of AsyncDisposableStack.
includes: [asyncHelpers.js]
flags: [async]
features: [explicit-resource-management]
---*/
asyncTest(async function() {
// disposed should be true --------
async function TestDisposableStackDisposedTrue() {
let stack = new AsyncDisposableStack();
const disposable = {
value: 1,
[Symbol.asyncDispose]() {
return 42;
}
};
stack.use(disposable);
stack.dispose();
assert.sameValue(stack.disposed, true, 'disposed should be true');
};
TestDisposableStackDisposedTrue();
// disposed should be false --------
async function TestDisposableStackDisposedFalse() {
let stack = new AsyncDisposableStack();
const disposable = {
value: 1,
[Symbol.asyncDispose]() {
return 42;
}
};
stack.use(disposable);
assert.sameValue(stack.disposed, false, 'disposed should be false');
};
TestDisposableStackDisposedFalse();
});

View File

@ -0,0 +1,22 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Test move() on a disposed-stack.
includes: [asyncHelpers.js]
flags: [async]
features: [explicit-resource-management]
---*/
// move() method on disposed stack --------
asyncTest(async function() {
async function TestAsyncDisposableStackMoveOnDisposedStack() {
let stack = new AsyncDisposableStack();
await stack.disposeAsync();
let newStack = stack.move();
};
await assert.throwsAsync(
ReferenceError, () => TestAsyncDisposableStackMoveOnDisposedStack(),
'Cannot move elements from a disposed stack!');
});

View File

@ -0,0 +1,28 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Test developer exposed AsyncDisposableStack protype method move.
features: [explicit-resource-management]
---*/
// Two stacks should not be the same --------
(function TestAsyncDisposableStackMoveNotSameObjects() {
let stack = new AsyncDisposableStack();
const firstDisposable = {
value: 1,
[Symbol.asyncDispose]() {
return 42;
}
};
const secondDisposable = {
value: 2,
[Symbol.asyncDispose]() {
return 43;
}
};
stack.use(firstDisposable);
stack.use(secondDisposable);
let newStack = stack.move();
assert.notSameValue(stack, newStack);
})();

View File

@ -0,0 +1,27 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Test use() on a disposed stack.
includes: [asyncHelpers.js]
flags: [async]
features: [explicit-resource-management]
---*/
asyncTest(async function() {
async function TestAsyncDisposableStackUseOnDisposedStack() {
let stack = new AsyncDisposableStack();
const disposable = {
value: 1,
[Symbol.asyncDispose]() {
return 42;
}
};
await stack.disposeAsync();
stack.use(disposable);
};
await assert.throwsAsync(
ReferenceError, () => TestAsyncDisposableStackUseOnDisposedStack(),
'Cannot add values to a disposed stack!');
});

View File

@ -0,0 +1,56 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
Test developer exposed AsyncDisposableStack protype methods use().
features: [explicit-resource-management]
---*/
// use() method on a non object --------
function TestAsyncDisposableStackUseWithNonObject() {
let stack = new AsyncDisposableStack();
stack.use(42);
};
assert.throws(
TypeError, () => TestAsyncDisposableStackUseWithNonObject(),
'use() is called on non-object');
// use() method with null [symbol.asyncDispose] --------
function TestAsyncDisposableStackUseWithNullDispose() {
let stack = new AsyncDisposableStack();
const disposable = {
value: 1,
[Symbol.asyncDispose]: null,
};
stack.use(disposable);
};
assert.throws(
TypeError, () => TestAsyncDisposableStackUseWithNullDispose(),
'symbol.asyncDispose is null');
// use() method with undefined [symbol.asyncDispose] --------
function TestAsyncDisposableStackUseWithUndefinedDispose() {
let stack = new AsyncDisposableStack();
const disposable = {
value: 1,
[Symbol.asyncDispose]: undefined,
};
stack.use(disposable);
};
assert.throws(
TypeError, () => TestAsyncDisposableStackUseWithUndefinedDispose(),
'symbol.asyncDispose is undefined');
// use() method when [symbol.asyncDispose] is not callable--------
function TestAsyncDisposableStackUseWithNonCallableDispose() {
let stack = new AsyncDisposableStack();
const disposable = {
value: 1,
[Symbol.asyncDispose]: 42,
};
stack.use(disposable);
};
assert.throws(
TypeError, () => TestAsyncDisposableStackUseWithNonCallableDispose(),
'symbol.asyncDispose is not callable');