@pulse-compute/provider-fastly 1.0.0-beta.2 → 1.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,9 +7,9 @@
7
7
  > **Supported entry points:** `@pulse-compute/provider-fastly`, `@pulse-compute/provider-fastly/contract`, `@pulse-compute/provider-fastly/toolchain`, `@pulse-compute/provider-fastly/config-schema`, `@pulse-compute/provider-fastly/runtime/canonical-api-runtime`, `@pulse-compute/provider-fastly/build/canonical-target`, `@pulse-compute/provider-fastly/testing/fastly-cli`<br>
8
8
  > **Stability:** The listed entry points are supported for the Beta; all other exported subpaths are implementation-only.<br>
9
9
  > **npm:** [`@pulse-compute/provider-fastly`](https://www.npmjs.com/package/@pulse-compute/provider-fastly)<br>
10
- > **Canonical documentation:** [Package guide](https://pulsecompute.io/v1.0.0-beta.2/packages/provider-fastly/)
10
+ > **Canonical documentation:** [Package guide](https://pulsecompute.io/v1.0.0-beta.4/packages/provider-fastly/)
11
11
  >
12
- > This release-status block is generated from the synchronized `Pulse 1.0.0-beta.2` package policy.
12
+ > This release-status block is generated from the synchronized `Pulse 1.0.0-beta.4` package policy.
13
13
  <!-- pulse-package-status:end -->
14
14
 
15
15
  Fastly provider configuration, canonical capability lowering, local conformance execution, Compute target generation, and explicit external-tool boundaries.
@@ -49,7 +49,7 @@ trusted wall-clock authority. It does not fall back to Node execution.
49
49
 
50
50
  ## Documentation
51
51
 
52
- - [Fastly package guide](https://pulsecompute.io/v1.0.0-beta.2/packages/provider-fastly/)
53
- - [Project configuration](https://pulsecompute.io/v1.0.0-beta.2/reference/project-config/#fastly-provider-options)
54
- - [Fastly capabilities guide](https://pulsecompute.io/v1.0.0-beta.2/guides/fastly-capabilities/)
55
- - [Environment variables](https://pulsecompute.io/v1.0.0-beta.2/reference/environment/#pulse-fastly-bin)
52
+ - [Fastly package guide](https://pulsecompute.io/v1.0.0-beta.4/packages/provider-fastly/)
53
+ - [Project configuration](https://pulsecompute.io/v1.0.0-beta.4/reference/project-config/#fastly-provider-options)
54
+ - [Fastly capabilities guide](https://pulsecompute.io/v1.0.0-beta.4/guides/fastly-capabilities/)
55
+ - [Environment variables](https://pulsecompute.io/v1.0.0-beta.4/reference/environment/#pulse-fastly-bin)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pulse-compute/provider-fastly",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.0.0-beta.4",
4
4
  "license": "Apache-2.0",
5
5
  "engines": {
6
6
  "node": "^22.14.0 || ^24.0.0"
@@ -59,15 +59,15 @@
59
59
  }
60
60
  },
61
61
  "dependencies": {
62
- "@pulse-compute/crypto": "1.0.0-beta.2",
63
- "@pulse-compute/jwt": "1.0.0-beta.2",
64
- "@pulse-compute/runtime": "1.0.0-beta.2",
65
- "@pulse-compute/s3": "1.0.0-beta.2",
66
- "@pulse-compute/wasm-build-support": "1.0.0-beta.2",
67
- "@pulse-compute/wasm-contracts": "1.0.0-beta.2",
68
- "@pulse-compute/wasm-guest-link": "1.0.0-beta.2",
69
- "@pulse-compute/wasm-host-runtime": "1.0.0-beta.2",
70
- "@pulse-compute/wasm-runtime-core-as": "1.0.0-beta.2",
62
+ "@pulse-compute/crypto": "1.0.0-beta.4",
63
+ "@pulse-compute/jwt": "1.0.0-beta.4",
64
+ "@pulse-compute/runtime": "1.0.0-beta.4",
65
+ "@pulse-compute/s3": "1.0.0-beta.4",
66
+ "@pulse-compute/wasm-build-support": "1.0.0-beta.4",
67
+ "@pulse-compute/wasm-contracts": "1.0.0-beta.4",
68
+ "@pulse-compute/wasm-guest-link": "1.0.0-beta.4",
69
+ "@pulse-compute/wasm-host-runtime": "1.0.0-beta.4",
70
+ "@pulse-compute/wasm-runtime-core-as": "1.0.0-beta.4",
71
71
  "esbuild": "0.28.1"
72
72
  },
73
73
  "types": "./dist/index.d.ts",
@@ -87,7 +87,7 @@
87
87
  "url": "git+https://github.com/pulse-compute/pulse.git",
88
88
  "directory": "packages/provider-fastly"
89
89
  },
90
- "homepage": "https://pulsecompute.io/v1.0.0-beta.2/packages/provider-fastly/",
90
+ "homepage": "https://pulsecompute.io/v1.0.0-beta.4/packages/provider-fastly/",
91
91
  "bugs": {
92
92
  "url": "https://github.com/pulse-compute/pulse/issues"
93
93
  },
@@ -507,7 +507,35 @@ function __pulse_fastly_number_string(value: f64): string { if (value >= -900719
507
507
  function __pulse_fastly_string(handle: i32): string { const value = __pulse_fastly_value(handle); if (value.kind == PULSE_VALUE_STRING) return value.text; if (value.kind == PULSE_VALUE_NUMBER) return __pulse_fastly_number_string(value.number); if (value.kind == PULSE_VALUE_BOOLEAN) return value.boolean != 0 ? "true" : "false"; if (value.kind == PULSE_VALUE_NULL) return "null"; if (value.kind == PULSE_VALUE_UNDEFINED) return "undefined"; return __pulse_fastly_json(handle, 0) }
508
508
  function __pulse_fastly_number(handle: i32): f64 { const value = __pulse_fastly_value(handle); if (value.kind == PULSE_VALUE_NUMBER) return value.number; if (value.kind == PULSE_VALUE_BOOLEAN) return value.boolean != 0 ? 1.0 : 0.0; if (value.kind == PULSE_VALUE_STRING) return F64.parseFloat(value.text); return 0.0 }
509
509
  function __pulse_fastly_hex(value: i32): string { return String.fromCharCode(value < 10 ? 48 + value : 87 + value) }
510
- function __pulse_fastly_quote(value: string): string { let out = "\""; for (let i = 0; i < value.length; i += 1) { const c = value.charCodeAt(i); if (c == 34) out += "\\\""; else if (c == 92) out += "\\\\"; else if (c == 8) out += "\\b"; else if (c == 9) out += "\\t"; else if (c == 10) out += "\\n"; else if (c == 12) out += "\\f"; else if (c == 13) out += "\\r"; else if (c < 32) out += "\\u00" + __pulse_fastly_hex((c >> 4) & 15) + __pulse_fastly_hex(c & 15); else out += String.fromCharCode(c) } return out + "\"" }
510
+ function __pulse_fastly_is_unpaired(value: string, i: i32): bool {
511
+ const c = value.charCodeAt(i);
512
+ if (c >= 0xd800 && c <= 0xdbff) return i + 1 >= value.length || value.charCodeAt(i + 1) < 0xdc00 || value.charCodeAt(i + 1) > 0xdfff;
513
+ if (c >= 0xdc00 && c <= 0xdfff) return i == 0 || value.charCodeAt(i - 1) < 0xd800 || value.charCodeAt(i - 1) > 0xdbff;
514
+ return false;
515
+ }
516
+ function __pulse_fastly_quote(value: string): string {
517
+ // Count once and write UTF-16 units once. Repeated concatenation can allocate
518
+ // gigabytes for a valid bounded string when every byte needs JSON escaping.
519
+ let size = 2;
520
+ for (let i = 0; i < value.length; i++) {
521
+ const c = value.charCodeAt(i);
522
+ size += c == 34 || c == 92 || c == 8 || c == 9 || c == 10 || c == 12 || c == 13 ? 2 : (c < 32 || __pulse_fastly_is_unpaired(value, i)) ? 6 : 1;
523
+ }
524
+ const out = new Uint16Array(size); let cursor = 0; out[cursor++] = 34;
525
+ for (let i = 0; i < value.length; i++) {
526
+ const c = value.charCodeAt(i);
527
+ if (c == 34 || c == 92) { out[cursor++] = 92; out[cursor++] = u16(c); }
528
+ else if (c == 8 || c == 9 || c == 10 || c == 12 || c == 13) {
529
+ out[cursor++] = 92; out[cursor++] = c == 8 ? 98 : c == 9 ? 116 : c == 10 ? 110 : c == 12 ? 102 : 114;
530
+ } else if (c < 32 || __pulse_fastly_is_unpaired(value, i)) {
531
+ out[cursor++] = 92; out[cursor++] = 117;
532
+ out[cursor++] = u16('0123456789abcdef'.charCodeAt((c >> 12) & 15)); out[cursor++] = u16('0123456789abcdef'.charCodeAt((c >> 8) & 15));
533
+ out[cursor++] = u16('0123456789abcdef'.charCodeAt((c >> 4) & 15)); out[cursor++] = u16('0123456789abcdef'.charCodeAt(c & 15));
534
+ } else out[cursor++] = u16(c);
535
+ }
536
+ out[cursor] = 34;
537
+ return String.UTF16.decodeUnsafe(out.dataStart, out.byteLength);
538
+ }
511
539
  function __pulse_fastly_json(handle: i32, depth: i32): string {
512
540
  if (depth > 64) { __pulse_fastly_fail(PULSE_ERROR_JSON, 2, -1); return "null" }
513
541
  const value = __pulse_fastly_value(handle)
@@ -562,6 +590,15 @@ function host_request_json(schema: i32): i32 { const parsed = __pulse_fastly_par
562
590
  function __pulse_fastly_headers_from_options(options: __PulseFastlyValue, output: __PulseFastlyValue): void { const index = __pulse_fastly_find(options, "headers"); if (index < 0) return; const headers = __pulse_fastly_value(unchecked(options.values[index])); if (headers.kind == PULSE_VALUE_OBJECT) { for (let i = 0; i < headers.keys.length; i += 1) { const name = unchecked(headers.keys[i]); const value = __pulse_fastly_value(unchecked(headers.values[i])); if (value.kind == PULSE_VALUE_ARRAY) { for (let j = 0; j < value.values.length; j += 1) output.headers.push(new __PulseFastlyHeader(name, __pulse_fastly_string(unchecked(value.values[j])))) } else output.headers.push(new __PulseFastlyHeader(name, __pulse_fastly_string(unchecked(headers.values[i])))) } return } if (headers.kind == PULSE_VALUE_ARRAY) { for (let i = 0; i < headers.values.length; i += 1) { const pair = __pulse_fastly_value(unchecked(headers.values[i])); if (pair.kind != PULSE_VALUE_ARRAY || pair.values.length < 2) continue; output.headers.push(new __PulseFastlyHeader(__pulse_fastly_string(unchecked(pair.values[0])), __pulse_fastly_string(unchecked(pair.values[1])))) } } }
563
591
  function __pulse_fastly_response(value: i32, optionsHandle: i32, json: bool): i32 { const output = new __PulseFastlyValue(); output.kind = PULSE_VALUE_RESPONSE; output.status = 200; const options = __pulse_fastly_value(optionsHandle); let bodyValue = value; if (options.kind == PULSE_VALUE_OBJECT) { const statusIndex = __pulse_fastly_find(options, "status"); if (statusIndex >= 0) output.status = i32(__pulse_fastly_number(unchecked(options.values[statusIndex]))); const schemaIndex = __pulse_fastly_find(options, "schema"); if (json && schemaIndex >= 0) { bodyValue = __pulse_fastly_schema_apply(__pulse_fastly_string(unchecked(options.values[schemaIndex])), value, true); if (bodyValue <= 0) return 0 } __pulse_fastly_headers_from_options(options, output) } output.text = json ? __pulse_fastly_json(bodyValue, 0) : __pulse_fastly_string(value); let hasContentType = false; for (let i = 0; i < output.headers.length; i += 1) if (unchecked(output.headers[i]).name.toLowerCase() == "content-type") hasContentType = true; if (!hasContentType) output.headers.push(new __PulseFastlyHeader("content-type", json ? "application/json; charset=utf-8" : "text/plain; charset=utf-8")); return __pulse_fastly_put(output) }
564
592
  function host_response_json(value: i32, options: i32): i32 { return __pulse_fastly_response(value, options, true) }
593
+ function host_schema_encode(value: i32, schema: i32): i32 {
594
+ const id = __pulse_fastly_value(schema)
595
+ if (id.kind != PULSE_VALUE_STRING || id.text.length == 0) { __pulse_fastly_fail(PULSE_ERROR_SCHEMA, 55, -1); return 0 }
596
+ const projected = __pulse_fastly_schema_apply(id.text, value, true)
597
+ if (projected <= 0) return 0
598
+ const text = __pulse_fastly_json(projected, 0)
599
+ if (String.UTF8.byteLength(text) > __PULSE_SCHEMA_MAX_BYTES) { __pulse_fastly_fail(PULSE_ERROR_SCHEMA, 21, -1); return 0 }
600
+ return __pulse_fastly_string_value(text)
601
+ }
565
602
  function host_response_text(value: i32, options: i32): i32 { return __pulse_fastly_response(value, options, false) }
566
603
  function host_response_custom(specHandle: i32): i32 { const spec = __pulse_fastly_value(specHandle); if (spec.kind != PULSE_VALUE_OBJECT) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 40, -1); return 0 } const output = new __PulseFastlyValue(); output.kind = PULSE_VALUE_RESPONSE; output.status = 200; const statusIndex = __pulse_fastly_find(spec, "status"); if (statusIndex >= 0) output.status = i32(__pulse_fastly_number(unchecked(spec.values[statusIndex]))); const bodyIndex = __pulse_fastly_find(spec, "body"); if (bodyIndex >= 0) output.text = __pulse_fastly_string(unchecked(spec.values[bodyIndex])); __pulse_fastly_headers_from_options(spec, output); return __pulse_fastly_put(output) }
567
604
  function __pulse_fastly_grip_frame_channels(options: __PulseFastlyValue, output: __PulseFastlyValue): bool { const channelsIndex = __pulse_fastly_find(options, "channels"); const channelIndex = __pulse_fastly_find(options, "channel"); let count = 0; if (channelsIndex >= 0) { const channels = __pulse_fastly_value(unchecked(options.values[channelsIndex])); if (channels.kind != PULSE_VALUE_ARRAY) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 133, -1); return false } for (let i = 0; i < channels.values.length; i += 1) { const channel = __pulse_fastly_string(unchecked(channels.values[i])).trim(); if (channel.length == 0 || channel.indexOf(",") >= 0 || channel.indexOf("\r") >= 0 || channel.indexOf("\n") >= 0) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 134, -1); return false } output.headers.push(new __PulseFastlyHeader("Grip-Channel", channel)); count += 1 } } else if (channelIndex >= 0) { const channel = __pulse_fastly_string(unchecked(options.values[channelIndex])).trim(); if (channel.length == 0 || channel.indexOf(",") >= 0 || channel.indexOf("\r") >= 0 || channel.indexOf("\n") >= 0) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 134, -1); return false } output.headers.push(new __PulseFastlyHeader("Grip-Channel", channel)); count = 1 } if (count == 0) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 135, -1); return false } return true }
@@ -573,7 +610,7 @@ function host_kv_namespace(name: i32): i32 { __pulse_fastly_fail(PULSE_ERROR_UNS
573
610
  function host_fetch_text(responseHandle: i32): i32 { const response = __pulse_fastly_value(responseHandle); if (response.kind != PULSE_VALUE_FETCH) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 42, -1); return 0 } return __pulse_fastly_string_value(__pulse_fastly_fetch_body(response)) }
574
611
  function host_fetch_json(responseHandle: i32, schemaHandle: i32): i32 { const response = __pulse_fastly_value(responseHandle); if (response.kind != PULSE_VALUE_FETCH) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 43, -1); return 0 } if (__PULSE_SCHEMA_REQUIRE_JSON) { const contentType = __pulse_fastly_fetch_header_text(response.responseHandle, "content-type"); if (contentType.length == 0 || contentType.toLowerCase().indexOf("json") < 0) { __pulse_fastly_fail(PULSE_ERROR_SCHEMA, 44, -1); return 0 } } const parsed = __pulse_fastly_parse_json(__pulse_fastly_fetch_body(response)); if (parsed <= 0) return 0; const schema = __pulse_fastly_value(schemaHandle); return schema.kind == PULSE_VALUE_STRING ? __pulse_fastly_schema_apply(schema.text, parsed, false) : parsed }
575
612
  function host_fetch_header(responseHandle: i32, nameHandle: i32): i32 { const response = __pulse_fastly_value(responseHandle); if (response.kind != PULSE_VALUE_FETCH) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 45, -1); return 0 } const value = __pulse_fastly_fetch_header_text(response.responseHandle, __pulse_fastly_string(nameHandle)); return value.length == 0 ? host_value_undefined() : __pulse_fastly_string_value(value) }
