mirror of
https://github.com/servo/servo.git
synced 2025-10-04 02:29:12 +01:00
Update web-platform-tests to revision 6c2d23b1b5e4dc00c944eedd16a11850e74a2d11
This commit is contained in:
parent
ad83faa745
commit
0114122fe0
140 changed files with 4328 additions and 1419 deletions
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Async local storage API surface</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script type="module">
|
||||
import { storage, StorageArea } from "std:async-local-storage";
|
||||
import * as classAssert from "./helpers/class-assert.js";
|
||||
import { testWithArea } from "./helpers/als-tests.js";
|
||||
|
||||
test(() => {
|
||||
classAssert.isConstructor(StorageArea);
|
||||
classAssert.functionName(StorageArea, "StorageArea");
|
||||
classAssert.functionLength(StorageArea, 1);
|
||||
classAssert.hasClassPrototype(StorageArea);
|
||||
classAssert.hasPrototypeConstructorLink(StorageArea);
|
||||
classAssert.propertyKeys(StorageArea, ["length", "prototype", "name"], []);
|
||||
}, "StorageArea constructor");
|
||||
|
||||
test(() => {
|
||||
classAssert.propertyKeys(StorageArea.prototype, [
|
||||
"constructor", "set", "get", "has", "delete", "clear",
|
||||
"keys", "values", "entries", "backingStore"
|
||||
], []);
|
||||
|
||||
classAssert.methods(StorageArea.prototype, {
|
||||
set: 2,
|
||||
get: 1,
|
||||
has: 1,
|
||||
delete: 1,
|
||||
clear: 0,
|
||||
keys: 0,
|
||||
values: 0,
|
||||
entries: 0
|
||||
});
|
||||
|
||||
classAssert.accessors(StorageArea.prototype, {
|
||||
backingStore: ["get"]
|
||||
});
|
||||
}, "StorageArea.prototype methods and properties");
|
||||
|
||||
testWithArea(async area => {
|
||||
classAssert.propertyKeys(area, [], []);
|
||||
}, "Instances don't have any properties")
|
||||
|
||||
test(() => {
|
||||
assert_equals(storage instanceof StorageArea, true, "instanceof");
|
||||
assert_equals(storage.constructor, StorageArea, ".constructor property");
|
||||
assert_equals(Object.getPrototypeOf(storage), StorageArea.prototype, "[[Prototype]]");
|
||||
}, "Built-in storage export is a StorageArea");
|
||||
|
||||
testWithArea(async area => {
|
||||
assert_false(Symbol.toStringTag in StorageArea.prototype,
|
||||
"Symbol.toStringTag must not be in the prototype");
|
||||
assert_equals(Object.prototype.toString.call(StorageArea.prototype), "[object Object]",
|
||||
"The prototype must not be customized");
|
||||
|
||||
assert_equals(Object.prototype.toString.call(area), "[object Object]",
|
||||
"A constructed StorageArea must not be customized");
|
||||
assert_equals(Object.prototype.toString.call(storage), "[object Object]",
|
||||
"The default storage area must not be customized");
|
||||
}, "No custom toStringTag");
|
||||
</script>
|
|
@ -0,0 +1,72 @@
|
|||
import { StorageArea, storage as defaultArea } from "std:async-local-storage";
|
||||
import { assertArrayCustomEquals } from "./equality-asserters.js";
|
||||
|
||||
export function testWithArea(testFn, description) {
|
||||
promise_test(t => {
|
||||
const area = new StorageArea(description);
|
||||
t.add_cleanup(t => area.clear());
|
||||
|
||||
return testFn(area, t);
|
||||
}, description);
|
||||
}
|
||||
|
||||
export function testWithDefaultArea(testFn, description) {
|
||||
promise_test(t => {
|
||||
t.add_cleanup(t => defaultArea.clear());
|
||||
|
||||
return testFn(defaultArea, t);
|
||||
}, description);
|
||||
}
|
||||
|
||||
// These two functions take a key/value and use them to test
|
||||
// set()/get()/delete()/has()/keys()/values()/entries(). The keyEqualityAsserter should be a
|
||||
// function from ./equality-asserters.js.
|
||||
|
||||
export function testVariousMethodsWithDefaultArea(label, key, value, keyEqualityAsserter) {
|
||||
testWithDefaultArea(testVariousMethodsInner(key, value, keyEqualityAsserter), label);
|
||||
}
|
||||
|
||||
export function testVariousMethods(label, key, value, keyEqualityAsserter) {
|
||||
testWithArea(testVariousMethodsInner(key, value, keyEqualityAsserter), label);
|
||||
}
|
||||
|
||||
function testVariousMethodsInner(key, value, keyEqualityAsserter) {
|
||||
return async area => {
|
||||
await assertPromiseEquals(area.set(key, value), undefined, "set()", "undefined");
|
||||
|
||||
await assertPromiseEquals(area.get(key), value, "get()", "the set value");
|
||||
await assertPromiseEquals(area.has(key), true, "has()", "true");
|
||||
|
||||
const keysPromise = area.keys();
|
||||
assertIsPromise(keysPromise, "keys()");
|
||||
assertArrayCustomEquals(await keysPromise, [key], keyEqualityAsserter, "keys() must have the key");
|
||||
|
||||
const valuesPromise = area.values();
|
||||
assertIsPromise(valuesPromise);
|
||||
assert_array_equals(await valuesPromise, [value], "values() must have the value");
|
||||
|
||||
const entriesPromise = area.entries();
|
||||
assertIsPromise(entriesPromise, "entries()");
|
||||
const entries = await entriesPromise;
|
||||
assert_true(Array.isArray(entries), "entries() must give an array");
|
||||
assert_equals(entries.length, 1, "entries() must have only one value");
|
||||
assert_true(Array.isArray(entries[0]), "entries() 0th element must be an array");
|
||||
assert_equals(entries[0].length, 2, "entries() 0th element must have 2 elements");
|
||||
keyEqualityAsserter(entries[0][0], key, "entries() 0th element's 0th element must be the key");
|
||||
assert_equals(entries[0][1], value, "entries() 0th element's 1st element must be the value");
|
||||
|
||||
await assertPromiseEquals(area.delete(key), undefined, "delete()", "undefined");
|
||||
|
||||
await assertPromiseEquals(area.get(key), undefined, "get()", "undefined after deleting");
|
||||
await assertPromiseEquals(area.has(key), false, "has()", "false after deleting");
|
||||
};
|
||||
}
|
||||
|
||||
async function assertPromiseEquals(promise, expected, label, expectedLabel) {
|
||||
assertIsPromise(promise, label);
|
||||
assert_equals(await promise, expected, label + " must fulfill with " + expectedLabel);
|
||||
}
|
||||
|
||||
function assertIsPromise(promise, label) {
|
||||
assert_equals(promise.constructor, Promise, label + " must return a promise");
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
export function isConstructor(o) {
|
||||
assert_equals(typeof o, "function", "Must be a function according to typeof");
|
||||
assert_true(isConstructorTest(o), "Must be a constructor according to the meta-object protocol");
|
||||
assert_throws(new TypeError(), () => o(), "Attempting to call (not construct) must throw");
|
||||
}
|
||||
|
||||
export function functionLength(o, expected, label) {
|
||||
const lengthExpected = { writable: false, enumerable: false, configurable: true };
|
||||
const { value } = propertyDescriptor(o, "length", lengthExpected);
|
||||
|
||||
assert_equals(value, expected, `${formatLabel(label)}length value`);
|
||||
}
|
||||
|
||||
export function functionName(o, expected, label) {
|
||||
const lengthExpected = { writable: false, enumerable: false, configurable: true };
|
||||
const { value } = propertyDescriptor(o, "name", lengthExpected);
|
||||
|
||||
assert_equals(value, expected, `${formatLabel(label)}name value`);
|
||||
}
|
||||
|
||||
export function hasClassPrototype(o) {
|
||||
const prototypeExpected = { writable: false, enumerable: false, configurable: false };
|
||||
const { value } = propertyDescriptor(o, "prototype", prototypeExpected);
|
||||
assert_equals(typeof value, "object", "prototype must be an object");
|
||||
assert_not_equals(value, null, "prototype must not be null");
|
||||
}
|
||||
|
||||
export function hasPrototypeConstructorLink(klass) {
|
||||
const constructorExpected = { writable: true, enumerable: false, configurable: true };
|
||||
const { value } = propertyDescriptor(klass.prototype, "constructor", constructorExpected);
|
||||
assert_equals(value, klass, "constructor property must match");
|
||||
}
|
||||
|
||||
export function propertyKeys(o, expectedNames, expectedSymbols, label) {
|
||||
label = formatLabel(label);
|
||||
assert_array_equals(Object.getOwnPropertyNames(o), expectedNames, `${label}property names`);
|
||||
assert_array_equals(Object.getOwnPropertySymbols(o), expectedSymbols,
|
||||
`${label}property symbols`);
|
||||
}
|
||||
|
||||
export function methods(o, expectedMethods) {
|
||||
for (const [name, length] of Object.entries(expectedMethods)) {
|
||||
method(o, name, length);
|
||||
}
|
||||
}
|
||||
|
||||
export function accessors(o, expectedAccessors) {
|
||||
for (const [name, accessorTypes] of Object.entries(expectedAccessors)) {
|
||||
accessor(o, name, accessorTypes);
|
||||
}
|
||||
}
|
||||
|
||||
function method(o, prop, length) {
|
||||
const methodExpected = { writable: true, enumerable: false, configurable: true };
|
||||
const { value } = propertyDescriptor(o, prop, methodExpected);
|
||||
|
||||
assert_equals(typeof value, "function", `${prop} method must be a function according to typeof`);
|
||||
assert_false(isConstructorTest(value),
|
||||
`${prop} method must not be a constructor according to the meta-object protocol`);
|
||||
functionLength(value, length, prop);
|
||||
functionName(value, prop, prop);
|
||||
propertyKeys(value, ["length", "name"], [], prop);
|
||||
}
|
||||
|
||||
function accessor(o, prop, expectedAccessorTypes) {
|
||||
const accessorExpected = { enumerable: false, configurable: true };
|
||||
const propDesc = propertyDescriptor(o, prop, accessorExpected);
|
||||
|
||||
for (const possibleType of ["get", "set"]) {
|
||||
const accessorFunc = propDesc[possibleType];
|
||||
if (expectedAccessorTypes.includes(possibleType)) {
|
||||
const label = `${prop}'s ${possibleType}ter`;
|
||||
|
||||
assert_equals(typeof accessorFunc, "function",
|
||||
`${label} must be a function according to typeof`);
|
||||
assert_false(isConstructorTest(accessorFunc),
|
||||
`${label} must not be a constructor according to the meta-object protocol`);
|
||||
|
||||
functionLength(accessorFunc, possibleType === "get" ? 0 : 1, label);
|
||||
functionName(accessorFunc, `${possibleType} ${prop}`, label);
|
||||
propertyKeys(accessorFunc, ["length", "name"], [], label);
|
||||
} else {
|
||||
assert_equals(accessorFunc, undefined, `${prop} must not have a ${possibleType}ter`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function propertyDescriptor(obj, prop, mustMatch) {
|
||||
const propDesc = Object.getOwnPropertyDescriptor(obj, prop);
|
||||
for (const key in Object.keys(mustMatch)) {
|
||||
assert_equals(propDesc[key], mustMatch[key], `${prop} ${key}`);
|
||||
}
|
||||
return propDesc;
|
||||
}
|
||||
|
||||
function isConstructorTest(o) {
|
||||
try {
|
||||
new (new Proxy(o, {construct: () => ({})}));
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function formatLabel(label) {
|
||||
return label !== undefined ? ` ${label}` : "";
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
export function assertEqualDates(actual, expected, label) {
|
||||
assert_equals(expected.constructor, Date,
|
||||
"assertEqualDates usage check: expected must be a Date");
|
||||
|
||||
const labelPart = label === undefined ? "" : `${label}: `;
|
||||
assert_equals(actual.constructor, Date, `${labelPart}must be a Date`);
|
||||
assert_equals(actual.valueOf(), expected.valueOf(), `${labelPart}timestamps must match`);
|
||||
}
|
||||
|
||||
export function assertEqualArrayBuffers(actual, expected, label) {
|
||||
assert_equals(expected.constructor, ArrayBuffer,
|
||||
"assertEqualArrayBuffers usage check: expected must be an ArrayBuffer");
|
||||
|
||||
const labelPart = label === undefined ? "" : `${label}: `;
|
||||
assert_equals(actual.constructor, ArrayBuffer, `${labelPart}must be an ArrayBuffer`);
|
||||
assert_array_equals(new Uint8Array(actual), new Uint8Array(expected), `${labelPart}must match`);
|
||||
}
|
||||
|
||||
export function assertArrayBufferEqualsABView(actual, expected, label) {
|
||||
assert_true(ArrayBuffer.isView(expected),
|
||||
"assertArrayBufferEqualsABView usage check: expected must be an ArrayBuffer view");
|
||||
|
||||
assertEqualArrayBuffers(actual, expected.buffer, label);
|
||||
}
|
||||
|
||||
export function assertArrayCustomEquals(actual, expected, equalityAsserter, label) {
|
||||
assert_true(Array.isArray(expected),
|
||||
"assertArrayCustomEquals usage check: expected must be an Array");
|
||||
|
||||
const labelPart = label === undefined ? "" : `${label}: `;
|
||||
assert_true(Array.isArray(actual), `${labelPart}must be an array`);
|
||||
assert_equals(actual.length, expected.length, `${labelPart}length must be as expected`);
|
||||
|
||||
for (let i = 0; i < actual.length; ++i) {
|
||||
equalityAsserter(actual[i], expected[i], `${labelPart}index ${i}`);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Async local storage: tests against various key types</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script type="module">
|
||||
import { testWithArea, testVariousMethods } from "./helpers/als-tests.js";
|
||||
import { assertEqualDates, assertEqualArrayBuffers, assertArrayBufferEqualsABView }
|
||||
from "./helpers/equality-asserters.js";
|
||||
|
||||
const invalidKeys = {
|
||||
"undefined": undefined,
|
||||
"null": null,
|
||||
"a boolean": true,
|
||||
"a symbol": Symbol("a symbol"),
|
||||
"an object": { an: "object" },
|
||||
"a function": () => {},
|
||||
"a regexp": /foo/,
|
||||
"a Map": new Map(),
|
||||
"a Set": new Set(),
|
||||
"an IDBKeyRange": IDBKeyRange.only(5)
|
||||
};
|
||||
|
||||
const validKeys = {
|
||||
"a number": [5, assert_equals],
|
||||
"a string": ["a string", assert_equals],
|
||||
"a Date": [new Date(), assertEqualDates],
|
||||
"a typed array": [new Uint8Array([1, 2]), assertArrayBufferEqualsABView],
|
||||
"a DataView": [new DataView(new Uint8Array([3, 4]).buffer), assertArrayBufferEqualsABView],
|
||||
"an ArrayBuffer": [new Uint8Array([5, 6]).buffer, assertEqualArrayBuffers]
|
||||
};
|
||||
|
||||
const methods = ["set", "get", "has", "delete"];
|
||||
|
||||
for (const method of methods) {
|
||||
testWithArea(async (area, t) => {
|
||||
for (const [description, key] of Object.entries(invalidKeys)) {
|
||||
await promise_rejects(t, "DataError", area[method](key), description);
|
||||
}
|
||||
}, `${method}: invalid keys`);
|
||||
|
||||
testWithArea(async (area, t) => {
|
||||
for (const [description, key] of Object.entries(invalidKeys)) {
|
||||
await promise_rejects(t, "DataError", area[method]([key]), description);
|
||||
}
|
||||
}, `${method}: invalid keys, nested in arrays`);
|
||||
|
||||
testWithArea(async (area, t) => {
|
||||
for (const [key] of Object.values(validKeys)) {
|
||||
await area[method](key);
|
||||
}
|
||||
}, `${method}: valid keys`);
|
||||
|
||||
testWithArea(async (area, t) => {
|
||||
for (const [key] of Object.values(validKeys)) {
|
||||
await area[method]([key]);
|
||||
}
|
||||
}, `${method}: valid keys, nested in arrays`);
|
||||
}
|
||||
|
||||
for (const [description, [key, equalityAsserter]] of Object.entries(validKeys)) {
|
||||
testVariousMethods(`Storage methods smoke test: ${description} key`, key, 5, equalityAsserter);
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Async local storage: should not work in non-secure contexts when included via import()</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
assert_false(self.isSecureContext, "This test must run in a non-secure context");
|
||||
}, "Prerequisite check");
|
||||
|
||||
promise_test(t => {
|
||||
return promise_rejects(t, "SecurityError", import("std:async-local-storage"));
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Async local storage: should not work in non-secure contexts when included via an import statement</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
setup({ allow_uncaught_exception: true });
|
||||
|
||||
test(() => {
|
||||
assert_false(self.isSecureContext, "This test must run in a non-secure context");
|
||||
}, "Prerequisite check");
|
||||
|
||||
async_test(t => {
|
||||
window.addEventListener("error", t.step_func_done(errorEvent => {
|
||||
assert_equals(errorEvent.error.constructor, DOMException, "Must trigger a DOMException");
|
||||
assert_equals(errorEvent.error.name, "SecurityError",
|
||||
"The DOMException must be a \"SecurityError\"");
|
||||
}, { once: true }));
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="module">
|
||||
import "std:async-local-storage";
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Async local storage: should not work in non-secure contexts when included via a script element</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
setup({ allow_uncaught_exception: true });
|
||||
|
||||
test(() => {
|
||||
assert_false(self.isSecureContext, "This test must run in a non-secure context");
|
||||
}, "Prerequisite check");
|
||||
|
||||
async_test(t => {
|
||||
self.addEventListener("error", t.step_func_done(errorEvent => {
|
||||
assert_equals(errorEvent.error.constructor, DOMException, "Must trigger a DOMException");
|
||||
assert_equals(errorEvent.error.name, "SecurityError",
|
||||
"The DOMException must be a \"SecurityError\"");
|
||||
}, { once: true }));
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="module" src="std:async-local-storage"></script>
|
|
@ -6,6 +6,7 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script type="module">
|
||||
import { testVariousMethodsWithDefaultArea } from "./helpers/als-tests.js";
|
||||
import { storage } from "std:async-local-storage";
|
||||
|
||||
test(() => {
|
||||
|
@ -21,26 +22,7 @@ test(() => {
|
|||
assert_equals(backingStore.version, 1);
|
||||
}, "backingStore returns the correct object");
|
||||
|
||||
promise_test(async (t) => {
|
||||
t.add_cleanup(async () => {
|
||||
await storage.clear();
|
||||
});
|
||||
|
||||
assert_equals(await storage.set("key", "value"), undefined);
|
||||
|
||||
assert_equals(await storage.get("key"), "value");
|
||||
assert_equals(await storage.has("key"), true);
|
||||
assert_array_equals(await storage.keys(), ["key"]);
|
||||
assert_array_equals(await storage.values(), ["value"]);
|
||||
|
||||
const entries = await storage.entries();
|
||||
assert_true(Array.isArray(entries));
|
||||
assert_equals(entries.length, 1);
|
||||
assert_array_equals(entries[0], ["key", "value"]);
|
||||
|
||||
assert_equals(await storage.delete("key"), undefined);
|
||||
|
||||
assert_equals(await storage.get("key"), undefined);
|
||||
assert_equals(await storage.has("key"), false);
|
||||
}, "storage methods work, at least for one entry with string key and value");
|
||||
testVariousMethodsWithDefaultArea(
|
||||
"Storage methods smoke test with string key and value", "key", "value", assert_equals
|
||||
);
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue