Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

4
deps/v8/test/test262/.lint-vpython3 vendored Normal file
View File

@ -0,0 +1,4 @@
wheel: <
name: "infra/python/wheels/pyyaml/${vpython_platform}"
version: "version:5.4.1.chromium.1"
>

26
deps/v8/test/test262/BUILD.gn vendored Normal file
View File

@ -0,0 +1,26 @@
# Copyright 2016 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
group("v8_test262") {
testonly = true
data_deps = [
"../..:d8",
"../../tools:v8_testrunner",
]
data = [
"data/",
"detachArrayBuffer.js",
"harness-abstractmodulesource.js",
"harness-adapt.js",
"harness-adapt-donotevaluate.js",
"harness-agent.js",
"harness-done.js",
"harness-ishtmldda.js",
"test262.status",
"testcfg.py",
"local-tests/",
]
}

5
deps/v8/test/test262/OWNERS vendored Normal file
View File

@ -0,0 +1,5 @@
adamk@chromium.org
syg@chromium.org
# Needed by the test262_import builder
per-file test262.status=v8-ci-autoroll-builder@chops-service-accounts.iam.gserviceaccount.com

72
deps/v8/test/test262/PRESUBMIT.py vendored Normal file
View File

@ -0,0 +1,72 @@
# Copyright 2023 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import pathlib
import platform
from subprocess import STDOUT, PIPE, Popen
# This line is 'magic' in that git-cl looks for it to decide whether to
# use Python3 instead of Python2 when running the code in this file.
USE_PYTHON3 = True
def _CheckLint(input_api, output_api):
root = pathlib.Path(input_api.PresubmitLocalPath())
vpython_spec = root / '.lint-vpython3'
workdir = root / 'data'
lint_exe = workdir / 'tools' / 'lint' / 'lint.py'
test_path = workdir / '..' / 'local-tests' / 'test'
staging_path = (test_path / 'staging').relative_to(workdir)
lint_exceptions = root / 'lint.exceptions'
command = [
'vpython3',
'-vpython-spec',
vpython_spec,
lint_exe,
'--exceptions',
lint_exceptions,
'--features',
staging_path / 'features.txt',
staging_path,
]
proc = Popen(
command,
cwd=workdir,
stderr=STDOUT,
stdout=PIPE,
shell=platform.system() == 'Windows')
output, exit_code = proc.communicate()[0], proc.returncode
if exit_code == 0:
return []
return [
output_api.PresubmitError(
"Test262 lint failed.", long_text=output.decode())
]
def _PyUnitTest(input_api, output_api):
return input_api.RunTests(
input_api.canned_checks.GetUnitTestsRecursively(
input_api,
output_api,
input_api.os_path.join(input_api.PresubmitLocalPath()),
files_to_check=[r'.+_test\.py$'],
files_to_skip=[],
run_on_python2=False,
))
def _CommonChecks(input_api, output_api):
checks = [
_CheckLint,
_PyUnitTest,
]
return sum([check(input_api, output_api) for check in checks], [])
def CheckChangeOnCommit(input_api, output_api):
return _CommonChecks(input_api, output_api)
def CheckChangeOnUpload(input_api, output_api):
return _CommonChecks(input_api, output_api)

20
deps/v8/test/test262/README vendored Normal file
View File

@ -0,0 +1,20 @@
This directory contains code for binding the test262 test suite
into the v8 test harness. The tests are checked out as a dependency from
https://chromium.googlesource.com/external/github.com/tc39/test262
at a revision specified in the DEPS file as 'data' in this directory. They are
fetched with 'gclient sync'. To update to a newer version, please change the
DEPS file.
Using a newer version, e.g. 'deadbeef' may be possible but the tests are only
known to pass (and indeed run) with the DEPS revision. Example:
cd data
git fetch
git checkout deadbeef
If you do update to a newer revision you may have to change the test
harness adapter code since it uses internal functionality from the
harness that comes bundled with the tests. You will most likely also
have to update the test expectation file.

View File

@ -0,0 +1,9 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function $DETACHBUFFER(buffer) {
%ArrayBufferDetach(buffer);
}
$262.detachArrayBuffer = $DETACHBUFFER;

View File

@ -0,0 +1,5 @@
// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
$262.AbstractModuleSource = %GetAbstractModuleSource();

View File

@ -0,0 +1,12 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// V8 has several long-standing bugs where "early errors", i.e. errors that are
// supposed to be thrown at parse time, end up being thrown at runtime instead.
// This file is used to implement the FAIL_PHASE_ONLY outcome as used in
// test/test262/test262.status. Tests marked with this outcome are run in a
// special mode that verifies that a) V8 throws an exception at all, and b) that
// the exception has the correct type, but ignores the fact that they are thrown
// after parsing is done. See crbug.com/v8/8467 for details.
$DONOTEVALUATE = () => {};

101
deps/v8/test/test262/harness-adapt.js vendored Normal file
View File

@ -0,0 +1,101 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function fnGlobalObject() { return (function() { return this; })(); }
var ES5Harness = (function() {
var currentTest = {};
var $this = this;
function Test262Error(id, path, description, codeString,
preconditionString, result, error) {
this.id = id;
this.path = path;
this.description = description;
this.result = result;
this.error = error;
this.code = codeString;
this.pre = preconditionString;
}
Test262Error.prototype.toString = function() {
return this.result + " " + this.error;
}
function registerTest(test) {
if (!(test.precondition && !test.precondition())) {
var error;
try {
var res = test.test.call($this);
} catch(e) {
res = 'fail';
error = e;
}
var retVal = /^s/i.test(test.id)
? (res === true || typeof res == 'undefined' ? 'pass' : 'fail')
: (res === true ? 'pass' : 'fail');
if (retVal != 'pass') {
var precondition = (test.precondition !== undefined)
? test.precondition.toString()
: '';
throw new Test262Error(
test.id,
test.path,
test.description,
test.test.toString(),
precondition,
retVal,
error);
}
}
}
return {
registerTest: registerTest
}
})();
function RealmOperators(realm) {
let $262 = {
evalScript(script) {
return Realm.eval(realm, script);
},
createRealm() {
return RealmOperators(Realm.createAllowCrossRealmAccess());
},
global: Realm.eval(realm, 'this'),
gc() {
v8GC();
}
};
$262.global.$262 = $262;
return $262;
}
var $262 = RealmOperators(Realm.current());

118
deps/v8/test/test262/harness-agent.js vendored Normal file
View File

@ -0,0 +1,118 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
$262.agent = (function () {
var workers = [];
var i32a = null;
var pendingReports = [];
// Agents call Atomics.wait on this location to sleep.
var SLEEP_LOC = 0;
// 1 if the started worker is ready, 0 otherwise.
var START_LOC = 1;
// The number of workers that have received the broadcast.
var BROADCAST_LOC = 2;
// Each worker has a count of outstanding reports; worker N uses memory
// location [WORKER_REPORT_LOC + N].
var WORKER_REPORT_LOC = 3;
function workerScript(script) {
return `
var index;
var i32a = null;
var broadcasts = [];
var pendingReceiver = null;
function handleBroadcast() {
if (pendingReceiver && broadcasts.length > 0) {
pendingReceiver.apply(null, broadcasts.shift());
pendingReceiver = null;
}
};
var onmessage = function({data:msg}) {
switch (msg.kind) {
case 'start':
i32a = msg.i32a;
index = msg.index;
(0, eval)(\`${script}\`);
break;
case 'broadcast':
Atomics.add(i32a, ${BROADCAST_LOC}, 1);
broadcasts.push([msg.sab, msg.id]);
handleBroadcast();
break;
}
};
var $262 = {
agent: {
receiveBroadcast(receiver) {
pendingReceiver = receiver;
handleBroadcast();
},
report(msg) {
postMessage(String(msg));
Atomics.add(i32a, ${WORKER_REPORT_LOC} + index, 1);
},
sleep(s) { Atomics.wait(i32a, ${SLEEP_LOC}, 0, s); },
leaving() {},
monotonicNow() {
return performance.now();
}
}
};`;
}
var agent = {
start(script) {
if (i32a === null) {
i32a = new Int32Array(new SharedArrayBuffer(256));
}
var w = new Worker(workerScript(script), {type: 'string'});
w.index = workers.length;
w.postMessage({kind: 'start', i32a: i32a, index: w.index});
workers.push(w);
},
broadcast(sab, id) {
if (!(sab instanceof SharedArrayBuffer)) {
throw new TypeError('sab must be a SharedArrayBuffer.');
}
Atomics.store(i32a, BROADCAST_LOC, 0);
for (var w of workers) {
w.postMessage({kind: 'broadcast', sab: sab, id: id|0});
}
while (Atomics.load(i32a, BROADCAST_LOC) != workers.length) {}
},
getReport() {
for (var w of workers) {
while (Atomics.load(i32a, WORKER_REPORT_LOC + w.index) > 0) {
pendingReports.push(w.getMessage());
Atomics.sub(i32a, WORKER_REPORT_LOC + w.index, 1);
}
}
return pendingReports.shift() || null;
},
sleep(s) { Atomics.wait(i32a, SLEEP_LOC, 0, s); },
monotonicNow() {
return performance.now();
}
};
return agent;
})();

17
deps/v8/test/test262/harness-done.js vendored Normal file
View File

@ -0,0 +1,17 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function $DONE(error) {
if (error) {
if(typeof error === 'object' && error !== null && 'name' in error) {
print('Test262:AsyncTestFailure:' + error.name + ': ' + error.message);
} else {
print('Test262:AsyncTestFailure:Test262Error: ' + String(error));
}
quit(1);
}
print('Test262:AsyncTestComplete');
quit(0);
};

View File

@ -0,0 +1,5 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
$262.IsHTMLDDA = %GetUndetectable();

5
deps/v8/test/test262/lint.exceptions vendored Normal file
View File

@ -0,0 +1,5 @@
# Tests that intentionally violate the project's linting rules (along with a
# space-separated list of the specific rules they violate) should be specified
# in this file.
#
# (see the original file at data/lint.exceptions for more information)

View File

@ -0,0 +1,27 @@
// Copyright (C) 2017 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 23.1.1.1
description: >
The correct error is thrown `Map.prototype.set` throws an error and
the IteratorClose throws an error.
features: [Symbol.iterator]
---*/
var count = 0;
var iterable = {};
iterable[Symbol.iterator] = function() {
return {
next: function() {
return { value: [], done: false };
},
return: function() {
throw new TypeError('ignore');
}
};
};
Map.prototype.set = function() { throw new Test262Error(); }
assert.throws(Test262Error, function() {
new Map(iterable);
});

View File

@ -0,0 +1,35 @@
// Copyright 2012 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es5id: 12.1.1_1
description: Tests that the this-value is ignored in DateTimeFormat.
author: Norbert Lindenberg
includes: [testIntl.js]
---*/
testWithIntlConstructors(function (Constructor) {
var obj, newObj;
if (Constructor === Intl.DateTimeFormat) {
obj = new Constructor();
newObj = Intl.DateTimeFormat.call(obj);
if (obj !== newObj) {
$ERROR("Should have modified existing object.");
}
var key = Object.getOwnPropertySymbols(newObj)[0];
if (!(newObj[key] instanceof Intl.DateTimeFormat)) {
$ERROR("Should have installed a DateTimeFormat instance.");
}
return true;
}
// variant 1: use constructor in a "new" expression
obj = new Constructor();
newObj = Intl.DateTimeFormat.call(obj);
if (obj === newObj) {
$ERROR("DateTimeFormat object created with \"new\" was not ignored as this-value.");
}
return true;
});

View File

@ -0,0 +1,35 @@
// Copyright 2012 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es5id: 11.1.1_1
description: Tests that the this-value is ignored in NumberFormat.
author: Norbert Lindenberg
includes: [testIntl.js]
---*/
testWithIntlConstructors(function (Constructor) {
var obj, newObj;
if (Constructor === Intl.NumberFormat) {
obj = new Constructor();
newObj = Intl.NumberFormat.call(obj);
if (obj !== newObj) {
$ERROR("Should have modified existing object.");
}
var key = Object.getOwnPropertySymbols(newObj)[0];
if (!(newObj[key] instanceof Intl.NumberFormat)) {
$ERROR("Should have installed a NumberFormat instance.");
}
return true;
}
// variant 1: use constructor in a "new" expression
obj = new Constructor();
newObj = Intl.NumberFormat.call(obj);
if (obj === newObj) {
$ERROR("NumberFormat object created with \"new\" was not ignored as this-value.");
}
return true;
});

View File

@ -0,0 +1,26 @@
/*---
description: Syntax error if `arguments` used in class field (arrow function expression)
esid: sec-class-definitions-static-semantics-early-errors
features: [class, class-fields-public, arrow-function]
flags: [generated]
negative:
phase: early
type: SyntaxError
info: |
Static Semantics: Early Errors
FieldDefinition:
PropertyNameInitializeropt
- It is a Syntax Error if ContainsArguments of Initializer is true.
Static Semantics: ContainsArguments
IdentifierReference : Identifier
1. If the StringValue of Identifier is "arguments", return true.
...
For all other grammatical productions, recurse on all nonterminals. If any piece returns true, then return true. Otherwise return false.
---*/
throw "Test262: This statement should not be evaluated.";
var C = class {
x = () => {
var t = () => { arguments; };
t();
}
}

View File

@ -0,0 +1,33 @@
/*---
description: error if `arguments` in StatementList of eval (direct eval)
esid: sec-performeval-rules-in-initializer
features: [class, class-fields-public, arrow-function]
flags: [generated]
info: |
Static Semantics: Early Errors
FieldDefinition:
PropertyNameInitializeropt
- It is a Syntax Error if ContainsArguments of Initializer is true.
Static Semantics: ContainsArguments
IdentifierReference : Identifier
1. If the StringValue of Identifier is "arguments", return true.
...
For all other grammatical productions, recurse on all nonterminals. If any piece returns true, then return true. Otherwise return false.
---*/
var C = class {
x = () => {
var t = () => { eval("arguments"); };
t();
}
}
assert.throws(SyntaxError, function() {
var c = new C();
c.x();
});

View File

@ -0,0 +1,30 @@
/*---
description: error if `arguments` in StatementList of eval (direct eval)
esid: sec-performeval-rules-in-initializer
features: [class, class-fields-public, arrow-function]
flags: [generated]
info: |
Static Semantics: Early Errors
FieldDefinition:
PropertyNameInitializeropt
- It is a Syntax Error if ContainsArguments of Initializer is true.
Static Semantics: ContainsArguments
IdentifierReference : Identifier
1. If the StringValue of Identifier is "arguments", return true.
...
For all other grammatical productions, recurse on all nonterminals. If any piece returns true, then return true. Otherwise return false.
---*/
var C = class {
x = eval("() => arguments");
}
assert.throws(SyntaxError, function() {
var c = new C();
c.x();
});

View File

@ -0,0 +1,16 @@
// Copyright (C) 2017 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
HTML-like comments are not available in module code
(SingleLineHTMLCloseComment)
esid: sec-html-like-comments
es6id: B1.3
negative:
phase: early
type: SyntaxError
flags: [module]
---*/
-->
function f(){}

View File

@ -0,0 +1,15 @@
// Copyright (C) 2017 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
HTML-like comments are not available in module code
(SingleLineHTMLCloseComment)
esid: sec-html-like-comments
es6id: B1.3
negative:
phase: early
type: SyntaxError
flags: [module]
---*/
-->
function f(){}

View File

@ -0,0 +1,26 @@
/*---
description: Syntax error if `arguments` used in class field (arrow function expression)
esid: sec-class-definitions-static-semantics-early-errors
features: [class, class-fields-public, arrow-function]
flags: [generated]
negative:
phase: early
type: SyntaxError
info: |
Static Semantics: Early Errors
FieldDefinition:
PropertyNameInitializeropt
- It is a Syntax Error if ContainsArguments of Initializer is true.
Static Semantics: ContainsArguments
IdentifierReference : Identifier
1. If the StringValue of Identifier is "arguments", return true.
...
For all other grammatical productions, recurse on all nonterminals. If any piece returns true, then return true. Otherwise return false.
---*/
throw "Test262: This statement should not be evaluated.";
class C {
x = () => {
var t = () => { arguments; };
t();
}
}

View File

@ -0,0 +1,34 @@
/*---
description: error if `arguments` in StatementList of eval (direct eval)
esid: sec-performeval-rules-in-initializer
features: [class, class-fields-public, arrow-function]
flags: [generated]
info: |
Static Semantics: Early Errors
FieldDefinition:
PropertyNameInitializeropt
- It is a Syntax Error if ContainsArguments of Initializer is true.
Static Semantics: ContainsArguments
IdentifierReference : Identifier
1. If the StringValue of Identifier is "arguments", return true.
...
For all other grammatical productions, recurse on all nonterminals. If any piece returns true, then return true. Otherwise return false.
---*/
class C {
x = () => {
var t = () => { eval("arguments"); };
t();
}
}
assert.throws(SyntaxError, function() {
var c = new C();
c.x();
});

View File

@ -0,0 +1,30 @@
/*---
description: error if `arguments` in StatementList of eval (direct eval)
esid: sec-performeval-rules-in-initializer
features: [class, class-fields-public, arrow-function]
flags: [generated]
info: |
Static Semantics: Early Errors
FieldDefinition:
PropertyNameInitializeropt
- It is a Syntax Error if ContainsArguments of Initializer is true.
Static Semantics: ContainsArguments
IdentifierReference : Identifier
1. If the StringValue of Identifier is "arguments", return true.
...
For all other grammatical productions, recurse on all nonterminals. If any piece returns true, then return true. Otherwise return false.
---*/
class C {
x = eval("() => arguments");
}
assert.throws(SyntaxError, function() {
var c = new C();
c.x();
});

View File

@ -0,0 +1 @@
v8-ci-autoroll-builder@chops-service-accounts.iam.gserviceaccount.com

View File

@ -0,0 +1,9 @@
// Copyright (C) 2025 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Unescaped surrogate pairs
features: [RegExp.escape]
---*/
assert.sameValue(RegExp.escape("\ud800\udc00"), "\ud800\udc00", 'Unescaped surrogate pair');

View File

@ -0,0 +1,274 @@
## Proposed language features
#
# This project accepts tests for language proposals that have reached stage 3
# in TC39's standardization process. Those tests should be annotated with a
# dedicated feature flag so that consumers may more easily omit them as
# necessary.
#
# Generally, feature flags should be per proposal, not per individual API
# that a proposal adds. To filter for specific APIs, use the directory
# structure.
#
# https://github.com/tc39/process-document
# Intl.Locale Info
# https://github.com/tc39/proposal-intl-locale-info
Intl.Locale-info
# Intl.NumberFormat V3
# https://github.com/tc39/proposal-intl-numberformat-v3
Intl.NumberFormat-v3
# Legacy RegExp features
# https://github.com/tc39/proposal-regexp-legacy-features
legacy-regexp
# Temporal
# https://github.com/tc39/proposal-temporal
Temporal
# ShadowRealm, née Callable Boundary Realms
# https://github.com/tc39/proposal-realms
ShadowRealm
# Intl.DurationFormat
# https://github.com/tc39/proposal-intl-duration-format
Intl.DurationFormat
# Decorators
# https://github.com/tc39/proposal-decorators
decorators
# Duplicate named capturing groups
# https://github.com/tc39/proposal-duplicate-named-capturing-groups
regexp-duplicate-named-groups
# https://tc39.es/proposal-array-from-async/
Array.fromAsync
# JSON.parse with source
# https://github.com/tc39/proposal-json-parse-with-source
json-parse-with-source
# RegExp.escape
# https://github.com/tc39/proposal-regex-escaping
RegExp.escape
# Explicit Resource Management
# https://github.com/tc39/proposal-explicit-resource-management
explicit-resource-management
# Float16Array + Math.f16round
# https://github.com/tc39/proposal-float16array
Float16Array
# Math.sumPrecise
# https://github.com/tc39/proposal-math-sum
Math.sumPrecise
# Source Phase Imports
## https://github.com/tc39/proposal-source-phase-imports
source-phase-imports
## test262 special specifier
source-phase-imports-module-source
# Uint8Array Base64
# https://github.com/tc39/proposal-arraybuffer-base64
uint8array-base64
# Atomics.pause
# https://github.com/tc39/proposal-atomics-microwait
Atomics.pause
# Error.isError
# https://github.com/tc39/proposal-is-error
Error.isError
# Deferred import evaluation
# https://tc39.es/proposal-defer-import-eval
import-defer
# Iterator Sequencing
# https://github.com/tc39/proposal-iterator-sequencing
iterator-sequencing
# Time Zone Canonicalization
# https://github.com/tc39/proposal-canonical-tz
canonical-tz
## Standard language features
#
# Language features that have been included in a published version of the
# ECMA-262 specification. These flags are largely maintained for historical
# reasons, though their use for relatively new features (i.e. prior to
# availability across major implementations) is appreciated.
AggregateError
align-detached-buffer-semantics-with-web-reality # https://github.com/tc39/ecma262/pull/2164
arbitrary-module-namespace-names # https://github.com/tc39/ecma262/pull/2154
ArrayBuffer
array-find-from-last
Array.prototype.at
Array.prototype.flat
Array.prototype.flatMap
Array.prototype.includes
Array.prototype.values
Atomics.waitAsync
array-grouping
arraybuffer-transfer
arrow-function
async-iteration
async-functions
Atomics
BigInt
caller
change-array-by-copy
class
class-fields-private
class-fields-private-in
class-fields-public
class-methods-private
class-static-block
class-static-fields-private
class-static-fields-public
class-static-methods-private
coalesce-expression
computed-property-names
const
cross-realm
DataView
DataView.prototype.getFloat32
DataView.prototype.getFloat64
DataView.prototype.getInt16
DataView.prototype.getInt32
DataView.prototype.getInt8
DataView.prototype.getUint16
DataView.prototype.getUint32
DataView.prototype.setUint8
default-parameters
destructuring-assignment
destructuring-binding
dynamic-import
error-cause
exponentiation
export-star-as-namespace-from-module # https://github.com/tc39/ecma262/pull/1174
FinalizationRegistry
for-in-order
for-of
Float32Array
Float64Array
generators
globalThis
hashbang
import-attributes
import.meta
iterator-helpers
Int8Array
Int16Array
Int32Array
Intl-enumeration
intl-normative-optional # https://tc39.es/ecma402/#legacy-constructor
Intl.DateTimeFormat-datetimestyle
Intl.DateTimeFormat-dayPeriod # https://github.com/tc39/ecma402/pull/346
Intl.DateTimeFormat-extend-timezonename
Intl.DateTimeFormat-formatRange
Intl.DateTimeFormat-fractionalSecondDigits # https://github.com/tc39/ecma402/pull/347
Intl.DisplayNames
Intl.DisplayNames-v2
Intl.ListFormat
Intl.Locale
Intl.NumberFormat-unified
Intl.RelativeTimeFormat
Intl.Segmenter
json-modules
json-superset
let
logical-assignment-operators
Map
new.target
numeric-separator-literal
object-rest
object-spread
Object.fromEntries
Object.hasOwn
Object.is
optional-catch-binding
optional-chaining
Promise
Promise.allSettled
Promise.any
Promise.prototype.finally
promise-with-resolvers
promise-try
Proxy
proxy-missing-checks # https://github.com/tc39/ecma262/pull/666
Reflect
Reflect.construct
Reflect.set
Reflect.setPrototypeOf
regexp-dotall
regexp-lookbehind
regexp-match-indices
regexp-modifiers
regexp-named-groups
regexp-unicode-property-escapes
regexp-v-flag
resizable-arraybuffer
rest-parameters
Set
set-methods
SharedArrayBuffer
string-trimming
String.fromCodePoint
String.prototype.at
String.prototype.endsWith
String.prototype.includes
String.prototype.isWellFormed
String.prototype.matchAll
String.prototype.replaceAll
String.prototype.trimEnd
String.prototype.trimStart
String.prototype.toWellFormed
super
Symbol
symbols-as-weakmap-keys
Symbol.asyncIterator
Symbol.hasInstance
Symbol.isConcatSpreadable
Symbol.iterator
Symbol.match
Symbol.matchAll
Symbol.prototype.description
Symbol.replace
Symbol.search
Symbol.species
Symbol.split
Symbol.toPrimitive
Symbol.toStringTag
Symbol.unscopables
tail-call-optimization
template
top-level-await
TypedArray
TypedArray.prototype.at
u180e
Uint8Array
Uint16Array
Uint32Array
Uint8ClampedArray
WeakMap
WeakRef
WeakSet
well-formed-json-stringify
__proto__
__getter__
__setter__
## Test-Harness Features
#
# The rare cases where testing language functionality requires non-standard
# language features, exposed through global-environment functions on the $262
# object, go here.
IsHTMLDDA
host-gc-required

2739
deps/v8/test/test262/test262.status vendored Normal file

File diff suppressed because it is too large Load Diff

292
deps/v8/test/test262/testcfg.py vendored Normal file
View File

@ -0,0 +1,292 @@
# Copyright 2012 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import importlib.machinery
import sys
from functools import cached_property
from pathlib import Path
from testrunner.local import statusfile
from testrunner.local import testsuite
from testrunner.objects import testcase
from testrunner.outproc import base as outproc
from testrunner.outproc import test262
# TODO(littledan): move the flag mapping into the status file
#
# Multiple flags are allowed, separated by space.
FEATURE_FLAGS = {
'Intl.Locale-info': '--harmony-intl-locale-info-func',
'FinalizationRegistry': '--harmony-weak-refs-with-cleanup-some',
'WeakRef': '--harmony-weak-refs-with-cleanup-some',
'host-gc-required': '--expose-gc-as=v8GC',
'IsHTMLDDA': '--allow-natives-syntax',
'import-assertions': '--harmony-import-assertions',
'Temporal': '--harmony-temporal',
'array-find-from-last': '--harmony-array-find-last',
'ShadowRealm': '--harmony-shadow-realm',
'regexp-v-flag': '--harmony-regexp-unicode-sets',
'String.prototype.isWellFormed': '--harmony-string-is-well-formed',
'String.prototype.toWellFormed': '--harmony-string-is-well-formed',
'json-parse-with-source': '--harmony-json-parse-with-source',
'iterator-helpers': '--harmony-iterator-helpers',
'set-methods': '--harmony-set-methods',
'import-attributes': '--harmony-import-attributes',
'regexp-duplicate-named-groups': '--js-regexp-duplicate-named-groups',
'regexp-modifiers': '--js-regexp-modifiers',
'Float16Array': '--js-float16array',
'explicit-resource-management': '--js-explicit-resource-management',
'decorators': '--js-decorators',
'promise-try': '--js-promise-try',
'Atomics.pause': '--js-atomics-pause',
'source-phase-imports': '--js-source-phase-imports --allow-natives-syntax',
'Error.isError': '--js-error-iserror',
'uint8array-base64': '--js-base-64',
'RegExp.escape': '--js-regexp-escape',
}
SKIPPED_FEATURES = set([])
TEST262_DIR = Path(__file__).resolve().parent
BASE_DIR = TEST262_DIR.parents[1]
TEST_262_HARNESS_FILES = ["sta.js", "assert.js"]
TEST_262_NATIVE_FILES = ["detachArrayBuffer.js"]
TEST_262_SUITE_PATH = Path("data") / "test"
TEST_262_HARNESS_PATH = Path("data") / "harness"
TEST_262_TOOLS_ABS_PATH = TEST262_DIR / Path("data") / "tools" / "packaging"
TEST_262_LOCAL_TESTS_PATH = Path("local-tests") / "test"
sys.path.append(str(TEST_262_TOOLS_ABS_PATH))
class VariantsGenerator(testsuite.VariantsGenerator):
def gen(self, test):
flags_set = self._get_flags_set(test)
test_record = test.test_record
# Add a reverse test ensuring that FAIL_PHASE_ONLY is only used for tests
# that actually fail to throw an exception at wrong phase.
phase_variants = ['']
if test.fail_phase_only:
phase_variants.append('-fail-phase-reverse')
for phase_var in phase_variants:
for n, variant in enumerate(self._get_variants(test)):
flags = flags_set[variant][0]
if 'noStrict' in test_record:
yield (variant, flags, str(n) + phase_var)
elif 'onlyStrict' in test_record:
yield (variant, flags + ['--use-strict'], 'strict-%d' % n + phase_var)
else:
yield (variant, flags, str(n))
yield (variant, flags + ['--use-strict'], 'strict-%d' % n + phase_var)
class TestLoader(testsuite.JSTestLoader):
@cached_property
def local_staging_implementations(self):
return set()
@property
def test_dirs(self):
self.reset_local_implementations_filtering()
return [
self.test_root,
self.suite.root / TEST_262_LOCAL_TESTS_PATH,
]
def reset_local_implementations_filtering(self):
self.local_staging_implementations.clear()
@property
def excluded_suffixes(self):
return {"_FIXTURE.js"}
@property
def excluded_dirs(self):
return {"intl402", "Intl402"} if self.test_config.noi18n else set()
def _should_filter_by_test(self, test):
if test.has_local_staging_implementation:
if test.path_js in self.local_staging_implementations:
print(f"Skipping test {test.path_js} as it has a local implementation")
return True
self.local_staging_implementations.add(test.path_js)
features = test.test_record.get("features", [])
return SKIPPED_FEATURES.intersection(features)
class TestSuite(testsuite.TestSuite):
def __init__(self, ctx, *args, **kwargs):
super(TestSuite, self).__init__(ctx, *args, **kwargs)
self.test_root = self.root / TEST_262_SUITE_PATH
# TODO: this makes the TestLoader mutable, refactor it.
self._test_loader.test_root = self.test_root
self.harnesspath = self.root / TEST_262_HARNESS_PATH
self.harness = [self.harnesspath / f for f in TEST_262_HARNESS_FILES]
self.harness += [self.root / "harness-adapt.js"]
self.local_test_root = self.root / TEST_262_LOCAL_TESTS_PATH
self.parse_test_record = self._load_parse_test_record()
def _load_parse_test_record(self):
root = TEST_262_TOOLS_ABS_PATH
f = None
try:
loader = importlib.machinery.SourceFileLoader(
"parseTestRecord", f"{root}/parseTestRecord.py")
module = loader.load_module()
return module.parseTestRecord
except Exception as e:
print(f'Cannot load parseTestRecord: {e}')
raise
finally:
if f:
f.close()
def _test_loader_class(self):
return TestLoader
def _test_class(self):
return TestCase
def _variants_gen_class(self):
return VariantsGenerator
class TestCase(testcase.D8TestCase):
def __init__(self, *args, **kwargs):
super(TestCase, self).__init__(*args, **kwargs)
source = self.get_source()
self.test_record = self.suite.parse_test_record(source, self.path)
self._expected_exception = (
self.test_record
.get('negative', {})
.get('type', None)
)
self._async = 'async' in self.test_record.get('flags', [])
# We disallow combining FAIL_PHASE_ONLY with any other fail outcome types.
# Outcome parsing logic in the base class converts all outcomes specified in
# the status file into either FAIL, CRASH or PASS, thus we do not need to
# handle FAIL_OK, FAIL_SLOPPY and various other outcomes.
if self.fail_phase_only:
assert (
statusfile.FAIL not in self.expected_outcomes and
statusfile.CRASH not in self.expected_outcomes), self.name
@property
def fail_phase_only(self):
# The FAIL_PHASE_ONLY is defined in tools/testrunner/local/statusfile.py and
# can be used in status files to mark tests that throw an exception at wrong
# phase, e.g. SyntaxError is thrown at execution phase instead of parsing
# phase. See https://crbug.com/v8/8467 for more details.
return statusfile.FAIL_PHASE_ONLY in self._statusfile_outcomes
@property
def _fail_phase_reverse(self):
return 'fail-phase-reverse' in self.procid
def __needs_harness_agent(self):
return self.path.parts[:2] == ("built-ins", "Atomics")
def _get_files_params(self):
harness_args = []
if "raw" not in self.test_record.get("flags", []):
harness_args = list(self.suite.harness)
return (harness_args +
([self.suite.root /
"harness-agent.js"] if self.__needs_harness_agent() else []) +
([self.suite.root / "harness-ishtmldda.js"]
if "IsHTMLDDA" in self.test_record.get("features", []) else []) +
([self.suite.root /
"harness-abstractmodulesource.js"] if "source-phase-imports"
in self.test_record.get("features", []) else []) +
([self.suite.root / "harness-adapt-donotevaluate.js"]
if self.fail_phase_only and not self._fail_phase_reverse else []) +
([self.suite.root / "harness-done.js"]
if "async" in self.test_record.get("flags", []) else []) +
self._get_includes() +
(["--module"] if "module" in self.test_record else []) +
[self._get_source_path()])
def _get_suite_flags(self):
feature_flags = []
for (feature, flags_string) in FEATURE_FLAGS.items():
if feature in self.test_record.get("features", []):
for flag in flags_string.split(" "):
feature_flags.append(flag)
return (["--ignore-unhandled-promises"] +
(["--throws"] if "negative" in self.test_record else []) +
(["--allow-natives-syntax"] if "detachArrayBuffer.js"
in self.test_record.get("includes", []) else []) + feature_flags +
["--no-arguments"] # disable top-level arguments in d8
)
def _get_includes(self):
return [self._base_path(filename) / filename
for filename in self.test_record.get("includes", [])]
def _base_path(self, filename):
if filename in TEST_262_NATIVE_FILES:
return self.suite.root
else:
return self.suite.harnesspath
def _get_source_path(self):
path = self.suite.local_test_root / self.path_js
if path.exists():
return path
return self.suite.test_root / self.path_js
@cached_property
def has_local_staging_implementation(self):
return (str(self.path_js).startswith("staging")
and (self.suite.local_test_root / self.path_js).exists()
)
@property
def output_proc(self):
if self._expected_exception is not None:
return test262.ExceptionOutProc(self.expected_outcomes,
self._expected_exception,
self._fail_phase_reverse, self._async)
else:
# We only support fail phase reverse on tests that expect an exception.
assert not self._fail_phase_reverse
if self.expected_outcomes == outproc.OUTCOMES_PASS:
return test262.PassNoExceptionOutProc(self._async)
return test262.NoExceptionOutProc(self.expected_outcomes, self._async)
def skip_rdb(self, result):
return not result.has_unexpected_output

52
deps/v8/test/test262/tools/export.py vendored Normal file
View File

@ -0,0 +1,52 @@
#!/usr/bin/env python3
# Copyright 2023 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Pushes changes to test262 inside V8 to the upstream repo."""
from argparse import ArgumentParser
from pathlib import Path
import sys
def main():
parser = ArgumentParser()
parser.add_argument(
'-t',
'--blink-tools-path',
help=("Absolute path to where blink tools are located "
"(usually inside a local chromium checkout)."))
parser.add_argument(
'--config-path',
help="Absolute path to a project configuration json file.",
default=(Path(__file__).parent / 'v8configs.json'))
parser.add_argument(
'--approver',
help="Flag indicating that this run will only approve and merge "
"exisiting PRs. Approval of these PRs needs to be done by an account "
"different from the one that created the PR.",
action="store_true")
args, exporter_args = parser.parse_known_args(sys.argv)
sys.path.append(args.blink_tools_path)
from blinkpy.common import exit_codes
from blinkpy.common.host import Host
from blinkpy.common.path_finder import add_depot_tools_dir_to_os_path
from v8_exporter import V8TestExporter, V8TestApprover
from v8configs import config_from_file
add_depot_tools_dir_to_os_path()
host = Host(project_config_factory=config_from_file(args.config_path))
exporter = (V8TestApprover if args.approver else V8TestExporter)(host)
try:
success = exporter.main(exporter_args[1:])
host.exit(0 if success else 1)
except KeyboardInterrupt:
host.print_('Interrupted, exiting')
host.exit(exit_codes.INTERRUPTED_EXIT_STATUS)
if __name__ == '__main__':
main()

73
deps/v8/test/test262/tools/import.py vendored Normal file
View File

@ -0,0 +1,73 @@
#!/usr/bin/env python3
# Copyright 2023 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Pushes changes to test262 inside V8 to the upstream repo."""
from argparse import ArgumentParser
from pathlib import Path
import sys
def main():
parser = ArgumentParser()
parser.add_argument(
'-t',
'--blink-tools-path',
help=("Absolute path to where blink tools are located "
"(usually inside a local chromium checkout)."))
parser.add_argument(
'--config-path',
help="Absolute path to a project configuration json file.",
default=(Path(__file__).parent / 'v8configs.json'))
parser.add_argument(
'--phase',
help=("Phase of the import process to run. One of 'ALL', 'PREBUILD', "
"'POSTBUILD', 'UPLOAD'. ALL will run all phases; suitable for "
"local runs. PREBUILD and POSTBUILD are to be used when building "
"and running the tests is delegated to a proper builder. UPLOAD is "
"used for creating and uploading the CL for the import. UPLOAD is "
"deferred to the recipe on the import builder. This importer "
"script gets called twice on the builder, first with PREBUILD and "
"second with POSTBUILD. Build and UPLOAD phases are deferred to "
"the recipe on the builder."),
choices=['ALL', 'PREBUILD', 'POSTBUILD', 'UPLOAD'],
default='ALL')
parser.add_argument(
'--test262-failure-file',
help=('Absolute path to a file with names of the test to be skipped for '
'this import. Used only in PREBUILD phase.'),
default=None)
parser.add_argument(
'--v8-test262-last-revision',
help=('Used only in POSTBUILD when called separately. The old revision was'
' overwritten at this point by the PREBUILD phase.'),
default=None)
args, exporter_args = parser.parse_known_args(sys.argv)
sys.path.append(args.blink_tools_path)
from blinkpy.common import exit_codes
from blinkpy.common.host import Host
from blinkpy.common.path_finder import add_depot_tools_dir_to_os_path
from v8configs import config_from_file
from v8_importer import V8TestImporter
add_depot_tools_dir_to_os_path()
host = Host(project_config_factory=config_from_file(args.config_path))
importer = V8TestImporter(
phase=args.phase,
host=host,
test262_failure_file=args.test262_failure_file,
v8_test262_last_rev=args.v8_test262_last_revision)
try:
success = importer.main(exporter_args[1:])
host.exit(0 if success else 1)
except KeyboardInterrupt:
host.print_('Interrupted, exiting')
host.exit(exit_codes.INTERRUPTED_EXIT_STATUS)
if __name__ == '__main__':
main()

59
deps/v8/test/test262/tools/mocks.py vendored Normal file
View File

@ -0,0 +1,59 @@
# Copyright 2024 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Contains empty mocks for all blinkpy dependencies. When importing this module
all the necessary blinkpy imports are resolved to these mocks."""
import sys
sys.modules['blinkpy.w3c.local_wpt'] = __import__('mocks')
class LocalRepo:
pass
sys.modules['blinkpy.w3c.wpt_github'] = __import__('mocks')
class GitHubRepo:
pass
PROVISIONAL_PR_LABEL = 'provisional'
sys.modules['blinkpy.w3c.chromium_finder'] = __import__('mocks')
def absolute_chromium_dir():
pass
sys.modules['blinkpy.w3c.chromium_configs'] = __import__('mocks')
class ProjectConfig:
pass
sys.modules['blinkpy.common.system.log_utils'] = __import__('mocks')
def configure_logging():
pass
sys.modules['blinkpy.w3c.common'] = __import__('mocks')
def read_credentials():
pass
sys.modules['blinkpy.w3c.test_importer'] = __import__('mocks')
class TestImporter:
def __init__(self, *args, **kwargs):
pass

View File

@ -0,0 +1,86 @@
# Copyright 2023 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from requests.exceptions import HTTPError
from blinkpy.w3c.test_exporter import TestExporter
from blinkpy.w3c.wpt_github import GitHubError
import logging
_log = logging.getLogger(__name__)
PR_APPROVAL_LOGIN = 'test262-merge-bot'
class BaseV8TestExporter(TestExporter):
def export_in_flight_changes(self, pr_events) -> bool:
"""Test262 exporter ignores in-flight changes."""
pass
class V8TestExporter(BaseV8TestExporter):
def merge_pull_request(self, pull_request):
"""Exporter mode does not merge any PRs. We only create them."""
pass
class V8TestApprover(BaseV8TestExporter):
def merge_pull_request(self, pull_request):
"""Merges a pull request only if in approver mode."""
self.approve(pull_request.number)
super().merge_pull_request(pull_request)
def approve(self, pr_number):
"""Approves a PR.
Chromium/WPT exports are self approved via a web hook with self
approve functionality from an external github project
(https://github.com/web-platform-tests/wpt-pr-bot).
We will mimic the same behavior by sending an approve request just
before we attempt a second pass merge.
"""
if not self.is_approvable(pr_number):
return
body = {
'body': ('The review process for this patch is being conducted in '
'the V8 project.'),
'event': 'APPROVE',
'comments': [],
}
try:
response = self.github.request(
self.pr_path(pr_number), method='POST', body=body)
except HTTPError as e:
response = e.response
_log.error('Failed to approve PR %d: %s', pr_number, response.text)
def pr_path(self, pr_number):
return (f'/repos/{self.github.gh_org}/{self.github.gh_repo_name}'
f'/pulls/{pr_number}/reviews')
def is_approvable(self, pr_number):
"""Validates approval requirements."""
try:
response = self.github.request(self.pr_path(pr_number), method='GET')
reviews = response.data
reviewed_by_bot = any(
review['user']['login'] == PR_APPROVAL_LOGIN for review in reviews)
if reviewed_by_bot:
_log.info('PR %d already approved by us', pr_number)
return False
except HTTPError as e:
response = e.response
_log.error('Failed to get PR %d: %s', pr_number, response.text)
return False
return True
def create_or_update_pr_from_landed_commit(self, commit):
"""Approver mode does not create any PRs"""
pass

View File

@ -0,0 +1,391 @@
# Copyright 2023 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from abc import ABC, abstractmethod
from enum import Enum
from pathlib import Path
import argparse
import logging
import re
import shutil
import sys
from blinkpy.common.system.log_utils import configure_logging
from blinkpy.w3c.common import read_credentials
TEST_FILE_REFERENCE_IN_STATUS_FILE = re.compile("^\s*'(.*)':.*,$")
TEST262_FAILURE_LINE = re.compile("=== test262/(.*) ===")
TEST262_PATTERN = re.compile('^test/(.*)\.[^\s]*$')
TEST262_RENAME_PATTERN = re.compile('^R[^\s]*\s*([^\s]*)\s*([^\s]*)$')
TEST262_REPO_URL = 'https://chromium.googlesource.com/external/github.com/tc39/test262'
V8_TEST262_ROLLS_META_BUG = 'v8:7834'
_log = logging.getLogger(__file__)
class GitFileStatus(Enum):
ADDED = 'A'
DELETED = 'D'
MODIFIED = 'M'
UNKNOWN = 'X'
class V8TestImporter():
def __init__(self,
phase,
host,
test262_github=None,
test262_failure_file=None,
v8_test262_last_rev=None):
self.host = host
self.github = test262_github
self.project_config = host.project_config
self.project_root = Path(self.project_config.project_root)
self.test262_status_file = self.project_root / 'test' / 'test262' / 'test262.status'
self.phase = phase
self.test262_failure_file = test262_failure_file
self.v8_test262_last_rev = v8_test262_last_rev
def parse_args(self, argv):
parser = argparse.ArgumentParser()
parser.description = __doc__
parser.add_argument(
'-v',
'--verbose',
action='store_true',
help='log extra details that may be helpful when debugging')
parser.add_argument(
'--credentials-json',
help='A JSON file with GitHub credentials, '
'generally not necessary on developer machines')
return parser.parse_args(argv)
def main(self, argv=None):
options = self.parse_args(argv)
self.verbose = options.verbose
log_level = logging.DEBUG if self.verbose else logging.INFO
configure_logging(logging_level=log_level, include_time=True)
credentials = read_credentials(self.host, options.credentials_json)
gh_user = credentials.get('GH_USER')
gh_token = credentials.get('GH_TOKEN')
if not gh_user or not gh_token:
_log.warning('You have not set your GitHub credentials. This '
'script may fail with a network error when making '
'an API request to GitHub.')
_log.warning('See https://chromium.googlesource.com/chromium/src'
'/+/main/docs/testing/web_platform_tests.md'
'#GitHub-credentials for instructions on how to set '
'your credentials up.')
self.github = self.project_config.github_factory(self.host, gh_user,
gh_token)
test262_rev = self.fetch_test262(gh_token)
v8_test262_rev = (
self.v8_test262_last_rev or self.find_current_test262_rev())
if self.run_prebuild_phase():
if test262_rev == v8_test262_rev:
_log.info(f'No changes to import. {test262_rev} == {v8_test262_rev}')
return False
_log.info(f'Importing test262@{test262_rev} to V8')
self.roll_as_dependency(test262_rev)
self.overwrite_files()
self.sync_folders(v8_test262_rev, test262_rev)
failure_lines = []
if self.run_build_phase():
failure_lines = self.build_and_test()
# We either have the lines from the build phase or we read them from a file
# provided by the executor of POSTBUILD phase.
failure_lines = failure_lines or self.failure_lines_from_file()
if self.run_postbuild_phase():
self.update_status_file(v8_test262_rev, test262_rev, failure_lines)
# Output the import range for the recipe to pick up.
print(f'{TEST262_REPO_URL}/+log/{v8_test262_rev[:8]}..{test262_rev[:8]}')
if self.run_upload_phase():
self.commit_and_upload_changes(v8_test262_rev, test262_rev)
# TODO: Create bug if status update yields a skip block
return True
@property
def test262_path(self):
return Path(self.local_test262.path)
def run_prebuild_phase(self):
return self.phase in ['ALL', 'PREBUILD']
def run_build_phase(self):
return self.phase in ['ALL']
def run_postbuild_phase(self):
return self.phase in ['ALL', 'POSTBUILD']
def run_upload_phase(self):
return self.phase in ['ALL', 'UPLOAD']
def fetch_test262(self, gh_token):
_log.info(f'Fetching test262')
self.local_test262 = self.project_config.local_repo_factory(
self.host, gh_token=gh_token)
self.local_test262.fetch()
self.test262_git = self.host.git(self.test262_path)
return self.test262_git.latest_git_commit()
def find_current_test262_rev(self):
_log.info(f'Finding current test262 revision in V8')
return self.host.executive.run_command(
['gclient', 'getdep', '-r', 'test/test262/data'],
cwd=self.project_root).splitlines()[-1].strip()
def roll_as_dependency(self, test262_rev):
self.host.executive.run_command(
['gclient', 'setdep', '-r', f'test/test262/data@{test262_rev}'],
cwd=self.project_root)
def overwrite_files(self):
for file in self.project_config.files_to_copy:
_log.info(f'Overwriting {file.destination} with {file.source}')
shutil.copyfile(
Path(self.local_test262.path) / file.source,
self.project_root / file.destination)
def sync_folders(self, v8_test262_rev, test262_rev):
for folder in self.project_config.paths_to_sync:
_log.info(f'Sync {folder.destination} with {folder.source}')
destination = self.project_root / folder.destination
for f in destination.glob('./**/*'):
if f.is_file() and not self.is_git_sync_exception(f):
relative_path = f.relative_to(destination)
source_file = self.test262_path / folder.source / relative_path
status = self.get_git_file_status(v8_test262_rev, test262_rev,
source_file)
self.update_file(f, status, source_file)
def is_git_sync_exception(self, file):
return file.name == 'features.txt'
def get_git_file_status(self, v8_test262_rev, test262_rev, source_file):
status_line = self.test262_git.run([
'diff', '--name-status', v8_test262_rev, test262_rev, '--', source_file
]).splitlines()
assert len(status_line) < 2, f'Expected zero or one line, got {status_line}'
if len(status_line) == 0:
return GitFileStatus.UNKNOWN
return GitFileStatus(status_line[0][0])
def update_file(self, local_file, status, source_file):
gfs = GitFileStatus
if status in [gfs.ADDED, gfs.DELETED, gfs.MODIFIED]:
_log.info(f'{local_file} has counterpart in Test262. Deleting.')
local_file.unlink()
else:
_log.warning(
f'{local_file} has no counterpart in Test262. '
'Maybe it was never exported?'
)
def build_and_test(self):
"""Builds and run test262 tests V8."""
_log.info('Building V8')
build_config = 'x64.release'
self.host.executive.run_command(
[sys.executable, 'tools/dev/gm.py', build_config],
cwd=self.project_root)
_log.info('Running test262 tests')
test_results = self.host.executive.run_command(
[
sys.executable, 'tools/run-tests.py',
f'--outdir=out/{build_config}', '--progress=verbose',
'--exit-after-n-failures=0', 'test262'
],
error_handler=testing_error_handler,
cwd=self.project_root).splitlines()
failure_matches = [TEST262_FAILURE_LINE.match(l) for l in test_results]
return uniq(m.group(1) for m in failure_matches if m)
def failure_lines_from_file(self):
if not self.test262_failure_file:
_log.warning('No failure file provided. Skipping.')
return []
with open(self.test262_failure_file, 'r') as r_file:
return r_file.readlines()
def update_status_file(self, v8_test262_rev, test262_rev, failure_lines):
_log.info(f'Updating status file')
updated_status = self.remove_and_rename(v8_test262_rev, test262_rev)
added_lines = self.failed_tests_to_status_lines(failure_lines)
if added_lines:
updated_status = self.rewrite_status_file_content(updated_status,
added_lines,
v8_test262_rev,
test262_rev)
with open(self.test262_status_file, 'w') as w_file:
w_file.writelines(updated_status)
def remove_and_rename(self, v8_test262_rev, test262_rev):
remover = DeletedTestsRemover(self, v8_test262_rev, test262_rev)
renamer = RenamedTestsUpdater(self, v8_test262_rev, test262_rev)
def updated_line(line):
return remover.updated_line(renamer.updated_line(line))
updated_status = [updated_line(line) for line in self.status_file_lines()]
return [line for line in updated_status if line is not None]
def status_file_lines(self):
with open(self.test262_status_file, 'r') as r_file:
return r_file.readlines()
def failed_tests_to_status_lines(self, failed_tests):
# Transform the list of failed tests into a list of status file lines.
return [f" '{test}': [FAIL],\n" for test in failed_tests]
def rewrite_status_file_content(self, updated_status, added_lines,
v8_test262_rev, test262_rev):
# Reassemble the status file with the new tests added.
# TODO(liviurau): This is easy to unit test. Add unit tests.
status_lines_before_eof = updated_status[:-2]
eof_status_lines = updated_status[-2:]
assert eof_status_lines == [
'\n', ']\n'
], f'Unexpected status file eof. {eof_status_lines}'
import_header_lines = [
'\n####\n', f'# Import test262@{test262_rev[:8]}\n',
f'# {TEST262_REPO_URL}/+log/{v8_test262_rev[:8]}..{test262_rev[:8]}\n'
]
new_failing_tests_lines = ['[ALWAYS, {\n'] + added_lines + [
'}],\n', f'# End import test262@{test262_rev[:8]}\n', '####\n'
]
return (status_lines_before_eof + import_header_lines +
new_failing_tests_lines + eof_status_lines)
def commit_and_upload_changes(self, v8_test262_rev, test262_rev):
_log.info('Committing changes.')
self.project_git.run([
'commit',
'-a',
'-m',
'[test262] Roll test262',
'-m',
f'{TEST262_REPO_URL}/+log/{v8_test262_rev[:8]}..{test262_rev[:8]}',
'-m',
'no-export: true',
])
_log.info('Uploading changes.')
self.project_git.run([
'cl',
'upload',
'--bypass-hooks',
'-f',
'-b',
V8_TEST262_ROLLS_META_BUG,
'-d',
])
_log.info(f'Issue: {self.project_git.run(["cl", "issue"]).strip()}')
def uniq(lst):
"""Return a list with unique elements from the input list."""
return sorted(set(lst))
def testing_error_handler(error):
"""Error handler that does nothing; used to suppress errors."""
pass
def relative_test_name(name):
"""Remove the test262 prefix from the test name."""
return re.sub(TEST262_PATTERN, r'\1', name)
class StatusFileUpdater(ABC):
def __init__(self, importer, v8_test262_rev, test262_rev, diff_args):
self.importer = importer
self.diff_args = diff_args
self.to_update = self.collect_updateable_tests(v8_test262_rev, test262_rev)
def updated_line(self, line):
test_name_result = TEST_FILE_REFERENCE_IN_STATUS_FILE.match(line)
if test_name_result:
return self.update_test_line(line, test_name_result)
return line
def collect_updateable_tests(self, v8_test262_rev, test262_rev):
lines = self.importer.test262_git.run([
'diff', *self.diff_args, v8_test262_rev, test262_rev, '--', 'test'
]).splitlines()
return self.process_git_output(lines)
@abstractmethod
def process_git_output(self, lines):
pass
@abstractmethod
def update_test_line(self, line, test_name_result):
pass
class DeletedTestsRemover(StatusFileUpdater):
def __init__(self, importer, v8_test262_rev, test262_rev):
super().__init__(importer, v8_test262_rev, test262_rev,
['--name-only', '--diff-filter=D'])
def process_git_output(self, lines):
return [
relative_test_name(line)
for line in lines
if TEST262_PATTERN.match(line)
]
def update_test_line(self, line, test_name_result):
test_name = test_name_result.group(1)
if test_name not in self.to_update:
return line
_log.info(f'... removing {test_name}')
return None
class RenamedTestsUpdater(StatusFileUpdater):
def __init__(self, importer, v8_test262_rev, test262_rev):
super().__init__(importer, v8_test262_rev, test262_rev,
['--name-status', '--diff-filter=R'])
def process_git_output(self, lines):
search_renames = [re.search(TEST262_RENAME_PATTERN, line) for line in lines]
renames = {
rename.group(1): rename.group(2) for rename in search_renames if rename
}
return {
relative_test_name(key): relative_test_name(value)
for key, value in renames.items()
if TEST262_PATTERN.match(key) and TEST262_PATTERN.match(value)
}
def update_test_line(self, line, test_name_result):
old_name = test_name_result.group(1)
new_name = self.to_update.get(old_name)
if not new_name:
return line
_log.info(f'... updating {old_name} to {new_name}')
return line.replace(old_name, new_name)

View File

@ -0,0 +1,190 @@
# Copyright 2024 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import mocks
import textwrap
import unittest
from pyfakefs import fake_filesystem_unittest
from v8_importer import (DeletedTestsRemover, GitFileStatus,
RenamedTestsUpdater, V8TestImporter)
from v8configs import to_object
fake_host = to_object({
'project_config': {
'project_root':
'.',
'paths_to_sync': [{
"source": "test/staging",
"destination": "test/test262/local-tests/test/staging"
}]
},
})
V8_REVISION = 'abcdef123456'
TEST262_REVISION = '123456abcdef'
class Test_TestV8Importer(fake_filesystem_unittest.TestCase):
def test_phases(self):
importer = V8TestImporter('ALL', fake_host)
self.assertTrue(importer.run_prebuild_phase())
self.assertTrue(importer.run_build_phase())
self.assertTrue(importer.run_postbuild_phase())
self.assertTrue(importer.run_upload_phase())
importer = V8TestImporter('PREBUILD', fake_host)
self.assertTrue(importer.run_prebuild_phase())
self.assertFalse(importer.run_build_phase())
self.assertFalse(importer.run_postbuild_phase())
self.assertFalse(importer.run_upload_phase())
importer = V8TestImporter('POSTBUILD', fake_host)
self.assertFalse(importer.run_prebuild_phase())
self.assertFalse(importer.run_build_phase())
self.assertTrue(importer.run_postbuild_phase())
self.assertFalse(importer.run_upload_phase())
importer = V8TestImporter('UPLOAD', fake_host)
self.assertFalse(importer.run_prebuild_phase())
self.assertFalse(importer.run_build_phase())
self.assertFalse(importer.run_postbuild_phase())
self.assertTrue(importer.run_upload_phase())
def test_sync_folders(self):
self.setUpPyfakefs(allow_root_user=True)
destination = 'test/test262/local-tests/test/staging'
self.fs.create_file(f'{destination}/test1.js')
self.fs.create_file(f'{destination}/features.txt')
self.fs.create_file(f'{destination}/f1/test1.js')
self.fs.create_file(f'{destination}/f1/test2.js')
def get_git_file_status(*args):
path = str(args[2])
self.assertFalse(path.endswith('features.txt'))
return GitFileStatus.ADDED if path.endswith(
'test1.js') else GitFileStatus.UNKNOWN
importer = V8TestImporter('X', fake_host)
importer.local_test262 = to_object({
'path': '.',
})
importer.get_git_file_status = get_git_file_status
importer.sync_folders(V8_REVISION, TEST262_REVISION)
self.assertFalse(self.fs.exists(f'{destination}/test1.js'))
self.assertTrue(self.fs.exists(f'{destination}/features.txt'))
self.assertFalse(self.fs.exists(f'{destination}/f1/test1.js'))
self.assertTrue(self.fs.exists(f'{destination}/f1/test2.js'))
def test_remove_and_rename_tests(self):
self.setUpPyfakefs(allow_root_user=True)
self.fs.create_file(
'test/test262/test262.status',
contents=textwrap.dedent("""\
n'importe quoi
...
'folder1/sometest1': [FAIL],
'deleted_testname': [FAIL],
'renamed_testname': [FAIL],
'folder2/sometest1': [FAIL],
'folder2/sometest2': [FAIL],
...
"""))
importer = V8TestImporter('X', fake_host)
importer.test262_git = to_object({
'run':
lambda *args: 'test/deleted_testname.js\n'
'R001 test/renamed_testname.js test/updated_testname.js\n',
})
tests = importer.remove_and_rename(V8_REVISION, TEST262_REVISION)
self.assertEquals(
textwrap.dedent("""\
n'importe quoi
...
'folder1/sometest1': [FAIL],
'updated_testname': [FAIL],
'folder2/sometest1': [FAIL],
'folder2/sometest2': [FAIL],
...
"""), ''.join(tests))
def test_failed_tests_to_status_lines(self):
importer = V8TestImporter('X', fake_host)
result = importer.failed_tests_to_status_lines(['test1', 'test2'])
self.assertSequenceEqual([" 'test1': [FAIL],\n", " 'test2': [FAIL],\n"],
result)
def test_rewrite_status_file_content(self):
# Below \n is used inside the text block to avoid a trailing whitespace
# check
updated_status = textwrap.dedent("""\
some_testname
some random line
some other testname\n
]
""")
updated_status = updated_status.splitlines(keepends=True)
added_lines = [' new test 1\n', ' new test 2\n']
importer = V8TestImporter('X', fake_host)
result = importer.rewrite_status_file_content(updated_status, added_lines,
V8_REVISION, TEST262_REVISION)
self.assertEquals(textwrap.dedent("""\
some_testname
some random line
some other testname\n
####
# Import test262@123456ab
# https://chromium.googlesource.com/external/github.com/tc39/test262/+log/abcdef12..123456ab
[ALWAYS, {
new test 1
new test 2
}],
# End import test262@123456ab
####\n
]
"""), ''.join(result))
def test_deletion_updater(self):
importer = V8TestImporter('X', fake_host)
importer.test262_git = to_object({
'run': lambda *args: textwrap.dedent("""\
test/should_not_match.js extra garbage
test/should_not_match2.js
test/some_testname.js
practically garbage
"""),
})
updater = DeletedTestsRemover(importer, 'a', 'b')
self.assertEquals(['some_testname'], updater.to_update)
def test_rename_updater(self):
importer = V8TestImporter('X', fake_host)
importer.test262_git = to_object({
'run':
lambda *args: textwrap.dedent("""\
M test/should_not_match.js test/should_not_match.js
test/should_not_match2.js
R001 test/rename_testname.js test/updated_testname.js
R002 test/folder1/rename_testname.js test/folder2/updated_testname.js
practically garbage
"""),
})
updater = RenamedTestsUpdater(importer, 'a', 'b')
expected = {
'rename_testname': 'updated_testname',
'folder1/rename_testname': 'folder2/updated_testname',
}
self.assertEquals(expected, updater.to_update)
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,45 @@
{
"github": {
"name": "Test262",
"org": "tc39",
"repo": "test262",
"main_branch": "main",
"patch_path_renames": [
{
"source": "test/test262/local-tests/test/staging/features.txt",
"destination": "features.txt"
},
{
"source": "test/test262/local-tests/test/staging",
"destination": "test/staging"
}
]
},
"gerrit": {
"revision_footer": "Test262-Export-Revision: ",
"relative_tests_path": "test/test262/local-tests/test/staging",
"project": "v8/v8",
"branch": "main"
},
"exporter": {
"pr_label": "v8-export",
"committer_email": "V8 Test262 Sync",
"committer_name": "v8-test262-autoroller@chromium.org",
"pr_updated_comment": "Successfully updated Test262 GitHub pull request with new revision \"{subject}\": {pr_url}",
"inflight_cl_comment": "Exportable changes to test262 were detected in this CL and a pull request in the upstream repo has been made: {pr_url}.\n\nWhen this CL lands, the bot will automatically merge the PR on GitHub if the required GitHub checks pass."
},
"importer": {
"files_to_copy": [
{
"source": "features.txt",
"destination": "test/test262/local-tests/test/staging/features.txt"
}
],
"paths_to_sync": [
{
"source": "test/staging",
"destination": "test/test262/local-tests/test/staging"
}
]
}
}

122
deps/v8/test/test262/tools/v8configs.py vendored Normal file
View File

@ -0,0 +1,122 @@
# Copyright 2023 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Contains all project-specific configuration and entities for V8/Tets262 host."""
import json
from functools import cached_property
from blinkpy.w3c.local_wpt import LocalRepo
from blinkpy.w3c.wpt_github import GitHubRepo, PROVISIONAL_PR_LABEL
from blinkpy.w3c.chromium_configs import ProjectConfig
def to_object(item):
"""
Recursively convert a dictionary to an object.
"""
if isinstance(item, dict):
return type('_dict_obj', (), {k: to_object(v) for k, v in item.items()})
if isinstance(item, list):
return [to_object(element) for element in item]
return item
class Test262GitHub(GitHubRepo):
def __init__(self,
config,
host,
user=None,
token=None,
pr_history_window=1000):
super(Test262GitHub, self).__init__(
gh_org=config.github.org,
gh_repo_name=config.github.repo,
export_pr_label=config.exporter.pr_label,
provisional_pr_label=PROVISIONAL_PR_LABEL,
host=host,
user=user,
token=token,
pr_history_window=pr_history_window,
main_branch=config.github.main_branch,
min_expected_prs=0)
@property
def skipped_revisions(self):
return [
# Revisions below would choke on github checks. Next revision in v8 repo
# is an effective reland.
"f4e862d29f6aeaa66b5e8e755dc70fe7cb2bc243",
"44702d6ea9c1bce9c95316e3aca41c14e0e8533f",
"87437c41113c2b41aaf5bcbc7fee996df0ab1711",
"b8d49712ab12dd13bee5da34849f8ab7f5309715",
"46c933180967191758afd0427f9d0ba02a4d24a3",
"85bf69fd70e118b1ace64110ed82cb1ff0d58533",
"b97d50ae5e4bb6b5abfc811c0b618d888c3f1377",
"c4946b3e60c597fb9d9cccb2b100647a945e309d",
]
class V8Test262Config(ProjectConfig):
def __init__(self, filesystem, config_file):
super().__init__(filesystem)
with open(config_file, 'r') as f:
self.config = to_object(json.loads(f.read()))
self.relative_tests_path = self.config.gerrit.relative_tests_path
self.revision_footer = self.config.gerrit.revision_footer
self.gerrit_project = self.config.gerrit.project
self.gerrit_branch = self.config.gerrit.branch
self.github_factory = github_factory(self.config)
self.local_repo_factory = local_repo_factory(self.config)
self.files_to_copy = self.config.importer.files_to_copy
self.paths_to_sync = self.config.importer.paths_to_sync
@cached_property
def project_root(self):
from blinkpy.common.system.executive import Executive
return Executive().run_command(
['git', 'rev-parse', '--show-toplevel']).strip()
@property
def test_root(self):
return self.project_root + '/' + self.relative_tests_path
@property
def import_destination_path(self):
return self.test_root
@property
def pr_updated_comment_template(self):
return self.config.exporter.pr_updated_comment
def inflight_cl_comment_template(self):
return self.config.exporter.inflight_cl_comment
def config_from_file(config_file):
return lambda filesystem: V8Test262Config(filesystem, config_file)
def local_repo_factory(config):
return lambda host, gh_token: LocalRepo(
name=config.github.name,
gh_org=config.github.org,
gh_repo_name=config.github.repo,
gh_ssh_url_template='https://{}@github.com/%s/%s.git' %
(config.github.org, config.github.repo),
mirror_url=None,
default_committer_email=config.exporter.committer_email,
default_committer_name=config.exporter.committer_name,
patch_path_renames=[(r.source, r.destination)
for r in config.github.patch_path_renames],
host=host,
gh_token=gh_token,
main_branch=config.github.main_branch,
)
def github_factory(config):
return lambda host, user, token: Test262GitHub(config, host, user, token)