[explicit-resource-management] Add using in bytecode generator

This CL adds `using` to bytecode generator. This CL does not include exception handling and JSDisposableStack methods.
Also, since `using` and `const` have the same behavior (except for disposing resources), we add required checks to the existing code.

Bug: v8:13559
Change-Id: I1d169859cc2a3e16c7cc9078219d5e4a466f4560
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5270855
Commit-Queue: Rezvan Mahdavi Hezaveh <rezvan@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#93014}
This commit is contained in:
Rezvan Mahdavi Hezaveh 2024-03-25 10:22:05 -07:00 committed by test262-merge-bot
parent 961480ac61
commit db7c0d1499
4 changed files with 226 additions and 0 deletions

View File

@ -109,6 +109,10 @@ promise-with-resolvers
# https://github.com/tc39/proposal-set-methods
set-methods
# Explicit Resource Management
# https://github.com/tc39/proposal-explicit-resource-management
explicit-resource-management
## Standard language features
#
# Language features that have been included in a published version of the

View File

@ -0,0 +1,14 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Value shared by all realms
info: |
Unless otherwise specified, well-known symbols values are shared by all
realms.
features: [cross-realm, explicit-resource-management]
---*/
var OSymbol = $262.createRealm().global.Symbol;
assert.sameValue(Symbol.dispose, OSymbol.dispose);

View File

@ -0,0 +1,17 @@
// Copyright (C) 2024 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
`Symbol.dispose` property descriptor
info: |
This property has the attributes { [[Writable]]: false, [[Enumerable]]:
false, [[Configurable]]: false }.
includes: [propertyHelper.js]
features: [explicit-resource-management]
---*/
assert.sameValue(typeof Symbol.dispose, 'symbol');
verifyNotEnumerable(Symbol, 'dispose');
verifyNotWritable(Symbol, 'dispose');
verifyNotConfigurable(Symbol, 'dispose');

View File

@ -0,0 +1,191 @@
// 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 if disposed methods are called in correct syntax.
includes: [compareArray.js]
features: [explicit-resource-management]
---*/
// Block ----------------
let blockValues = [];
(function TestUsingInBlock() {
{
using x = {
value: 1,
[Symbol.dispose]() {
blockValues.push(42);
}
};
blockValues.push(43);
}
})();
assert.compareArray(blockValues, [43, 42]);
// CaseBlock --------------
let caseBlockValues = [];
(function TestUsingInCaseBlock() {
let label = 1;
switch (label) {
case 1:
using x = {
value: 1,
[Symbol.dispose]() {
caseBlockValues.push(42);
}
};
}
caseBlockValues.push(43);
})();
assert.compareArray(caseBlockValues, [42, 43]);
// ForStatement --------------
let forStatementValues = [];
(function TestUsingInForStatement() {
for (let i = 0; i < 3; i++) {
using x = {
value: i,
[Symbol.dispose]() {
forStatementValues.push(this.value);
}
};
}
forStatementValues.push(3);
})();
assert.compareArray(forStatementValues, [0, 1, 2, 3]);
// ForInStatement --------------
let forInStatementValues = [];
(function TestUsingInForInStatement() {
for (let i in [0, 1]) {
using x = {
value: i,
[Symbol.dispose]() {
forInStatementValues.push(this.value);
}
};
}
forInStatementValues.push('2');
})();
assert.compareArray(forInStatementValues, ['0', '1', '2']);
// ForOfStatement --------------
let forOfStatementValues = [];
(function TestUsingInForOfStatement() {
for (let i of [0, 1]) {
using x = {
value: i,
[Symbol.dispose]() {
forOfStatementValues.push(this.value);
}
};
}
forOfStatementValues.push(2);
})();
assert.compareArray(forOfStatementValues, [0, 1, 2]);
// FunctionBody --------------
let functionBodyValues = [];
(function TestUsingInFunctionBody() {
using x = {
value: 1,
[Symbol.dispose]() {
functionBodyValues.push(42);
}
};
using y = {
value: 2,
[Symbol.dispose]() {
functionBodyValues.push(43);
}
};
})();
assert.compareArray(functionBodyValues, [43, 42]);
// GeneratorBody --------------
let generatorBodyValues = [];
function* gen() {
using x = {
value: 1,
[Symbol.dispose]() {
generatorBodyValues.push(42);
}
};
yield x;
}
(function TestUsingInGeneratorBody() {
let iter = gen();
iter.next();
iter.next();
generatorBodyValues.push(43);
})();
assert.compareArray(generatorBodyValues, [42, 43]);
// ClassStaticBlockBody --------------
let classStaticBlockBodyValues = [];
class staticBlockClass {
static {
using x = {
value: 1,
[Symbol.dispose]() {
classStaticBlockBodyValues.push(42);
}
};
}
}
(function TestUsingInAsyncFunctionBody() {
let example = new staticBlockClass();
})();
assert.compareArray(classStaticBlockBodyValues, [42]);
// Derived constructor case
let derivedConstructorValues = [];
class baseClass {
constructor() {
derivedConstructorValues.push(43);
}
}
class subClass extends baseClass {
constructor() {
try {
using x = {
value: 1,
[Symbol.dispose]() {
derivedConstructorValues.push(42);
}
};
} catch (e) {
return;
} finally {
super();
}
}
}
(function TestUsingInDerivedConstructor() {
let example = new subClass();
})();
assert.compareArray(derivedConstructorValues, [42, 43]);
// Lack of dispose method
let values = [];
function TestUsingWithoutDisposeMethod() {
{
using x = {value: 1};
values.push(43);
}
}
assert.throws(TypeError, TestUsingWithoutDisposeMethod, 'No dispose method');