зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1721686 - Add test for exposed interfaces on WebAssembly namespace. r=smaug
This commit modifies test_interfaces.js to also test the exposed interfaces in the WebAssembly namespace. We have conditional features that we'd like to have confidence that we're not accidentally exposing to web content. Currently there are: * WebAssembly exceptions, enabled only in nightly with a default-off pref * mozIntGemm accelerator function, available only in system or addon principals Depends on D120731 Differential Revision: https://phabricator.services.mozilla.com/D120732
This commit is contained in:
Родитель
23fa492341
Коммит
81a19d221d
|
@ -19,6 +19,28 @@
|
|||
//
|
||||
// See createInterfaceMap() below for a complete list of properties.
|
||||
|
||||
// IMPORTANT: Do not change this list without review from
|
||||
// a JavaScript Engine peer!
|
||||
var wasmGlobalEntry = {
|
||||
name: "WebAssembly",
|
||||
insecureContext: true,
|
||||
disabled: !getJSTestingFunctions().wasmIsSupportedByHardware(),
|
||||
};
|
||||
var wasmGlobalInterfaces = [
|
||||
{ name: "Module", insecureContext: true },
|
||||
{ name: "Instance", insecureContext: true },
|
||||
{ name: "Memory", insecureContext: true },
|
||||
{ name: "Table", insecureContext: true },
|
||||
{ name: "Global", insecureContext: true },
|
||||
{ name: "CompileError", insecureContext: true },
|
||||
{ name: "LinkError", insecureContext: true },
|
||||
{ name: "RuntimeError", insecureContext: true },
|
||||
{
|
||||
name: "Function",
|
||||
insecureContext: true,
|
||||
nightly: true,
|
||||
},
|
||||
];
|
||||
// IMPORTANT: Do not change this list without review from
|
||||
// a JavaScript Engine peer!
|
||||
var ecmaGlobals = [
|
||||
|
@ -76,7 +98,7 @@ var ecmaGlobals = [
|
|||
"WeakMap",
|
||||
"WeakRef",
|
||||
"WeakSet",
|
||||
{ name: "WebAssembly", optional: true },
|
||||
wasmGlobalEntry,
|
||||
];
|
||||
// IMPORTANT: Do not change the list above without review from
|
||||
// a JavaScript Engine peer!
|
||||
|
@ -265,16 +287,37 @@ var interfaceNamesInGlobalScope = [
|
|||
];
|
||||
// IMPORTANT: Do not change the list above without review from a DOM peer!
|
||||
|
||||
function createInterfaceMap({
|
||||
isNightly,
|
||||
isEarlyBetaOrEarlier,
|
||||
isRelease,
|
||||
isDesktop,
|
||||
isAndroid,
|
||||
isInsecureContext,
|
||||
isFennec,
|
||||
isCrossOriginIsolated,
|
||||
}) {
|
||||
function entryDisabled(
|
||||
entry,
|
||||
{
|
||||
isNightly,
|
||||
isEarlyBetaOrEarlier,
|
||||
isRelease,
|
||||
isDesktop,
|
||||
isAndroid,
|
||||
isInsecureContext,
|
||||
isFennec,
|
||||
isCrossOriginIsolated,
|
||||
}
|
||||
) {
|
||||
return (
|
||||
entry.nightly === !isNightly ||
|
||||
(entry.nightlyAndroid === !(isAndroid && isNightly) && isAndroid) ||
|
||||
(entry.nonReleaseAndroid === !(isAndroid && !isRelease) && isAndroid) ||
|
||||
entry.desktop === !isDesktop ||
|
||||
(entry.android === !isAndroid &&
|
||||
!entry.nonReleaseAndroid &&
|
||||
!entry.nightlyAndroid) ||
|
||||
entry.fennecOrDesktop === (isAndroid && !isFennec) ||
|
||||
entry.fennec === !isFennec ||
|
||||
entry.release === !isRelease ||
|
||||
entry.earlyBetaOrEarlier === !isEarlyBetaOrEarlier ||
|
||||
entry.crossOriginIsolated === !isCrossOriginIsolated ||
|
||||
entry.disabled
|
||||
);
|
||||
}
|
||||
|
||||
function createInterfaceMap(data, ...interfaceGroups) {
|
||||
var interfaceMap = {};
|
||||
|
||||
function addInterfaces(interfaces) {
|
||||
|
@ -283,22 +326,7 @@ function createInterfaceMap({
|
|||
interfaceMap[entry] = true;
|
||||
} else {
|
||||
ok(!("pref" in entry), "Bogus pref annotation for " + entry.name);
|
||||
if (
|
||||
entry.nightly === !isNightly ||
|
||||
(entry.nightlyAndroid === !(isAndroid && isNightly) && isAndroid) ||
|
||||
(entry.nonReleaseAndroid === !(isAndroid && !isRelease) &&
|
||||
isAndroid) ||
|
||||
entry.desktop === !isDesktop ||
|
||||
(entry.android === !isAndroid &&
|
||||
!entry.nonReleaseAndroid &&
|
||||
!entry.nightlyAndroid) ||
|
||||
entry.fennecOrDesktop === (isAndroid && !isFennec) ||
|
||||
entry.fennec === !isFennec ||
|
||||
entry.release === !isRelease ||
|
||||
entry.earlyBetaOrEarlier === !isEarlyBetaOrEarlier ||
|
||||
entry.crossOriginIsolated === !isCrossOriginIsolated ||
|
||||
entry.disabled
|
||||
) {
|
||||
if (entryDisabled(entry, data)) {
|
||||
interfaceMap[entry.name] = false;
|
||||
} else if (entry.optional) {
|
||||
interfaceMap[entry.name] = "optional";
|
||||
|
@ -309,15 +337,16 @@ function createInterfaceMap({
|
|||
}
|
||||
}
|
||||
|
||||
addInterfaces(ecmaGlobals);
|
||||
addInterfaces(interfaceNamesInGlobalScope);
|
||||
for (let interfaceGroup of interfaceGroups) {
|
||||
addInterfaces(interfaceGroup);
|
||||
}
|
||||
|
||||
return interfaceMap;
|
||||
}
|
||||
|
||||
function runTest(data) {
|
||||
var interfaceMap = createInterfaceMap(data);
|
||||
for (var name of Object.getOwnPropertyNames(self)) {
|
||||
function runTest(parentName, parent, data, ...interfaceGroups) {
|
||||
var interfaceMap = createInterfaceMap(data, ...interfaceGroups);
|
||||
for (var name of Object.getOwnPropertyNames(parent)) {
|
||||
// An interface name should start with an upper case character.
|
||||
if (!/^[A-Z]/.test(name)) {
|
||||
continue;
|
||||
|
@ -326,7 +355,9 @@ function runTest(data) {
|
|||
interfaceMap[name] === "optional" || interfaceMap[name],
|
||||
"If this is failing: DANGER, are you sure you want to expose the new interface " +
|
||||
name +
|
||||
" to all webpages as a property on the service worker? Do not make a change to this file without a " +
|
||||
" to all webpages as a property on " +
|
||||
parentName +
|
||||
"? Do not make a change to this file without a " +
|
||||
" review from a DOM peer for that specific change!!! (or a JS peer for changes to ecmaGlobals)"
|
||||
);
|
||||
delete interfaceMap[name];
|
||||
|
@ -336,11 +367,12 @@ function runTest(data) {
|
|||
delete interfaceMap[name];
|
||||
} else {
|
||||
ok(
|
||||
name in self === interfaceMap[name],
|
||||
name in parent === interfaceMap[name],
|
||||
name +
|
||||
" should " +
|
||||
(interfaceMap[name] ? "" : " NOT") +
|
||||
" be defined on the global scope"
|
||||
" be defined on " +
|
||||
parentName
|
||||
);
|
||||
if (!interfaceMap[name]) {
|
||||
delete interfaceMap[name];
|
||||
|
@ -356,6 +388,9 @@ function runTest(data) {
|
|||
}
|
||||
|
||||
workerTestGetHelperData(function(data) {
|
||||
runTest(data);
|
||||
runTest("self", self, data, ecmaGlobals, interfaceNamesInGlobalScope);
|
||||
if (WebAssembly && !entryDisabled(wasmGlobalEntry, data)) {
|
||||
runTest("WebAssembly", WebAssembly, data, wasmGlobalInterfaces);
|
||||
}
|
||||
workerTestDone();
|
||||
});
|
||||
|
|
|
@ -47,6 +47,28 @@ const isFennec =
|
|||
).isFennec;
|
||||
const isCrossOriginIsolated = window.crossOriginIsolated;
|
||||
|
||||
// IMPORTANT: Do not change this list without review from
|
||||
// a JavaScript Engine peer!
|
||||
var wasmGlobalEntry = {
|
||||
name: "WebAssembly",
|
||||
insecureContext: true,
|
||||
disabled: !SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupportedByHardware(),
|
||||
};
|
||||
var wasmGlobalInterfaces = [
|
||||
{ name: "Module", insecureContext: true },
|
||||
{ name: "Instance", insecureContext: true },
|
||||
{ name: "Memory", insecureContext: true },
|
||||
{ name: "Table", insecureContext: true },
|
||||
{ name: "Global", insecureContext: true },
|
||||
{ name: "CompileError", insecureContext: true },
|
||||
{ name: "LinkError", insecureContext: true },
|
||||
{ name: "RuntimeError", insecureContext: true },
|
||||
{
|
||||
name: "Function",
|
||||
insecureContext: true,
|
||||
nightly: true,
|
||||
},
|
||||
];
|
||||
// IMPORTANT: Do not change this list without review from
|
||||
// a JavaScript Engine peer!
|
||||
var ecmaGlobals = [
|
||||
|
@ -105,11 +127,7 @@ var ecmaGlobals = [
|
|||
{ name: "WeakMap", insecureContext: true },
|
||||
{ name: "WeakRef", insecureContext: true },
|
||||
{ name: "WeakSet", insecureContext: true },
|
||||
{
|
||||
name: "WebAssembly",
|
||||
insecureContext: true,
|
||||
disabled: !SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupportedByHardware(),
|
||||
},
|
||||
wasmGlobalEntry,
|
||||
];
|
||||
// IMPORTANT: Do not change the list above without review from
|
||||
// a JavaScript Engine peer!
|
||||
|
@ -1381,7 +1399,33 @@ var interfaceNamesInGlobalScope = [
|
|||
];
|
||||
// IMPORTANT: Do not change the list above without review from a DOM peer!
|
||||
|
||||
function createInterfaceMap() {
|
||||
function entryDisabled(entry) {
|
||||
return (
|
||||
entry.nightly === !isNightly ||
|
||||
(entry.nightlyAndroid === !(isAndroid && isNightly) && isAndroid) ||
|
||||
entry.desktop === !isDesktop ||
|
||||
entry.windows === !isWindows ||
|
||||
entry.mac === !isMac ||
|
||||
entry.linux === !isLinux ||
|
||||
(entry.android === !isAndroid && !entry.nightlyAndroid) ||
|
||||
entry.fennecOrDesktop === (isAndroid && !isFennec) ||
|
||||
entry.fennec === !isFennec ||
|
||||
entry.release === !isRelease ||
|
||||
entry.releaseNonWindowsAndMac === !(isRelease && !isWindows && !isMac) ||
|
||||
entry.releaseNonWindows === !(isRelease && !isWindows) ||
|
||||
// The insecureContext test is very purposefully converting
|
||||
// entry.insecureContext to boolean, so undefined will convert to
|
||||
// false. That way entries without an insecureContext annotation
|
||||
// will get treated as "insecureContext: false", which means exposed
|
||||
// only in secure contexts.
|
||||
(isInsecureContext && !entry.insecureContext) ||
|
||||
entry.earlyBetaOrEarlier === !isEarlyBetaOrEarlier ||
|
||||
entry.crossOriginIsolated === !isCrossOriginIsolated ||
|
||||
entry.disabled
|
||||
);
|
||||
}
|
||||
|
||||
function createInterfaceMap(...interfaceGroups) {
|
||||
var interfaceMap = {};
|
||||
|
||||
function addInterfaces(interfaces) {
|
||||
|
@ -1390,47 +1434,21 @@ function createInterfaceMap() {
|
|||
interfaceMap[entry] = !isInsecureContext;
|
||||
} else {
|
||||
ok(!("pref" in entry), "Bogus pref annotation for " + entry.name);
|
||||
if (
|
||||
entry.nightly === !isNightly ||
|
||||
(entry.nightlyAndroid === !(isAndroid && isNightly) && isAndroid) ||
|
||||
entry.desktop === !isDesktop ||
|
||||
entry.windows === !isWindows ||
|
||||
entry.mac === !isMac ||
|
||||
entry.linux === !isLinux ||
|
||||
(entry.android === !isAndroid && !entry.nightlyAndroid) ||
|
||||
entry.fennecOrDesktop === (isAndroid && !isFennec) ||
|
||||
entry.fennec === !isFennec ||
|
||||
entry.release === !isRelease ||
|
||||
entry.releaseNonWindowsAndMac ===
|
||||
!(isRelease && !isWindows && !isMac) ||
|
||||
entry.releaseNonWindows === !(isRelease && !isWindows) ||
|
||||
// The insecureContext test is very purposefully converting
|
||||
// entry.insecureContext to boolean, so undefined will convert to
|
||||
// false. That way entries without an insecureContext annotation
|
||||
// will get treated as "insecureContext: false", which means exposed
|
||||
// only in secure contexts.
|
||||
(isInsecureContext && !entry.insecureContext) ||
|
||||
entry.earlyBetaOrEarlier === !isEarlyBetaOrEarlier ||
|
||||
entry.crossOriginIsolated === !isCrossOriginIsolated ||
|
||||
entry.disabled
|
||||
) {
|
||||
interfaceMap[entry.name] = false;
|
||||
} else {
|
||||
interfaceMap[entry.name] = true;
|
||||
}
|
||||
interfaceMap[entry.name] = !entryDisabled(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addInterfaces(ecmaGlobals);
|
||||
addInterfaces(interfaceNamesInGlobalScope);
|
||||
for (let interfaceGroup of interfaceGroups) {
|
||||
addInterfaces(interfaceGroup);
|
||||
}
|
||||
|
||||
return interfaceMap;
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
var interfaceMap = createInterfaceMap();
|
||||
for (var name of Object.getOwnPropertyNames(window)) {
|
||||
function runTest(parentName, parent, ...interfaceGroups) {
|
||||
var interfaceMap = createInterfaceMap(...interfaceGroups);
|
||||
for (var name of Object.getOwnPropertyNames(parent)) {
|
||||
// An interface name should start with an upper case character.
|
||||
// However, we have a couple of legacy interfaces that start with 'moz', so
|
||||
// we want to allow those until we can remove them.
|
||||
|
@ -1441,28 +1459,32 @@ function runTest() {
|
|||
interfaceMap[name],
|
||||
"If this is failing: DANGER, are you sure you want to expose the new interface " +
|
||||
name +
|
||||
" to all webpages as a property on the window? Do not make a change to this file without a " +
|
||||
" to all webpages as a property on '" +
|
||||
parentName +
|
||||
"'? Do not make a change to this file without a " +
|
||||
" review from a DOM peer for that specific change!!! (or a JS peer for changes to ecmaGlobals)"
|
||||
);
|
||||
|
||||
ok(
|
||||
name in window,
|
||||
`${name} is exposed as an own property on the window but tests false for "in" in the global scope`
|
||||
name in parent,
|
||||
`${name} is exposed as an own property on '" + parentName + "' but tests false for "in" in the global scope`
|
||||
);
|
||||
ok(
|
||||
Object.getOwnPropertyDescriptor(window, name),
|
||||
`${name} is exposed as an own property on the window but has no property descriptor in the global scope`
|
||||
Object.getOwnPropertyDescriptor(parent, name),
|
||||
`${name} is exposed as an own property on '" + parentName + "' but has no property descriptor in the global scope`
|
||||
);
|
||||
|
||||
delete interfaceMap[name];
|
||||
}
|
||||
for (var name of Object.keys(interfaceMap)) {
|
||||
ok(
|
||||
name in window === interfaceMap[name],
|
||||
name in parent === interfaceMap[name],
|
||||
name +
|
||||
" should " +
|
||||
(interfaceMap[name] ? "" : " NOT") +
|
||||
" be defined on the global scope"
|
||||
" be defined on '" +
|
||||
parentName +
|
||||
"' scope"
|
||||
);
|
||||
if (!interfaceMap[name]) {
|
||||
delete interfaceMap[name];
|
||||
|
@ -1476,4 +1498,7 @@ function runTest() {
|
|||
);
|
||||
}
|
||||
|
||||
runTest();
|
||||
runTest("window", window, ecmaGlobals, interfaceNamesInGlobalScope);
|
||||
if (window.WebAssembly && !entryDisabled(wasmGlobalEntry)) {
|
||||
runTest("WebAssembly", window.WebAssembly, wasmGlobalInterfaces);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,28 @@
|
|||
// value needs to depend on channel or OS, we will need to make sure
|
||||
// we have that information before setting up the property lists.
|
||||
|
||||
// IMPORTANT: Do not change this list without review from
|
||||
// a JavaScript Engine peer!
|
||||
var wasmGlobalEntry = {
|
||||
name: "WebAssembly",
|
||||
insecureContext: true,
|
||||
disabled: !getJSTestingFunctions().wasmIsSupportedByHardware(),
|
||||
};
|
||||
var wasmGlobalInterfaces = [
|
||||
{ name: "Module", insecureContext: true },
|
||||
{ name: "Instance", insecureContext: true },
|
||||
{ name: "Memory", insecureContext: true },
|
||||
{ name: "Table", insecureContext: true },
|
||||
{ name: "Global", insecureContext: true },
|
||||
{ name: "CompileError", insecureContext: true },
|
||||
{ name: "LinkError", insecureContext: true },
|
||||
{ name: "RuntimeError", insecureContext: true },
|
||||
{
|
||||
name: "Function",
|
||||
insecureContext: true,
|
||||
nightly: true,
|
||||
},
|
||||
];
|
||||
// IMPORTANT: Do not change this list without review from
|
||||
// a JavaScript Engine peer!
|
||||
var ecmaGlobals = [
|
||||
|
@ -85,11 +107,7 @@ var ecmaGlobals = [
|
|||
{ name: "WeakMap", insecureContext: true },
|
||||
{ name: "WeakRef", insecureContext: true },
|
||||
{ name: "WeakSet", insecureContext: true },
|
||||
{
|
||||
name: "WebAssembly",
|
||||
insecureContext: true,
|
||||
disabled: !getJSTestingFunctions().wasmIsSupportedByHardware(),
|
||||
},
|
||||
wasmGlobalEntry,
|
||||
];
|
||||
// IMPORTANT: Do not change the list above without review from
|
||||
// a JavaScript Engine peer!
|
||||
|
@ -293,16 +311,40 @@ var interfaceNamesInGlobalScope = [
|
|||
];
|
||||
// IMPORTANT: Do not change the list above without review from a DOM peer!
|
||||
|
||||
function createInterfaceMap({
|
||||
isNightly,
|
||||
isEarlyBetaOrEarlier,
|
||||
isRelease,
|
||||
isDesktop,
|
||||
isAndroid,
|
||||
isInsecureContext,
|
||||
isFennec,
|
||||
isCrossOringinIsolated,
|
||||
}) {
|
||||
function entryDisabled(
|
||||
entry,
|
||||
{
|
||||
isNightly,
|
||||
isEarlyBetaOrEarlier,
|
||||
isRelease,
|
||||
isDesktop,
|
||||
isAndroid,
|
||||
isInsecureContext,
|
||||
isFennec,
|
||||
isCrossOringinIsolated,
|
||||
}
|
||||
) {
|
||||
return (
|
||||
entry.nightly === !isNightly ||
|
||||
(entry.nightlyAndroid === !(isAndroid && isNightly) && isAndroid) ||
|
||||
entry.desktop === !isDesktop ||
|
||||
(entry.android === !isAndroid && !entry.nightlyAndroid) ||
|
||||
entry.fennecOrDesktop === (isAndroid && !isFennec) ||
|
||||
entry.fennec === !isFennec ||
|
||||
entry.release === !isRelease ||
|
||||
// The insecureContext test is very purposefully converting
|
||||
// entry.insecureContext to boolean, so undefined will convert to
|
||||
// false. That way entries without an insecureContext annotation
|
||||
// will get treated as "insecureContext: false", which means exposed
|
||||
// only in secure contexts.
|
||||
(isInsecureContext && !entry.insecureContext) ||
|
||||
entry.earlyBetaOrEarlier === !isEarlyBetaOrEarlier ||
|
||||
entry.crossOringinIsolated === !isCrossOringinIsolated ||
|
||||
entry.disabled
|
||||
);
|
||||
}
|
||||
|
||||
function createInterfaceMap(data, ...interfaceGroups) {
|
||||
var interfaceMap = {};
|
||||
|
||||
function addInterfaces(interfaces) {
|
||||
|
@ -311,41 +353,21 @@ function createInterfaceMap({
|
|||
interfaceMap[entry] = !isInsecureContext;
|
||||
} else {
|
||||
ok(!("pref" in entry), "Bogus pref annotation for " + entry.name);
|
||||
if (
|
||||
entry.nightly === !isNightly ||
|
||||
(entry.nightlyAndroid === !(isAndroid && isNightly) && isAndroid) ||
|
||||
entry.desktop === !isDesktop ||
|
||||
(entry.android === !isAndroid && !entry.nightlyAndroid) ||
|
||||
entry.fennecOrDesktop === (isAndroid && !isFennec) ||
|
||||
entry.fennec === !isFennec ||
|
||||
entry.release === !isRelease ||
|
||||
// The insecureContext test is very purposefully converting
|
||||
// entry.insecureContext to boolean, so undefined will convert to
|
||||
// false. That way entries without an insecureContext annotation
|
||||
// will get treated as "insecureContext: false", which means exposed
|
||||
// only in secure contexts.
|
||||
(isInsecureContext && !entry.insecureContext) ||
|
||||
entry.earlyBetaOrEarlier === !isEarlyBetaOrEarlier ||
|
||||
entry.crossOringinIsolated === !isCrossOringinIsolated ||
|
||||
entry.disabled
|
||||
) {
|
||||
interfaceMap[entry.name] = false;
|
||||
} else {
|
||||
interfaceMap[entry.name] = true;
|
||||
}
|
||||
interfaceMap[entry.name] = !entryDisabled(entry, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addInterfaces(ecmaGlobals);
|
||||
addInterfaces(interfaceNamesInGlobalScope);
|
||||
for (let interfaceGroup of interfaceGroups) {
|
||||
addInterfaces(interfaceGroup);
|
||||
}
|
||||
|
||||
return interfaceMap;
|
||||
}
|
||||
|
||||
function runTest(data) {
|
||||
var interfaceMap = createInterfaceMap(data);
|
||||
for (var name of Object.getOwnPropertyNames(self)) {
|
||||
function runTest(parentName, parent, data, ...interfaceGroups) {
|
||||
var interfaceMap = createInterfaceMap(data, ...interfaceGroups);
|
||||
for (var name of Object.getOwnPropertyNames(parent)) {
|
||||
// An interface name should start with an upper case character.
|
||||
if (!/^[A-Z]/.test(name)) {
|
||||
continue;
|
||||
|
@ -354,18 +376,21 @@ function runTest(data) {
|
|||
interfaceMap[name],
|
||||
"If this is failing: DANGER, are you sure you want to expose the new interface " +
|
||||
name +
|
||||
" to all webpages as a property on the worker? Do not make a change to this file without a " +
|
||||
" to all webpages as a property of " +
|
||||
parentName +
|
||||
"? Do not make a change to this file without a " +
|
||||
" review from a DOM peer for that specific change!!! (or a JS peer for changes to ecmaGlobals)"
|
||||
);
|
||||
delete interfaceMap[name];
|
||||
}
|
||||
for (var name of Object.keys(interfaceMap)) {
|
||||
ok(
|
||||
name in self === interfaceMap[name],
|
||||
name in parent === interfaceMap[name],
|
||||
name +
|
||||
" should " +
|
||||
(interfaceMap[name] ? "" : " NOT") +
|
||||
" be defined on the global scope"
|
||||
" be defined on " +
|
||||
parentName
|
||||
);
|
||||
if (!interfaceMap[name]) {
|
||||
delete interfaceMap[name];
|
||||
|
@ -380,6 +405,9 @@ function runTest(data) {
|
|||
}
|
||||
|
||||
workerTestGetHelperData(function(data) {
|
||||
runTest(data);
|
||||
runTest("self", self, data, ecmaGlobals, interfaceNamesInGlobalScope);
|
||||
if (WebAssembly && !entryDisabled(wasmGlobalEntry, data)) {
|
||||
runTest("WebAssembly", WebAssembly, data, wasmGlobalInterfaces);
|
||||
}
|
||||
workerTestDone();
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче