diff --git a/integration-tests/cli/help.test.js b/integration-tests/cli/help.test.js index 8219516316..001c379ade 100644 --- a/integration-tests/cli/help.test.js +++ b/integration-tests/cli/help.test.js @@ -32,7 +32,7 @@ test('--help should return help on stdout and zero exit code', async function (t '--engine-wasm The JS engine Wasm file path', '--module-mode [experimental] Run all sources as native modules,', 'with full error stack support.', - '--enable-experimental-aot Enable experimental AOT compilation for performance', + '--enable-aot Enable AOT compilation for performance', '--enable-experimental-high-resolution-time-methods Enable experimental high-resolution fastly.now() method', '--enable-experimental-top-level-await Enable experimental top level await', 'ARGS:', @@ -61,7 +61,7 @@ test('-h should return help on stdout and zero exit code', async function (t) { '--engine-wasm The JS engine Wasm file path', '--module-mode [experimental] Run all sources as native modules,', 'with full error stack support.', - '--enable-experimental-aot Enable experimental AOT compilation for performance', + '--enable-aot Enable AOT compilation for performance', '--enable-experimental-high-resolution-time-methods Enable experimental high-resolution fastly.now() method', '--enable-experimental-top-level-await Enable experimental top level await', 'ARGS:', diff --git a/integration-tests/js-compute/fixtures/app/src/headers.js b/integration-tests/js-compute/fixtures/app/src/headers.js index 3376b83ffc..d11a8f7342 100644 --- a/integration-tests/js-compute/fixtures/app/src/headers.js +++ b/integration-tests/js-compute/fixtures/app/src/headers.js @@ -26,8 +26,11 @@ routes.set('/headers/from-response/set', async () => { backend: 'httpbin', cacheOverride: new CacheOverride('pass'), }); - response.headers.set('cuStom', 'test'); - return response; + return new Response(response.body, { + headers: { + cuStom: 'test', + }, + }); }); routes.set('/headers/from-response/delete-invalid', async () => { @@ -35,8 +38,9 @@ routes.set('/headers/from-response/delete-invalid', async () => { backend: 'httpbin', cacheOverride: new CacheOverride('pass'), }); - response.headers.delete('none'); - return response; + const outResponse = new Response(response.body, response); + outResponse.headers.delete('none'); + return outResponse; }); routes.set('/headers/from-response/set-delete', async () => { @@ -44,7 +48,9 @@ routes.set('/headers/from-response/set-delete', async () => { backend: 'httpbin', cacheOverride: new CacheOverride('pass'), }); - response.headers.set('custom', 'test'); - response.headers.delete('access-control-allow-origin'); - return response; + const outResponse = new Response(response.body, response); + outResponse.headers.set('custom', 'test'); + outResponse.headers.set('another', 'test'); + outResponse.headers.delete('access-control-allow-origin'); + return outResponse; }); diff --git a/integration-tests/js-compute/fixtures/app/src/index.js b/integration-tests/js-compute/fixtures/app/src/index.js index 9a4d4ec0e9..44c5e7be44 100644 --- a/integration-tests/js-compute/fixtures/app/src/index.js +++ b/integration-tests/js-compute/fixtures/app/src/index.js @@ -91,7 +91,10 @@ async function app(event) { } } } finally { - res.headers.set('fastly_service_version', FASTLY_SERVICE_VERSION); + try { + // this will fail if headers were same headers object from original upstream + res.headers.set('fastly_service_version', FASTLY_SERVICE_VERSION); + } catch {} } return res; diff --git a/integration-tests/js-compute/fixtures/app/src/manual-framing-headers.js b/integration-tests/js-compute/fixtures/app/src/manual-framing-headers.js index 30bb32b20d..ad717e5e17 100644 --- a/integration-tests/js-compute/fixtures/app/src/manual-framing-headers.js +++ b/integration-tests/js-compute/fixtures/app/src/manual-framing-headers.js @@ -224,10 +224,14 @@ async function responseMethod(setManualFramingHeaders) { backend: 'httpbin', cacheOverride: new CacheOverride('pass'), }); - response.setManualFramingHeaders(setManualFramingHeaders); - response.headers.set('content-length', '11'); - response.headers.delete('transfer-encoding'); - return response; + const outResponse = new Response(response.body, { + headers: response.headers, + status: response.status, + }); + outResponse.setManualFramingHeaders(setManualFramingHeaders); + outResponse.headers.set('content-length', '11'); + outResponse.headers.delete('transfer-encoding'); + return outResponse; } routes.set('/override-content-length/response/method/false', async () => { diff --git a/integration-tests/js-compute/fixtures/app/src/request-headers.js b/integration-tests/js-compute/fixtures/app/src/request-headers.js index 9bac7c6748..25f6242e62 100644 --- a/integration-tests/js-compute/fixtures/app/src/request-headers.js +++ b/integration-tests/js-compute/fixtures/app/src/request-headers.js @@ -1,4 +1,5 @@ /* eslint-env serviceworker */ +import { assertThrows } from './assertions.js'; import { routes } from './routes.js'; { @@ -7,6 +8,11 @@ import { routes } from './routes.js'; * @type {Request} request **/ const request = event.request; + + assertThrows(() => { + request.headers.set('should-be', 'immutable'); + }, TypeError); + const headers = {}; for (const [name, value] of request.headers.entries()) { if (!headers[name]) { diff --git a/integration-tests/js-compute/fixtures/app/src/response.js b/integration-tests/js-compute/fixtures/app/src/response.js index 0742fb7f74..5a37cdf3e1 100644 --- a/integration-tests/js-compute/fixtures/app/src/response.js +++ b/integration-tests/js-compute/fixtures/app/src/response.js @@ -1,7 +1,7 @@ /* eslint-env serviceworker */ import { routes } from './routes.js'; -import { assert } from './assertions.js'; +import { assert, assertThrows } from './assertions.js'; import { allowDynamicBackends } from 'fastly:experimental'; routes.set('/response/stall', async (event) => { @@ -64,6 +64,11 @@ routes.set('/response/request-body-init', async () => { accept: 'image/webp', }, }); + + assertThrows(() => { + downloadResp.headers.set('should-be', 'immutable'); + }, TypeError); + // stream it through an echo proxy const postResp = await fetch( new Request('https://httpbin.org/anything', { diff --git a/integration-tests/js-compute/fixtures/app/tests.json b/integration-tests/js-compute/fixtures/app/tests.json index c40cc121af..cde168e667 100644 --- a/integration-tests/js-compute/fixtures/app/tests.json +++ b/integration-tests/js-compute/fixtures/app/tests.json @@ -1322,7 +1322,10 @@ "GET /headers/from-response/set-delete": { "downstream_response": { "status": 200, - "headers": [["cuStom", "test"]] + "headers": [ + ["cuStom", "test"], + ["another", "test"] + ] } }, diff --git a/integration-tests/js-compute/test.js b/integration-tests/js-compute/test.js index b4c5e8f3ed..a2b1516ec2 100755 --- a/integration-tests/js-compute/test.js +++ b/integration-tests/js-compute/test.js @@ -85,7 +85,7 @@ const config = TOML.parse( config.name = serviceName; if (aot) { const buildArgs = config.scripts.build.split(' '); - buildArgs.splice(-1, null, '--enable-experimental-aot'); + buildArgs.splice(-1, null, '--enable-aot'); config.scripts.build = buildArgs.join(' '); } if (debugBuild) { diff --git a/runtime/fastly/builtins/fetch/request-response.cpp b/runtime/fastly/builtins/fetch/request-response.cpp index 16f46ca9ef..b404f5c928 100644 --- a/runtime/fastly/builtins/fetch/request-response.cpp +++ b/runtime/fastly/builtins/fetch/request-response.cpp @@ -462,7 +462,8 @@ JSObject *Request::headers(JSContext *cx, JS::HandleObject obj) { if (!headers) { MOZ_ASSERT(is_instance(obj)); if (is_downstream(obj)) { - headers = Headers::create(cx, request_handle(obj).headers(), Headers::HeadersGuard::Request); + headers = + Headers::create(cx, request_handle(obj).headers(), Headers::HeadersGuard::Immutable); } else { headers = Headers::create(cx, Headers::HeadersGuard::Request); } @@ -482,7 +483,7 @@ JSObject *Response::headers(JSContext *cx, JS::HandleObject obj) { MOZ_ASSERT(is_instance(obj)); if (is_upstream(obj)) { headers = - Headers::create(cx, response_handle(obj).headers(), Headers::HeadersGuard::Response); + Headers::create(cx, response_handle(obj).headers(), Headers::HeadersGuard::Immutable); } else { headers = Headers::create(cx, Headers::HeadersGuard::Response); } diff --git a/src/parseInputs.js b/src/parseInputs.js index 609a10d547..c5e674196d 100644 --- a/src/parseInputs.js +++ b/src/parseInputs.js @@ -39,7 +39,15 @@ export async function parseInputs(cliInputs) { bundle = true; break; } + case '--enable-aot': { + enableAOT = true; + break; + } case '--enable-experimental-aot': { + console.error( + 'Warning: --enable-experimental-aot flag is now --enable-aot. The old flag continues\n' + + 'to work for now, but please update your build invocation!', + ); enableAOT = true; break; } diff --git a/src/printHelp.js b/src/printHelp.js index 0ee51b0495..3e35cb6b3b 100644 --- a/src/printHelp.js +++ b/src/printHelp.js @@ -16,7 +16,7 @@ OPTIONS: --engine-wasm The JS engine Wasm file path --module-mode [experimental] Run all sources as native modules, with full error stack support. - --enable-experimental-aot Enable experimental AOT compilation for performance + --enable-aot Enable AOT compilation for performance --enable-experimental-high-resolution-time-methods Enable experimental high-resolution fastly.now() method --enable-experimental-top-level-await Enable experimental top level await