diff --git a/cli/tests/unit/cache_api_test.ts b/cli/tests/unit/cache_api_test.ts index 7bc372003a..7bca16d89d 100644 --- a/cli/tests/unit/cache_api_test.ts +++ b/cli/tests/unit/cache_api_test.ts @@ -4,6 +4,7 @@ import { assertEquals, assertFalse, assertRejects, + assertThrows, } from "./test_util.ts"; Deno.test(async function cacheStorage() { @@ -95,6 +96,13 @@ Deno.test(async function cacheApi() { assertFalse(await caches.has(cacheName)); }); +Deno.test(function cacheIllegalConstructor() { + // @ts-expect-error illegal constructor + assertThrows(() => new Cache(), TypeError, "Illegal constructor"); + // @ts-expect-error illegal constructor + assertThrows(() => new Cache("foo", "bar"), TypeError, "Illegal constructor"); +}); + Deno.test(async function cachePutReaderLock() { const cacheName = "cache-v1"; const cache = await caches.open(cacheName); diff --git a/ext/cache/01_cache.js b/ext/cache/01_cache.js index afde7f7894..aefd989dd9 100644 --- a/ext/cache/01_cache.js +++ b/ext/cache/01_cache.js @@ -33,7 +33,9 @@ context: "Argument 1", }); const cacheId = await core.opAsync("op_cache_storage_open", cacheName); - return new Cache(cacheId); + const cache = webidl.createBranded(Cache); + cache[_id] = cacheId; + return cache; } async has(cacheName) { @@ -59,18 +61,20 @@ } } + const _matchAll = Symbol("[[matchAll]]"); const _id = Symbol("id"); class Cache { /** @type {number} */ [_id]; - constructor(cacheId) { - this[_id] = cacheId; + constructor() { + webidl.illegalConstructor(); } /** See https://w3c.github.io/ServiceWorker/#dom-cache-put */ async put(request, response) { + webidl.assertBranded(this, CachePrototype); const prefix = "Failed to execute 'put' on 'Cache'"; webidl.requiredArguments(arguments.length, 2, { prefix }); request = webidl.converters["RequestInfo_DOMString"](request, { @@ -159,13 +163,14 @@ /** See https://w3c.github.io/ServiceWorker/#cache-match */ async match(request, options) { + webidl.assertBranded(this, CachePrototype); const prefix = "Failed to execute 'match' on 'Cache'"; webidl.requiredArguments(arguments.length, 1, { prefix }); request = webidl.converters["RequestInfo_DOMString"](request, { prefix, context: "Argument 1", }); - const p = await this.#matchAll(request, options); + const p = await this[_matchAll](request, options); if (p.length > 0) { return p[0]; } else { @@ -175,6 +180,7 @@ /** See https://w3c.github.io/ServiceWorker/#cache-delete */ async delete(request, _options) { + webidl.assertBranded(this, CachePrototype); const prefix = "Failed to execute 'delete' on 'Cache'"; webidl.requiredArguments(arguments.length, 1, { prefix }); request = webidl.converters["RequestInfo_DOMString"](request, { @@ -208,7 +214,7 @@ * * The function will return an array of responses. */ - async #matchAll(request, _options) { + async [_matchAll](request, _options) { // Step 1. let r = null; // Step 2. @@ -273,6 +279,7 @@ webidl.configurePrototype(CacheStorage); webidl.configurePrototype(Cache); const CacheStoragePrototype = CacheStorage.prototype; + const CachePrototype = Cache.prototype; let cacheStorage; window.__bootstrap.caches = { diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json index ed43da7e50..d713775d06 100644 --- a/tools/wpt/expectation.json +++ b/tools/wpt/expectation.json @@ -4562,8 +4562,6 @@ "NavigationPreloadManager interface: operation disable()", "NavigationPreloadManager interface: operation setHeaderValue(ByteString)", "NavigationPreloadManager interface: operation getState()", - "Cache interface: existence and properties of interface object", - "Cache interface object length", "Cache interface: operation match(RequestInfo, optional CacheQueryOptions)", "Cache interface: operation matchAll(optional RequestInfo, optional CacheQueryOptions)", "Cache interface: operation add(RequestInfo)", @@ -4652,8 +4650,6 @@ "NavigationPreloadManager interface: operation disable()", "NavigationPreloadManager interface: operation setHeaderValue(ByteString)", "NavigationPreloadManager interface: operation getState()", - "Cache interface: existence and properties of interface object", - "Cache interface object length", "Cache interface: operation match(RequestInfo, optional CacheQueryOptions)", "Cache interface: operation matchAll(optional RequestInfo, optional CacheQueryOptions)", "Cache interface: operation add(RequestInfo)",