From 7e4252c56d180493c6d1e15410c907faec0ed572 Mon Sep 17 00:00:00 2001 From: Aditya Tewari Date: Sat, 30 Nov 2024 07:13:42 -0600 Subject: [PATCH] Enable cache: no-cache compat flag and enum --- src/workerd/api/http-test-ts.ts | 58 +++++++++++++------------ src/workerd/api/http-test-ts.ts-wd-test | 20 ++++++++- src/workerd/api/http.c++ | 9 ++-- src/workerd/api/http.h | 42 +++++++++++++----- src/workerd/io/compatibility-date.capnp | 6 +++ 5 files changed, 91 insertions(+), 44 deletions(-) diff --git a/src/workerd/api/http-test-ts.ts b/src/workerd/api/http-test-ts.ts index 6183ef7030b..ac1c699f3aa 100644 --- a/src/workerd/api/http-test-ts.ts +++ b/src/workerd/api/http-test-ts.ts @@ -50,40 +50,56 @@ async function assertFetchCacheRejectsError( export const cacheMode = { async test(ctrl: any, env: any, ctx: any) { - const allowedCacheModes: RequestCache[] = [ + const allowedCacheModes: Set = new Set([ 'default', 'force-cache', 'no-cache', 'no-store', 'only-if-cached', 'reload', - ]; + ]); assert.strictEqual('cache' in Request.prototype, env.CACHE_ENABLED); { const req = new Request('https://example.org', {}); assert.strictEqual(req.cache, undefined); } - if (!env.CACHE_ENABLED) { - for (const cacheMode of allowedCacheModes) { + + var enabledCacheModes: Set = new Set(); + + if (env.CACHE_ENABLED) { + enabledCacheModes.add('no-store'); + } + if (env.NO_CACHE_ENABLED) { + enabledCacheModes.add('no-cache'); + } + + const failureCacheModes = allowedCacheModes.difference(enabledCacheModes); + for (const cacheMode of failureCacheModes) { + if (!env.CACHE_ENABLED) { await assertRequestCacheThrowsError(cacheMode); await assertFetchCacheRejectsError(cacheMode); + } else { + await assertRequestCacheThrowsError( + cacheMode, + 'TypeError', + 'Unsupported cache mode: ' + cacheMode + ); + await assertFetchCacheRejectsError( + cacheMode, + 'TypeError', + 'Unsupported cache mode: ' + cacheMode + ); } - } else { - var failureCacheModes: RequestCache[] = [ - 'default', - 'no-cache', - 'force-cache', - 'only-if-cached', - 'reload', - ]; + } + for (const cacheMode of enabledCacheModes) { { - const req = new Request('https://example.org', { cache: 'no-store' }); - assert.strictEqual(req.cache, 'no-store'); + const req = new Request('https://example.org', { cache: cacheMode }); + assert.strictEqual(req.cache, cacheMode); } { const response = await env.SERVICE.fetch( 'http://placeholder/not-found', - { cache: 'no-store' } + { cache: cacheMode } ); assert.strictEqual( util.inspect(response), @@ -106,18 +122,6 @@ export const cacheMode = { }` ); } - for (const cacheMode of failureCacheModes) { - await assertRequestCacheThrowsError( - cacheMode, - 'TypeError', - 'Unsupported cache mode: ' + cacheMode - ); - await assertFetchCacheRejectsError( - cacheMode, - 'TypeError', - 'Unsupported cache mode: ' + cacheMode - ); - } } }, }; diff --git a/src/workerd/api/http-test-ts.ts-wd-test b/src/workerd/api/http-test-ts.ts-wd-test index afa520fc2c1..8ffb841da3e 100644 --- a/src/workerd/api/http-test-ts.ts-wd-test +++ b/src/workerd/api/http-test-ts.ts-wd-test @@ -10,6 +10,7 @@ const unitTests :Workerd.Config = ( bindings = [ ( name = "SERVICE", service = "http-test" ), ( name = "CACHE_ENABLED", json = "false" ), + ( name = "NO_CACHE_ENABLED", json = "false" ), ], compatibilityDate = "2023-08-01", compatibilityFlags = ["nodejs_compat", "service_binding_extra_handlers", "cache_option_disabled"], @@ -23,9 +24,24 @@ const unitTests :Workerd.Config = ( bindings = [ ( name = "SERVICE", service = "http-test-cache-option-enabled" ), ( name = "CACHE_ENABLED", json = "true" ), + ( name = "NO_CACHE_ENABLED", json = "false" ), ], - compatibilityDate = "2023-08-01", - compatibilityFlags = ["nodejs_compat", "service_binding_extra_handlers", "cache_option_enabled"], + compatibilityDate = "2024-11-11", + compatibilityFlags = ["nodejs_compat", "service_binding_extra_handlers"], + ) + ), + ( name = "http-test-cache-no-cache", + worker = ( + modules = [ + ( name = "worker-cache-no-cache", esModule = embed "http-test-ts.js" ) + ], + bindings = [ + ( name = "SERVICE", service = "http-test-cache-no-cache" ), + ( name = "CACHE_ENABLED", json = "true" ), + ( name = "NO_CACHE_ENABLED", json = "true" ), + ], + compatibilityDate = "2024-11-11", + compatibilityFlags = ["nodejs_compat", "service_binding_extra_handlers", "cache_no_cache_enabled"], ) ), ], diff --git a/src/workerd/api/http.c++ b/src/workerd/api/http.c++ index c5cc67aa7fd..8a371457462 100644 --- a/src/workerd/api/http.c++ +++ b/src/workerd/api/http.c++ @@ -1214,7 +1214,7 @@ kj::Maybe Request::serializeCfBlobJson(jsg::Lock& js) { break; case CacheMode::NOCACHE: ttl = 0; - KJ_FALLTHROUGH; + break; case CacheMode::NONE: KJ_UNREACHABLE; } @@ -1239,8 +1239,11 @@ void RequestInitializerDict::validate(jsg::Lock& js) { // Validate that the cache type is valid auto cacheMode = getCacheModeFromName(c); - JSG_REQUIRE(cacheMode != Request::CacheMode::NOCACHE, TypeError, - kj::str("Unsupported cache mode: ", c)); + + if (!FeatureFlags::get(js).getCacheNoCache()) { + JSG_REQUIRE(cacheMode != Request::CacheMode::NOCACHE, TypeError, + kj::str("Unsupported cache mode: ", c)); + } } } diff --git a/src/workerd/api/http.h b/src/workerd/api/http.h index ee3672b195f..05b1cd6ceab 100644 --- a/src/workerd/api/http.h +++ b/src/workerd/api/http.h @@ -755,12 +755,21 @@ struct RequestInitializerDict { referrer, referrerPolicy, integrity, signal); JSG_STRUCT_TS_OVERRIDE_DYNAMIC(CompatibilityFlags::Reader flags) { if(flags.getCacheOptionEnabled()) { - JSG_TS_OVERRIDE(RequestInit { - headers?: HeadersInit; - body?: BodyInit | null; - cache?: 'no-store'; - cf?: Cf; - }); + if(flags.getCacheNoCache()) { + JSG_TS_OVERRIDE(RequestInit { + headers?: HeadersInit; + body?: BodyInit | null; + cache?: 'no-store' | 'no-cache'; + cf?: Cf; + }); + } else { + JSG_TS_OVERRIDE(RequestInit { + headers?: HeadersInit; + body?: BodyInit | null; + cache?: 'no-store'; + cf?: Cf; + }); + } } else { JSG_TS_OVERRIDE(RequestInit { headers?: HeadersInit; @@ -929,12 +938,21 @@ class Request final: public Body { JSG_READONLY_PROTOTYPE_PROPERTY(keepalive, getKeepalive); if(flags.getCacheOptionEnabled()) { JSG_READONLY_PROTOTYPE_PROPERTY(cache, getCache); - JSG_TS_OVERRIDE(> { - constructor(input: RequestInfo | URL, init?: RequestInit); - clone(): Request; - cache?: "no-store"; - get cf(): Cf | undefined; - }); + if(flags.getCacheNoCache()) { + JSG_TS_OVERRIDE(> { + constructor(input: RequestInfo | URL, init?: RequestInit); + clone(): Request; + cache?: "no-store" | "no-cache"; + get cf(): Cf | undefined; + }); + } else { + JSG_TS_OVERRIDE(> { + constructor(input: RequestInfo | URL, init?: RequestInit); + clone(): Request; + cache?: "no-store"; + get cf(): Cf | undefined; + }); + } } else { JSG_TS_OVERRIDE(> { constructor(input: RequestInfo | URL, init?: RequestInit); diff --git a/src/workerd/io/compatibility-date.capnp b/src/workerd/io/compatibility-date.capnp index de899b9100d..6a59b498bc9 100644 --- a/src/workerd/io/compatibility-date.capnp +++ b/src/workerd/io/compatibility-date.capnp @@ -668,4 +668,10 @@ struct CompatibilityFlags @0x8f8c1b68151b6cef { # A bug in the original implementation of TransformStream failed to apply backpressure # correctly. The fix, however, can break existing implementations that don't account # for the bug so we need to put the fix behind a compat flag. + + cacheNoCache @69 :Bool + $compatEnableFlag("cache_no_cache_enabled") + $compatDisableFlag("cache_no_cache_disabled") + $experimental; + # Enables the use of cache: no-cache in the fetch api. }