diff --git a/src/workerd/api/http-test.js b/src/workerd/api/http-test.js index 480a47fe1dd..4186d345383 100644 --- a/src/workerd/api/http-test.js +++ b/src/workerd/api/http-test.js @@ -270,14 +270,12 @@ export const cacheMode = { assertFetchCacheRejectsError('no-transform'); assertFetchCacheRejectsError('unsupported'); } else { - { - const req = new Request('https://example.org', { cache: 'no-store' }); - assert.strictEqual(req.cache, 'no-store'); - } - { - const req = new Request('https://example.org', { cache: 'no-cache' }); - assert.strictEqual(req.cache, 'no-cache'); - } + assertRequestCacheThrowsError('no-store', + 'TypeError', + "Unsupported cache mode: no-store"); + assertRequestCacheThrowsError('no-cache', + 'TypeError', + "Unsupported cache mode: no-cache"); assertRequestCacheThrowsError('no-transform', 'TypeError', "Unsupported cache mode: no-transform"); diff --git a/src/workerd/api/http.c++ b/src/workerd/api/http.c++ index 63667b75918..68f7c271230 100644 --- a/src/workerd/api/http.c++ +++ b/src/workerd/api/http.c++ @@ -1204,8 +1204,7 @@ void RequestInitializerDict::validate() { JSG_REQUIRE(Worker::Api::current().getFeatureFlags().getCacheOptionEnabled(), Error, kj::str( "The 'cache' field on 'RequestInitializerDict' is not implemented.")); - // Check that the string is a supported type - auto cacheStruct = getCacheModeFromName(c); + JSG_FAIL_REQUIRE(TypeError, kj::str("Unsupported cache mode: ", c)); } } @@ -1818,13 +1817,7 @@ jsg::Promise> fetchImplNoOutputLock( // If the jsRequest has a CacheMode, we need to handle that here. // Currently, the only cache mode we support is undefined, but we will soon support // no-cache and no-store. These additional modes will be hidden behind an autogate. - if (jsRequest->getCacheMode() != Request::CacheMode::NONE) { - JSG_REQUIRE(FeatureFlags::get(js).getCacheOptionEnabled(), Error, kj::str( -+ "The 'cache' field on 'RequestInitializerDict' is not implemented.")); - return js.rejectedPromise>( - js.typeError(kj::str("Unsupported cache mode: ", - KJ_ASSERT_NONNULL(jsRequest->getCache(js))))); - } + KJ_ASSERT(jsRequest->getCacheMode() == Request::CacheMode::NONE); kj::String url = uriEncodeControlChars( urlList.back().toString(kj::Url::HTTP_PROXY_REQUEST).asBytes()); diff --git a/src/workerd/api/http.h b/src/workerd/api/http.h index 76b2757b381..b6e0afee093 100644 --- a/src/workerd/api/http.h +++ b/src/workerd/api/http.h @@ -752,7 +752,6 @@ struct RequestInitializerDict { // jsg::Optional priority; // TODO(conform): Might support later? - void validate(); JSG_STRUCT(method, headers, body, redirect, fetcher, cf, mode, credentials, cache, referrer, referrerPolicy, integrity, signal); @@ -761,6 +760,10 @@ struct RequestInitializerDict { body?: BodyInit | null; cf?: Cf; }); + + // This method is called within tryUnwrap() when the type is unpacked from v8. + // See jsg Readme for more details. + void validate(); }; class Request: public Body { diff --git a/src/workerd/jsg/README.md b/src/workerd/jsg/README.md index f1d3316d1fe..5e626e3a5fa 100644 --- a/src/workerd/jsg/README.md +++ b/src/workerd/jsg/README.md @@ -642,6 +642,7 @@ included in the JavaScript object.) If the struct has a validate() method, it is called when the struct is unwrapped from v8. This is an opportunity for it to throw a TypeError based on some custom logic. +The signature for this method is `void validate();` ```cpp struct ValdiatingFoo { @@ -656,6 +657,7 @@ struct ValdiatingFoo { ``` In this example the validate method would throw a `TypeError` if the size of the `abc` field was zero. +If you want to check `compat` flags you can directly use the `Worker::Api::current().getFeatureFlags()` ```cpp Foo someFunction(Foo foo) { diff --git a/src/workerd/jsg/jsg.h b/src/workerd/jsg/jsg.h index 733abe9052a..15966e00c75 100644 --- a/src/workerd/jsg/jsg.h +++ b/src/workerd/jsg/jsg.h @@ -639,6 +639,17 @@ namespace { // // Note that if a `validate` function is provided, then it will be called after the struct is // unwrapped from v8. This would be an appropriate time to throw an error. +// Signature: void validate(); +// Example: +// struct ValdiatingFoo { +// kj::String abc; +// void validate() { +// JSG_REQUIRE(abc.size() != 0, TypeError, "Field 'abc' had no length in 'ValidatingFoo'."); +// } +// JSG_STRUCT(abc); +// }; +// +// In this example the validate method would throw a `TypeError` if the size of the `abc` field was zero. // // Fields with a starting '$' will have that dollar sign prefix stripped in the JS binding. A // motivating example to enact that change was WebCrypto which has a field in a dictionary called diff --git a/src/workerd/jsg/struct.h b/src/workerd/jsg/struct.h index 77a76b3177a..ad2b276cf78 100644 --- a/src/workerd/jsg/struct.h +++ b/src/workerd/jsg/struct.h @@ -122,6 +122,9 @@ class StructWrapper, kj::_::Indexes(fields).unwrap(static_cast(*this), isolate, context, in)... }; + // Note that if a `validate` function is provided, then it will be called after the struct is + // unwrapped from v8. This would be an appropriate time to throw an error. + // Signature: void validate(); if constexpr (requires { t.validate(); }) { t.validate(); }