From e8c1af13e500d070def952ccb97a246baddde2e5 Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Fri, 11 Oct 2024 15:07:38 -0700 Subject: [PATCH 01/10] fix!: immutable headers guards for incoming response and downstream request --- .../js-compute/fixtures/app/src/request-headers.js | 6 ++++++ integration-tests/js-compute/fixtures/app/src/response.js | 7 ++++++- runtime/fastly/builtins/fetch/request-response.cpp | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) 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/runtime/fastly/builtins/fetch/request-response.cpp b/runtime/fastly/builtins/fetch/request-response.cpp index c04e183c49..43f85b3905 100644 --- a/runtime/fastly/builtins/fetch/request-response.cpp +++ b/runtime/fastly/builtins/fetch/request-response.cpp @@ -459,7 +459,7 @@ 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); } @@ -481,7 +481,7 @@ JSObject *Response::headers(JSContext *cx, JS::HandleObject obj) { headers = Headers::create(cx, response_handle(obj).headers(), Headers::HeadersGuard::Response); } else { - headers = Headers::create(cx, Headers::HeadersGuard::Response); + headers = Headers::create(cx, Headers::HeadersGuard::Immutable); } if (!headers) { return nullptr; From ae639b51d94d3b2a5036bcdbd736d8c5b85c034f Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Fri, 11 Oct 2024 15:09:31 -0700 Subject: [PATCH 02/10] fixup --- runtime/fastly/builtins/fetch/request-response.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runtime/fastly/builtins/fetch/request-response.cpp b/runtime/fastly/builtins/fetch/request-response.cpp index 43f85b3905..6e66225e2e 100644 --- a/runtime/fastly/builtins/fetch/request-response.cpp +++ b/runtime/fastly/builtins/fetch/request-response.cpp @@ -459,7 +459,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::Immutable); + headers = + Headers::create(cx, request_handle(obj).headers(), Headers::HeadersGuard::Immutable); } else { headers = Headers::create(cx, Headers::HeadersGuard::Request); } From dc33a132f9f68a47ae2def2236b4f918f261c4d4 Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Fri, 11 Oct 2024 15:18:50 -0700 Subject: [PATCH 03/10] fixup --- runtime/fastly/builtins/fetch/request-response.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/fastly/builtins/fetch/request-response.cpp b/runtime/fastly/builtins/fetch/request-response.cpp index 6e66225e2e..381c147cb4 100644 --- a/runtime/fastly/builtins/fetch/request-response.cpp +++ b/runtime/fastly/builtins/fetch/request-response.cpp @@ -480,9 +480,9 @@ 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::Immutable); + headers = Headers::create(cx, Headers::HeadersGuard::Response); } if (!headers) { return nullptr; From b2e9d1538de27c84bd5d773643b62e2d2487e368 Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Fri, 11 Oct 2024 15:58:04 -0700 Subject: [PATCH 04/10] fixups --- .../js-compute/fixtures/app/src/headers.js | 20 ++++++++++++------- .../js-compute/fixtures/app/src/index.js | 5 ++++- .../js-compute/fixtures/app/tests.json | 5 ++++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/integration-tests/js-compute/fixtures/app/src/headers.js b/integration-tests/js-compute/fixtures/app/src/headers.js index 3376b83ffc..26061c4b66 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); + 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); + 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 c097fa8064..cdacc67930 100644 --- a/integration-tests/js-compute/fixtures/app/src/index.js +++ b/integration-tests/js-compute/fixtures/app/src/index.js @@ -92,7 +92,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/tests.json b/integration-tests/js-compute/fixtures/app/tests.json index c25379912d..d08e5a4fb9 100644 --- a/integration-tests/js-compute/fixtures/app/tests.json +++ b/integration-tests/js-compute/fixtures/app/tests.json @@ -1503,7 +1503,10 @@ "GET /headers/from-response/set-delete": { "downstream_response": { "status": 200, - "headers": [["cuStom", "test"]] + "headers": [ + ["cuStom", "test"], + ["another", "test"] + ] } }, From bff45296e88a15c0c65ab23525a07694c16ed8ab Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Fri, 11 Oct 2024 16:11:39 -0700 Subject: [PATCH 05/10] fixup --- .../fixtures/app/src/manual-framing-headers.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) 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..a2a73fd6d7 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,11 @@ 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); + 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 () => { From dab45a6d97bb8f22c815a262bf8d9a697de55cc6 Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Fri, 11 Oct 2024 17:31:14 -0700 Subject: [PATCH 06/10] fixup --- .../js-compute/fixtures/app/src/manual-framing-headers.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 a2a73fd6d7..5e8c434c85 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,8 +224,11 @@ async function responseMethod(setManualFramingHeaders) { backend: 'httpbin', cacheOverride: new CacheOverride('pass'), }); - const outResponse = new Response(response); - outResponse.setManualFramingHeaders(setManualFramingHeaders); + const outResponse = new Response(response.body, { + headers: response.headers, + status: response.status, + }); + response.setManualFramingHeaders(setManualFramingHeaders); outResponse.headers.set('content-length', '11'); outResponse.headers.delete('transfer-encoding'); return outResponse; From 913751b55e9ec0eae86cf097e68efb1552305c1f Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Fri, 11 Oct 2024 17:47:52 -0700 Subject: [PATCH 07/10] fixup --- .../js-compute/fixtures/app/src/manual-framing-headers.js | 1 + 1 file changed, 1 insertion(+) 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 5e8c434c85..b2c017b7d7 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 @@ -229,6 +229,7 @@ async function responseMethod(setManualFramingHeaders) { status: response.status, }); response.setManualFramingHeaders(setManualFramingHeaders); + outResponse.setManualFramingHeaders(setManualFramingHeaders); outResponse.headers.set('content-length', '11'); outResponse.headers.delete('transfer-encoding'); return outResponse; From 3d579ca8b169073e795fe46c56f11ce384a6eb25 Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Fri, 11 Oct 2024 17:59:00 -0700 Subject: [PATCH 08/10] fixup --- .../js-compute/fixtures/app/src/manual-framing-headers.js | 1 - 1 file changed, 1 deletion(-) 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 b2c017b7d7..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 @@ -228,7 +228,6 @@ async function responseMethod(setManualFramingHeaders) { headers: response.headers, status: response.status, }); - response.setManualFramingHeaders(setManualFramingHeaders); outResponse.setManualFramingHeaders(setManualFramingHeaders); outResponse.headers.set('content-length', '11'); outResponse.headers.delete('transfer-encoding'); From b5dae628478be1ea029d8fe98c96407157c6ea21 Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Fri, 11 Oct 2024 17:59:51 -0700 Subject: [PATCH 09/10] fixup --- integration-tests/js-compute/fixtures/app/src/headers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/js-compute/fixtures/app/src/headers.js b/integration-tests/js-compute/fixtures/app/src/headers.js index 26061c4b66..d11a8f7342 100644 --- a/integration-tests/js-compute/fixtures/app/src/headers.js +++ b/integration-tests/js-compute/fixtures/app/src/headers.js @@ -38,7 +38,7 @@ routes.set('/headers/from-response/delete-invalid', async () => { backend: 'httpbin', cacheOverride: new CacheOverride('pass'), }); - const outResponse = new Response(response); + const outResponse = new Response(response.body, response); outResponse.headers.delete('none'); return outResponse; }); @@ -48,7 +48,7 @@ routes.set('/headers/from-response/set-delete', async () => { backend: 'httpbin', cacheOverride: new CacheOverride('pass'), }); - const outResponse = new Response(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'); From 3cd3cd72e1f700eaae111abedbd7c41a303ebc80 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Mon, 4 Nov 2024 16:25:58 -0800 Subject: [PATCH 10/10] AOT compilation: rename flag; no longer experimental. (#1033) --- integration-tests/cli/help.test.js | 4 ++-- integration-tests/js-compute/test.js | 2 +- src/parseInputs.js | 8 ++++++++ src/printHelp.js | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) 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/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/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