576
- function host_effect_begin(effectIndex: i32, payload: i32): void { if (effectIndex < 0 || effectIndex >= PULSE_FASTLY_EFFECT_COUNT || unchecked(__pulse_fastly_pending_active[effectIndex]) != 0) { __pulse_fastly_fail(PULSE_ERROR_STATE, 46, effectIndex); return } const payloadValue = __pulse_fastly_value(payload); if (payloadValue.kind != PULSE_VALUE_OBJECT) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 47, effectIndex); return } const urlIndex = __pulse_fastly_find(payloadValue, "url"); if (urlIndex < 0) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 48, effectIndex); return } const url = __pulse_fastly_string(unchecked(payloadValue.values[urlIndex])); const initIndex = __pulse_fastly_find(payloadValue, "init"); const init = initIndex >= 0 ? __pulse_fastly_value(unchecked(payloadValue.values[initIndex])) : new __PulseFastlyValue(); let method = "GET"; let body = ""; let headers = new __PulseFastlyValue(); headers.kind = PULSE_VALUE_OBJECT; if (init.kind == PULSE_VALUE_OBJECT) { const methodIndex = __pulse_fastly_find(init, "method"); if (methodIndex >= 0) method = __pulse_fastly_string(unchecked(init.values[methodIndex])).toUpperCase(); const headersIndex = __pulse_fastly_find(init, "headers"); if (headersIndex >= 0) headers = __pulse_fastly_value(unchecked(init.values[headersIndex])); const bodyIndex = __pulse_fastly_find(init, "body"); if (bodyIndex >= 0) { const bodyValue = unchecked(init.values[bodyIndex]); const bodyObject = __pulse_fastly_value(bodyValue); body = bodyObject.kind == PULSE_VALUE_STRING ? bodyObject.text : __pulse_fastly_json(bodyValue, 0) } }
613
+ function host_effect_begin(effectIndex: i32, payload: i32): void { ${(plan.schemas && plan.schemas.references || []).some(entry => entry.usage === 'value-encode') ? 'if (__pulse_fastly_last_error != PULSE_ERROR_NONE) return; ' : ''}if (effectIndex < 0 || effectIndex >= PULSE_FASTLY_EFFECT_COUNT || unchecked(__pulse_fastly_pending_active[effectIndex]) != 0) { __pulse_fastly_fail(PULSE_ERROR_STATE, 46, effectIndex); return } const payloadValue = __pulse_fastly_value(payload); if (payloadValue.kind != PULSE_VALUE_OBJECT) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 47, effectIndex); return } const urlIndex = __pulse_fastly_find(payloadValue, "url"); if (urlIndex < 0) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 48, effectIndex); return } const url = __pulse_fastly_string(unchecked(payloadValue.values[urlIndex])); const initIndex = __pulse_fastly_find(payloadValue, "init"); const init = initIndex >= 0 ? __pulse_fastly_value(unchecked(payloadValue.values[initIndex])) : new __PulseFastlyValue(); let method = "GET"; let body = ""; let headers = new __PulseFastlyValue(); headers.kind = PULSE_VALUE_OBJECT; if (init.kind == PULSE_VALUE_OBJECT) { const methodIndex = __pulse_fastly_find(init, "method"); if (methodIndex >= 0) method = __pulse_fastly_string(unchecked(init.values[methodIndex])).toUpperCase(); const headersIndex = __pulse_fastly_find(init, "headers"); if (headersIndex >= 0) headers = __pulse_fastly_value(unchecked(init.values[headersIndex])); const bodyIndex = __pulse_fastly_find(init, "body"); if (bodyIndex >= 0) { const bodyValue = unchecked(init.values[bodyIndex]); const bodyObject = __pulse_fastly_value(bodyValue); body = bodyObject.kind == PULSE_VALUE_STRING ? bodyObject.text : __pulse_fastly_json(bodyValue, 0) } }
577
614
  const requestOut = __pulse_fastly_out_i32(); let status = fastly_http_req_new(changetype<usize>(requestOut)); if (status != FASTLY_STATUS_OK) { __pulse_fastly_fail(PULSE_ERROR_HOSTCALL, 70, effectIndex); return } const requestHandle = __pulse_fastly_out_value(requestOut)
578
615
  const bodyOut = __pulse_fastly_out_i32(); status = fastly_http_body_new(changetype<usize>(bodyOut)); if (status != FASTLY_STATUS_OK) { __pulse_fastly_fail(PULSE_ERROR_HOSTCALL, 71, effectIndex); return } const bodyHandle = __pulse_fastly_out_value(bodyOut)
579
616
  const methodBytes = __pulse_fastly_utf8(method); status = fastly_http_req_method_set(requestHandle, changetype<usize>(methodBytes), methodBytes.byteLength); if (status != FASTLY_STATUS_OK) { __pulse_fastly_fail(PULSE_ERROR_HOSTCALL, 72, effectIndex); return }
@@ -635,7 +672,7 @@ function generateFastlyNativeHttpEffectsAssemblyScript(plan, options = {}) {
635
672
  const portableSource = stripPulseHostImports(portable.source);
636
673
  const source = [
637
674
  '/* Generated by Pulse Pass97 Fastly native HTTP effects compiler. */',
638
- 'export function __pulse_fastly_abort(message: string | null, fileName: string | null, line: u32, column: u32): void { unreachable() }',
675
+ 'export function __pulse_fastly_abort(message: string | null, fileName: string | null = null, line: u32 = 0, column: u32 = 0): void { unreachable() }',
639
676
  '',
640
677
  fastlyRuntimeSource(plan, bindings),
641
678
  portableSource,
@@ -785,7 +822,7 @@ function compileFastlyNativeHttpEffectsPlan(plan, options = {}) {
785
822
  maxBuffer: 64 * 1024 * 1024,
786
823
  timeout: Number(options.timeoutMs || 180000),
787
824
  env: schemaCodecsActive
788
- ? { ...process.env, JSON_STRICT: 'true', JSON_USE_FAST_PATH: '0' }
825
+ ? { ...process.env, JSON_STRICT: 'true', JSON_USE_FAST_PATH: '0', JSON_MODE: 'NAIVE' }
789
826
  : process.env
790
827
  });
791
828
  const durationMs = Date.now() - startedAt;
@@ -808,7 +845,7 @@ function compileFastlyNativeHttpEffectsPlan(plan, options = {}) {
808
845
  compilerVersion: FASTLY_NATIVE_HTTP_EFFECTS_COMPILER_VERSION,
809
846
  assemblyScript: Object.freeze({ package: 'assemblyscript', version: require(path.join(asc.packageRoot, 'package.json')).version }),
810
847
  jsonAs: jsonAs
811
- ? Object.freeze({ package: 'json-as', version: jsonAs.version, transform: true, strict: true })
848
+ ? Object.freeze({ package: 'json-as', version: jsonAs.version, transform: true, strict: true, mode: 'NAIVE', fastPath: false })
812
849
  : undefined,
813
850
  wasm: Object.freeze({ bytes: inspection.bytes, sha256: inspection.sha256, magic: inspection.magic }),
814
851
  wat: Object.freeze({ bytes: Buffer.byteLength(wat), sha256: sha256(wat) }),
@@ -1094,6 +1094,7 @@ function effectDispatchSource(plan) {
1094
1094
  const kinds = [...new Set((plan.effects || []).map((effect) => effect.kind))];
1095
1095
  const lines = [
1096
1096
  'function host_effect_begin(effectIndex: i32, payload: i32): void {',
1097
+ ...((plan.schemas && plan.schemas.references || []).some(entry => entry.usage === 'value-encode') ? [' if (__pulse_fastly_last_error != PULSE_ERROR_NONE) return'] : []),
1097
1098
  ' if (effectIndex < 0 || effectIndex >= PULSE_FASTLY_EFFECT_COUNT || unchecked(__pulse_fastly_pending_mode[effectIndex]) != PULSE_FASTLY_PENDING_NONE) { __pulse_fastly_fail(PULSE_ERROR_STATE, 46, effectIndex); return }',
1098
1099
  ' const payloadValue = __pulse_fastly_value(payload)',
1099
1100
  ' if (payloadValue.kind != PULSE_VALUE_OBJECT) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 47, effectIndex); return }',
@@ -1550,6 +1551,15 @@ function host_request_json(schema: i32): i32 { const parsed = __pulse_fastly_par
1550
1551
  function __pulse_fastly_headers_from_options(options: __PulseFastlyValue, output: __PulseFastlyValue): void { const index = __pulse_fastly_find(options, "headers"); if (index < 0) return; const headers = __pulse_fastly_value(unchecked(options.values[index])); if (headers.kind == PULSE_VALUE_OBJECT) { for (let i = 0; i < headers.keys.length; i += 1) { const name = unchecked(headers.keys[i]); const value = __pulse_fastly_value(unchecked(headers.values[i])); if (value.kind == PULSE_VALUE_ARRAY) { for (let j = 0; j < value.values.length; j += 1) output.headers.push(new __PulseFastlyHeader(name, __pulse_fastly_string(unchecked(value.values[j])))) } else output.headers.push(new __PulseFastlyHeader(name, __pulse_fastly_string(unchecked(headers.values[i])))) } return } if (headers.kind == PULSE_VALUE_ARRAY) { for (let i = 0; i < headers.values.length; i += 1) { const pair = __pulse_fastly_value(unchecked(headers.values[i])); if (pair.kind != PULSE_VALUE_ARRAY || pair.values.length < 2) continue; output.headers.push(new __PulseFastlyHeader(__pulse_fastly_string(unchecked(pair.values[0])), __pulse_fastly_string(unchecked(pair.values[1])))) } } }
1551
1552
  function __pulse_fastly_response(value: i32, optionsHandle: i32, json: bool): i32 { const output = new __PulseFastlyValue(); output.kind = PULSE_VALUE_RESPONSE; output.status = 200; const options = __pulse_fastly_value(optionsHandle); let bodyValue = value; if (options.kind == PULSE_VALUE_OBJECT) { const statusIndex = __pulse_fastly_find(options, "status"); if (statusIndex >= 0) output.status = i32(__pulse_fastly_number(unchecked(options.values[statusIndex]))); const schemaIndex = __pulse_fastly_find(options, "schema"); if (json && schemaIndex >= 0) { bodyValue = __pulse_fastly_schema_apply(__pulse_fastly_string(unchecked(options.values[schemaIndex])), value, true); if (bodyValue <= 0) return 0 } __pulse_fastly_headers_from_options(options, output) } output.text = json ? __pulse_fastly_json(bodyValue, 0) : __pulse_fastly_string(value); let hasContentType = false; for (let i = 0; i < output.headers.length; i += 1) if (unchecked(output.headers[i]).name.toLowerCase() == "content-type") hasContentType = true; if (!hasContentType) output.headers.push(new __PulseFastlyHeader("content-type", json ? "application/json; charset=utf-8" : "text/plain; charset=utf-8")); return __pulse_fastly_put(output) }
1552
1553
  function host_response_json(value: i32, options: i32): i32 { return __pulse_fastly_response(value, options, true) }
1554
+ function host_schema_encode(value: i32, schema: i32): i32 {
1555
+ const id = __pulse_fastly_value(schema)
1556
+ if (id.kind != PULSE_VALUE_STRING || id.text.length == 0) { __pulse_fastly_fail(PULSE_ERROR_SCHEMA, 55, -1); return 0 }
1557
+ const projected = __pulse_fastly_schema_apply(id.text, value, true)
1558
+ if (projected <= 0) return 0
1559
+ const text = __pulse_fastly_json(projected, 0)
1560
+ if (String.UTF8.byteLength(text) > __PULSE_SCHEMA_MAX_BYTES) { __pulse_fastly_fail(PULSE_ERROR_SCHEMA, 21, -1); return 0 }
1561
+ return __pulse_fastly_string_value(text)
1562
+ }
1553
1563
  function host_response_text(value: i32, options: i32): i32 { return __pulse_fastly_response(value, options, false) }
1554
1564
  function host_response_custom(specHandle: i32): i32 { const spec = __pulse_fastly_value(specHandle); if (spec.kind != PULSE_VALUE_OBJECT) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 40, -1); return 0 } const output = new __PulseFastlyValue(); output.kind = PULSE_VALUE_RESPONSE; output.status = 200; const statusIndex = __pulse_fastly_find(spec, "status"); if (statusIndex >= 0) output.status = i32(__pulse_fastly_number(unchecked(spec.values[statusIndex]))); const bodyIndex = __pulse_fastly_find(spec, "body"); if (bodyIndex >= 0) output.text = __pulse_fastly_string(unchecked(spec.values[bodyIndex])); __pulse_fastly_headers_from_options(spec, output); return __pulse_fastly_put(output) }
1555
1565
  function __pulse_fastly_grip_frame_channels(options: __PulseFastlyValue, output: __PulseFastlyValue): bool { const channelsIndex = __pulse_fastly_find(options, "channels"); const channelIndex = __pulse_fastly_find(options, "channel"); let count = 0; if (channelsIndex >= 0) { const channels = __pulse_fastly_value(unchecked(options.values[channelsIndex])); if (channels.kind != PULSE_VALUE_ARRAY) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 133, -1); return false } for (let i = 0; i < channels.values.length; i += 1) { const channel = __pulse_fastly_string(unchecked(channels.values[i])).trim(); if (channel.length == 0 || channel.indexOf(",") >= 0 || channel.indexOf("\r") >= 0 || channel.indexOf("\n") >= 0) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 134, -1); return false } output.headers.push(new __PulseFastlyHeader("Grip-Channel", channel)); count += 1 } } else if (channelIndex >= 0) { const channel = __pulse_fastly_string(unchecked(options.values[channelIndex])).trim(); if (channel.length == 0 || channel.indexOf(",") >= 0 || channel.indexOf("\r") >= 0 || channel.indexOf("\n") >= 0) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 134, -1); return false } output.headers.push(new __PulseFastlyHeader("Grip-Channel", channel)); count = 1 } if (count == 0) { __pulse_fastly_fail(PULSE_ERROR_VALUE, 135, -1); return false } return true }
@@ -1972,7 +1982,7 @@ function compileFastlyNativePlatformCapabilitiesPlan(plan, options = {}) {
1972
1982
  maxBuffer: 64 * 1024 * 1024,
1973
1983
  timeout: Number(options.timeoutMs || 180000),
1974
1984
  env: schemaCodecsActive
1975
- ? { ...process.env, JSON_STRICT: 'true', JSON_USE_FAST_PATH: '0' }
1985
+ ? { ...process.env, JSON_STRICT: 'true', JSON_USE_FAST_PATH: '0', JSON_MODE: 'NAIVE' }
1976
1986
  : process.env
1977
1987
  });
1978
1988
  const assemblyScriptDurationMs = Date.now() - startedAt;
@@ -2112,7 +2122,7 @@ function compileFastlyNativePlatformCapabilitiesPlan(plan, options = {}) {
2112
2122
  compilerVersion: FASTLY_NATIVE_PLATFORM_CAPABILITIES_COMPILER_VERSION,
2113
2123
  assemblyScript: Object.freeze({ package: 'assemblyscript', version: require(path.join(asc.packageRoot, 'package.json')).version }),
2114
2124
  jsonAs: jsonAs
2115
- ? Object.freeze({ package: 'json-as', version: jsonAs.version, transform: true, strict: true })
2125
+ ? Object.freeze({ package: 'json-as', version: jsonAs.version, transform: true, strict: true, mode: 'NAIVE', fastPath: false })
2116
2126
  : undefined,
2117
2127
  optimization,
2118
2128
  wasm: Object.freeze({ bytes: inspection.bytes, sha256: inspection.sha256, magic: inspection.magic }),
@@ -242,6 +242,7 @@ function createDriver() {
242
242
  javascript: FASTLY_JAVASCRIPT_TARGET_DESCRIPTOR
243
243
  }),
244
244
  execute: fastlyRuntime.executeCanonicalProgram,
245
+ prepareNativeExecution: require('./native-execution.js').prepareFastlyNativeExecution,
245
246
  createLoweringPlan(metadata, providerConfig = {}) {
246
247
  return createFastlyLoweringPlan(metadata, providerConfig.bindings || {});
247
248
  },
@@ -0,0 +1,71 @@
1
+ 'use strict';
2
+
3
+ const { inspectFastlyCanonicalTarget } = require('../build/canonical-target.js');
4
+ const { executeFastlyNativePlatformCapabilities } = require('../testing/native-platform-capabilities-host.js');
5
+ const { createConditionalKvAuthority } = require('../testing/conditional-kv-host.js');
6
+
7
+ // Execute the provider artifact against the existing fixture ABI. This is local
8
+ // conformance evidence, never Viceroy or deployed Fastly acceptance.
9
+ function prepareFastlyNativeExecution(invocation) {
10
+ const bindings = invocation.providerConfig.bindings;
11
+ const { native } = inspectFastlyCanonicalTarget({
12
+ plan: invocation.applicationPlan,
13
+ providerConfig: invocation.providerConfig,
14
+ projectRoot: invocation.project.root,
15
+ profile: invocation.project.profile,
16
+ targetDescriptor: invocation.selectedTarget,
17
+ synchronizedPackages: invocation.synchronizedPackages,
18
+ realizationArtifacts: invocation.nativeArtifact.realizationArtifacts,
19
+ guestUnits: invocation.nativeArtifact.guestUnits,
20
+ nativeOptimization: invocation.optimization,
21
+ compileTimeoutMs: invocation.timeoutMs || undefined
22
+ });
23
+ const evidence = Object.freeze({
24
+ kind: 'fastly-native-fixture-abi',
25
+ provider: 'fastly',
26
+ target: 'fastly-compute-native',
27
+ wasmSha256: native.manifest.wasm.sha256,
28
+ providerRealityValidated: false,
29
+ effectObservations: 'unavailable'
30
+ });
31
+ return (options = {}) => {
32
+ if (options.liveFetch === true) throw new TypeError('Fastly Native fixture execution cannot perform live fetches.');
33
+ const kvStores = {};
34
+ for (const [logical, physical] of Object.entries(bindings.kv || {})) {
35
+ kvStores[physical] = { ...kvStores[physical], ...(options.kv && options.kv[logical] || {}) };
36
+ }
37
+ const authority = createConditionalKvAuthority();
38
+ for (const [store, values] of Object.entries(kvStores)) {
39
+ authority.stores.set(store, new Map());
40
+ for (const [key, value] of Object.entries(values)) {
41
+ authority.seed(store, key, Buffer.from(JSON.stringify({ __pulseKv: 1, value })));
42
+ }
43
+ }
44
+ const execution = executeFastlyNativePlatformCapabilities(native, {
45
+ request: options.request,
46
+ fixtures: options.fetches,
47
+ configStore: bindings.configStore,
48
+ config: options.config,
49
+ secretStore: bindings.secretStore,
50
+ secrets: options.secrets,
51
+ kvStores,
52
+ conditionalKv: { authority }
53
+ });
54
+ const contentType = execution.response.headers.find(([name]) => name.toLowerCase() === 'content-type');
55
+ const type = String(contentType && contentType[1] || '').toLowerCase();
56
+ return Object.freeze({
57
+ response: Object.freeze({
58
+ ...execution.response,
59
+ kind: type.includes('application/json') || type.includes('+json') ? 'json' : type.startsWith('text/') ? 'text' : 'response',
60
+ bodyClass: execution.response.origin === true ? 'opaque' : 'structured'
61
+ }),
62
+ // The fixture ABI has hostcall traces, not canonical continuation telemetry.
63
+ effectCount: null,
64
+ continuations: Object.freeze([]),
65
+ resolutionOrder: Object.freeze([]),
66
+ evidence
67
+ });
68
+ };
69
+ }
70
+
71
+ module.exports = { prepareFastlyNativeExecution };