diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index dece3f9a4a..855ab89b0f 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -10,7 +10,7 @@ defaults:
run:
shell: bash
env:
- viceroy_version: 0.4.4
+ viceroy_version: 0.5.1
wasm-tools_version: 1.0.28
jobs:
@@ -128,7 +128,7 @@ jobs:
matrix:
include:
- crate: viceroy
- version: 0.4.4 # Note: workflow-level env vars can't be used in matrix definitions
+ version: 0.5.1 # Note: workflow-level env vars can't be used in matrix definitions
options: ""
- crate: wasm-tools
version: 1.0.28 # Note: workflow-level env vars can't be used in matrix definitions
@@ -383,6 +383,7 @@ jobs:
- 'byob'
- 'byte-repeater'
- 'cache-override'
+ - 'cache-simple'
- 'crypto'
- 'edge-dictionary'
- 'error'
diff --git a/integration-tests/js-compute/assertions.js b/integration-tests/js-compute/assertions.js
index 71b7fd27ca..9781d0e475 100644
--- a/integration-tests/js-compute/assertions.js
+++ b/integration-tests/js-compute/assertions.js
@@ -1,5 +1,33 @@
+/* global ReadableStream */
+
// Testing/Assertion functions //
+// TODO: Implement ReadableStream getIterator() and [@@asyncIterator]() methods
+export async function streamToString(stream) {
+ const decoder = new TextDecoder();
+ let string = '';
+ let reader = stream.getReader()
+ // eslint-disable-next-line no-constant-condition
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) {
+ return string;
+ }
+ string += decoder.decode(value)
+ }
+}
+
+export function iteratableToStream(iterable) {
+ return new ReadableStream({
+ async pull(controller) {
+ for await (const value of iterable) {
+ controller.enqueue(value);
+ }
+ controller.close();
+ }
+ });
+}
+
export function pass(message = '') {
return new Response(message)
}
diff --git a/integration-tests/js-compute/fixtures/cache-simple/bin/index.js b/integration-tests/js-compute/fixtures/cache-simple/bin/index.js
new file mode 100644
index 0000000000..32ee3c4dd2
--- /dev/null
+++ b/integration-tests/js-compute/fixtures/cache-simple/bin/index.js
@@ -0,0 +1,1011 @@
+///
+/* eslint-env serviceworker */
+/* global ReadableStream */
+import { pass, assert, assertDoesNotThrow, assertThrows, assertRejects, iteratableToStream, streamToString } from "../../../assertions.js";
+import { routes, FASTLY_SERVICE_VERSION } from "../../../test-harness.js";
+import { SimpleCache, SimpleCacheEntry } from 'fastly:cache';
+
+let error;
+routes.set("/simple-cache/interface", () => {
+ let actual = Reflect.ownKeys(SimpleCache)
+ let expected = ["prototype", "delete", "get", "set", "length", "name"]
+ error = assert(actual, expected, `Reflect.ownKeys(SimpleCache)`)
+ if (error) { return error }
+
+ // Check the prototype descriptors are correct
+ {
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache, 'prototype')
+ expected = {
+ "value": SimpleCache.prototype,
+ "writable": false,
+ "enumerable": false,
+ "configurable": false
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache, 'prototype')`)
+ if (error) { return error }
+ }
+
+ // Check the constructor function's defined parameter length is correct
+ {
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache, 'length')
+ expected = {
+ "value": 0,
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache, 'length')`)
+ if (error) { return error }
+ }
+
+ // Check the constructor function's name is correct
+ {
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache, 'name')
+ expected = {
+ "value": "SimpleCache",
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache, 'name')`)
+ if (error) { return error }
+ }
+
+ // Check the prototype has the correct keys
+ {
+ actual = Reflect.ownKeys(SimpleCache.prototype)
+ expected = ["constructor", Symbol.toStringTag]
+ error = assert(actual, expected, `Reflect.ownKeys(SimpleCache.prototype)`)
+ if (error) { return error }
+ }
+
+ // Check the constructor on the prototype is correct
+ {
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache.prototype, 'constructor')
+ expected = { "writable": true, "enumerable": false, "configurable": true, value: SimpleCache.prototype.constructor }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache.prototype, 'constructor')`)
+ if (error) { return error }
+
+ error = assert(typeof SimpleCache.prototype.constructor, 'function', `typeof SimpleCache.prototype.constructor`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache.prototype.constructor, 'length')
+ expected = {
+ "value": 0,
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache.prototype.constructor, 'length')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache.prototype.constructor, 'name')
+ expected = {
+ "value": "SimpleCache",
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache.prototype.constructor, 'name')`)
+ if (error) { return error }
+ }
+
+ // Check the Symbol.toStringTag on the prototype is correct
+ {
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache.prototype, Symbol.toStringTag)
+ expected = { "writable": false, "enumerable": false, "configurable": true, value: "SimpleCache" }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache.prototype, [Symbol.toStringTag])`)
+ if (error) { return error }
+
+ error = assert(typeof SimpleCache.prototype[Symbol.toStringTag], 'string', `typeof SimpleCache.prototype[Symbol.toStringTag]`)
+ if (error) { return error }
+ }
+
+ // Check the get static method has correct descriptors, length and name
+ {
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache, 'get')
+ expected = { "writable": true, "enumerable": true, "configurable": true, value: SimpleCache.get }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache, 'get')`)
+ if (error) { return error }
+
+ error = assert(typeof SimpleCache.get, 'function', `typeof SimpleCache.get`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache.get, 'length')
+ expected = {
+ "value": 1,
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache.get, 'length')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache.get, 'name')
+ expected = {
+ "value": "get",
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache.get, 'name')`)
+ if (error) { return error }
+ }
+
+ // Check the set static method has correct descriptors, length and name
+ {
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache, 'set')
+ expected = { "writable": true, "enumerable": true, "configurable": true, value: SimpleCache.set }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache, 'set')`)
+ if (error) { return error }
+
+ error = assert(typeof SimpleCache.set, 'function', `typeof SimpleCache.set`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache.set, 'length')
+ expected = {
+ "value": 3,
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache.set, 'length')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache.set, 'name')
+ expected = {
+ "value": "set",
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache.set, 'name')`)
+ if (error) { return error }
+ }
+
+ // Check the delete static method has correct descriptors, length and name
+ {
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache, 'delete')
+ expected = { "writable": true, "enumerable": true, "configurable": true, value: SimpleCache.delete }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache, 'delete')`)
+ if (error) { return error }
+
+ error = assert(typeof SimpleCache.delete, 'function', `typeof SimpleCache.delete`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache.delete, 'length')
+ expected = {
+ "value": 1,
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache.delete, 'length')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCache.delete, 'name')
+ expected = {
+ "value": "delete",
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCache.delete, 'name')`)
+ if (error) { return error }
+ }
+
+ return pass()
+});
+
+// SimpleCache constructor
+{
+
+ routes.set("/simple-store/constructor/called-as-regular-function", () => {
+ error = assertThrows(() => {
+ SimpleCache()
+ }, TypeError, `Illegal constructor`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/constructor/throws", () => {
+ error = assertThrows(() => new SimpleCache(), TypeError, `Illegal constructor`)
+ if (error) { return error }
+ return pass()
+ });
+}
+
+// SimpleCache delete static method
+// static delete(key: string): undefined;
+{
+ routes.set("/simple-cache/delete/called-as-constructor", () => {
+ error = assertThrows(() => {
+ new SimpleCache.delete('1')
+ }, TypeError, `SimpleCache.delete is not a constructor`)
+ if (error) { return error }
+ return pass()
+ });
+ // Ensure we correctly coerce the parameter to a string as according to
+ // https://tc39.es/ecma262/#sec-tostring
+ routes.set("/simple-cache/delete/key-parameter-calls-7.1.17-ToString", () => {
+ let sentinel;
+ const test = () => {
+ sentinel = Symbol('sentinel');
+ const key = {
+ toString() {
+ throw sentinel;
+ }
+ }
+ SimpleCache.delete(key)
+ }
+ error = assertThrows(test)
+ if (error) { return error }
+ try {
+ test()
+ } catch (thrownError) {
+ error = assert(thrownError, sentinel, 'thrownError === sentinel')
+ if (error) { return error }
+ }
+ error = assertThrows(() => {
+ SimpleCache.delete(Symbol())
+ }, TypeError, `can't convert symbol to string`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/delete/key-parameter-not-supplied", () => {
+ error = assertThrows(() => {
+ SimpleCache.delete()
+ }, TypeError, `SimpleCache.delete: At least 1 argument required, but only 0 passed`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/delete/key-parameter-empty-string", () => {
+ error = assertThrows(() => {
+ SimpleCache.delete('')
+ }, Error, `SimpleCache.delete: key can not be an empty string`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/delete/key-parameter-1024-character-string", () => {
+ error = assertDoesNotThrow(() => {
+ const key = 'a'.repeat(1024)
+ SimpleCache.delete(key)
+ })
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/delete/key-parameter-1025-character-string", () => {
+ error = assertThrows(() => {
+ const key = 'a'.repeat(1025)
+ SimpleCache.delete(key)
+ }, Error, `SimpleCache.delete: key is too long, the maximum allowed length is 1024.`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/delete/returns-undefined", () => {
+ error = assert(SimpleCache.delete('meow'), undefined, "SimpleCache.delete('meow') === undefined")
+ if (error) { return error }
+ return pass()
+ });
+}
+
+// SimpleCache set static method
+// static set(key: string, value: BodyInit, ttl: number): undefined;
+{
+ routes.set("/simple-cache/set/called-as-constructor", () => {
+ error = assertThrows(() => {
+ new SimpleCache.set('1', 'meow', 1)
+ }, TypeError, `SimpleCache.set is not a constructor`)
+ if (error) { return error }
+ return pass()
+ });
+ // Ensure we correctly coerce the key parameter to a string as according to
+ // https://tc39.es/ecma262/#sec-tostring
+ routes.set("/simple-cache/set/key-parameter-calls-7.1.17-ToString", () => {
+ let sentinel;
+ const test = () => {
+ sentinel = Symbol('sentinel');
+ const key = {
+ toString() {
+ throw sentinel;
+ }
+ }
+ SimpleCache.set(key, 'meow', 1)
+ }
+ error = assertThrows(test)
+ if (error) { return error }
+ try {
+ test()
+ } catch (thrownError) {
+ error = assert(thrownError, sentinel, 'thrownError === sentinel')
+ if (error) { return error }
+ }
+ error = assertThrows(() => {
+ SimpleCache.set(Symbol(), 'meow', 1)
+ }, TypeError, `can't convert symbol to string`)
+ if (error) { return error }
+ return pass()
+ });
+ // Ensure we correctly coerce the tll parameter to a number as according to
+ // https://tc39.es/ecma262/#sec-tonumber
+ routes.set("/simple-cache/set/tll-parameter-7.1.4-ToNumber", () => {
+ let sentinel;
+ let requestedType;
+ const test = () => {
+ sentinel = Symbol('sentinel');
+ const ttl = {
+ [Symbol.toPrimitive](type) {
+ requestedType = type;
+ throw sentinel;
+ }
+ }
+ SimpleCache.set('1', 'meow', ttl)
+ }
+ let error = assertThrows(test)
+ if (error) { return error }
+ try {
+ test()
+ } catch (thrownError) {
+ let error = assert(thrownError, sentinel, 'thrownError === sentinel')
+ if (error) { return error }
+ error = assert(requestedType, 'number', 'requestedType === "number"')
+ if (error) { return error }
+ }
+ error = assertThrows(() => SimpleCache.set('1', 'meow', Symbol()), TypeError, `can't convert symbol to number`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/no-parameters-supplied", () => {
+ error = assertThrows(() => {
+ SimpleCache.set()
+ }, TypeError, `SimpleCache.set: At least 3 arguments required, but only 0 passed`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/key-parameter-empty-string", () => {
+ error = assertThrows(() => {
+ SimpleCache.set('', 'meow', 1)
+ }, Error, `SimpleCache.set: key can not be an empty string`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/key-parameter-8135-character-string", () => {
+ error = assertDoesNotThrow(() => {
+ const key = 'a'.repeat(8135)
+ SimpleCache.set(key, 'meow', 1)
+ })
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/key-parameter-8136-character-string", () => {
+ error = assertThrows(() => {
+ const key = 'a'.repeat(8136)
+ SimpleCache.set(key, 'meow', 1)
+ }, Error, `SimpleCache.set: key is too long, the maximum allowed length is 8135.`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/ttl-parameter-negative-number", () => {
+ error = assertThrows(() => {
+ SimpleCache.set('cat', 'meow', -1)
+ }, Error, `SimpleCache.set: TTL parameter is an invalid value, only positive numbers can be used for TTL values.`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/ttl-parameter-NaN", () => {
+ error = assertThrows(() => {
+ SimpleCache.set('cat', 'meow', NaN)
+ }, Error, `SimpleCache.set: TTL parameter is an invalid value, only positive numbers can be used for TTL values.`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/ttl-parameter-Infinity", () => {
+ error = assertThrows(() => {
+ SimpleCache.set('cat', 'meow', Number.POSITIVE_INFINITY)
+ }, Error, `SimpleCache.set: TTL parameter is an invalid value, only positive numbers can be used for TTL values.`)
+ if (error) { return error }
+ error = assertThrows(() => {
+ SimpleCache.set('cat', 'meow', Number.NEGATIVE_INFINITY)
+ }, Error, `SimpleCache.set: TTL parameter is an invalid value, only positive numbers can be used for TTL values.`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/value-parameter-as-undefined", () => {
+ error = assert(SimpleCache.set("meow", undefined, 1), undefined, 'SimpleCache.set("meow", undefined, 1) === undefined')
+ if (error) { return error }
+ return pass()
+ });
+ // - ReadableStream
+ routes.set("/simple-cache/set/value-parameter-readablestream-missing-length-parameter", () => {
+ // TODO: remove this when streams are supported
+ let error = assertThrows(() => {
+ const stream = iteratableToStream([])
+ SimpleCache.set("meow", stream, 1)
+ }, TypeError, `Content-provided streams are not yet supported for streaming into SimpleCache`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/value-parameter-readablestream-negative-length-parameter", () => {
+ // TODO: remove this when streams are supported
+ let error = assertThrows(() => {
+ const stream = iteratableToStream([])
+ SimpleCache.set("meow", stream, 1, -1)
+ }, TypeError, `Content-provided streams are not yet supported for streaming into SimpleCache`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/value-parameter-readablestream-nan-length-parameter", () => {
+ // TODO: remove this when streams are supported
+ let error = assertThrows(() => {
+ const stream = iteratableToStream([])
+ SimpleCache.set("meow", stream, 1, NaN)
+ }, TypeError, `Content-provided streams are not yet supported for streaming into SimpleCache`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/value-parameter-readablestream-negative-infinity-length-parameter", () => {
+ // TODO: remove this when streams are supported
+ let error = assertThrows(() => {
+ const stream = iteratableToStream([])
+ SimpleCache.set("meow", stream, 1, Number.NEGATIVE_INFINITY)
+ }, TypeError, `Content-provided streams are not yet supported for streaming into SimpleCache`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/value-parameter-readablestream-positive-infinity-length-parameter", () => {
+ // TODO: remove this when streams are supported
+ let error = assertThrows(() => {
+ const stream = iteratableToStream([])
+ SimpleCache.set("meow", stream, 1, Number.POSITIVE_INFINITY)
+ }, TypeError, `Content-provided streams are not yet supported for streaming into SimpleCache`)
+ if (error) { return error }
+ return pass()
+ });
+ // Ensure we correctly coerce the tll parameter to a number as according to
+ // https://tc39.es/ecma262/#sec-tonumber
+ routes.set("/simple-cache/set/length-parameter-7.1.4-ToNumber", async () => {
+ const res = await fetch('https://compute-sdk-test-backend.edgecompute.app/', {
+ backend: "TheOrigin",
+ })
+ let sentinel;
+ let requestedType;
+ const test = () => {
+ sentinel = Symbol('sentinel');
+ const length = {
+ [Symbol.toPrimitive](type) {
+ requestedType = type;
+ throw sentinel;
+ }
+ }
+ SimpleCache.set('1', res.body, 1, length)
+ }
+ let error = assertThrows(test)
+ if (error) { return error }
+ try {
+ test()
+ } catch (thrownError) {
+ let error = assert(thrownError, sentinel, 'thrownError === sentinel')
+ if (error) { return error }
+ error = assert(requestedType, 'number', 'requestedType === "number"')
+ if (error) { return error }
+ }
+ error = assertThrows(() => SimpleCache.set('1', res.body, 1, Symbol()), TypeError, `can't convert symbol to number`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/value-parameter-readablestream-empty", () => {
+ // TODO: remove this when streams are supported
+ let error = assertThrows(() => {
+ const stream = iteratableToStream([])
+ SimpleCache.set("meow", stream, 1, 0)
+ }, TypeError, `Content-provided streams are not yet supported for streaming into SimpleCache`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/value-parameter-readablestream-locked", () => {
+ const stream = iteratableToStream([])
+ // getReader() causes the stream to become locked
+ stream.getReader()
+ let error = assertThrows(() => {
+ SimpleCache.set("meow", stream, 1, 0)
+ }, TypeError, `Can't use a ReadableStream that's locked or has ever been read from or canceled`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/set/value-parameter-readablestream", async () => {
+ const res = await fetch('https://compute-sdk-test-backend.edgecompute.app/', {
+ backend: "TheOrigin",
+ })
+ let result = SimpleCache.set('readablestream', res.body, 100, res.headers.get('content-length'))
+ error = assert(result, undefined, `SimpleCache.set('readablestream', res.body, 100)`)
+ if (error) { return error }
+ return pass()
+ });
+
+ // - URLSearchParams
+ routes.set("/simple-cache/set/value-parameter-URLSearchParams", () => {
+ const items = [
+ new URLSearchParams,
+ new URLSearchParams({ a: 'b', c: 'd' }),
+ ];
+ for (const searchParams of items) {
+ let result = SimpleCache.set("meow", searchParams,1 )
+ error = assert(result, undefined, `SimpleCache.set("meow", searchParams, 1) === undefiend`)
+ if (error) { return error }
+ }
+ return pass()
+ });
+ // - USV strings
+ routes.set("/simple-cache/set/value-parameter-strings", () => {
+ const strings = [
+ // empty
+ '',
+ // lone surrogate
+ '\uD800',
+ // surrogate pair
+ '𠈓',
+ String('carrot'),
+ ];
+ for (const string of strings) {
+ let result = SimpleCache.set("meow", string, 1)
+ error = assert(result, undefined, `SimpleCache.set("meow", string, 1) === undefined`)
+ if (error) { return error }
+ }
+ return pass()
+ });
+
+ // https://tc39.es/ecma262/#sec-tostring
+ routes.set("/simple-cache/set/value-parameter-calls-7.1.17-ToString", () => {
+ let sentinel;
+ const test = () => {
+ sentinel = Symbol('sentinel');
+ const value = {
+ toString() {
+ throw sentinel;
+ }
+ }
+ SimpleCache.set("meow", value, 1)
+ }
+ let error = assertThrows(test)
+ if (error) { return error }
+ try {
+ test()
+ } catch (thrownError) {
+ let error = assert(thrownError, sentinel, 'thrownError === sentinel')
+ if (error) { return error }
+ }
+ error = assertThrows(() => {
+ SimpleCache.set("meow", Symbol(), 1)
+ }, TypeError, `can't convert symbol to string`)
+ if (error) { return error }
+ return pass()
+ });
+
+ // - buffer source
+ routes.set("/simple-cache/set/value-parameter-buffer", () => {
+ const typedArrayConstructors = [
+ Int8Array,
+ Int16Array,
+ Int32Array,
+ Float32Array,
+ Float64Array,
+ BigInt64Array,
+ Uint8Array,
+ Uint8ClampedArray,
+ Uint16Array,
+ Uint32Array,
+ BigUint64Array,
+ ];
+ for (const constructor of typedArrayConstructors) {
+ const typedArray = new constructor(8);
+ let result = SimpleCache.set("meow", typedArray.buffer, 1)
+ error = assert(result, undefined, `SimpleCache.set("meow", typedArray.buffer, 1) === undefined`)
+ if (error) { return error }
+ }
+ return pass()
+ });
+ routes.set("/simple-cache/set/value-parameter-arraybuffer", () => {
+ const typedArrayConstructors = [
+ Int8Array,
+ Int16Array,
+ Int32Array,
+ Float32Array,
+ Float64Array,
+ BigInt64Array,
+ Uint8Array,
+ Uint8ClampedArray,
+ Uint16Array,
+ Uint32Array,
+ BigUint64Array,
+ ];
+ for (const constructor of typedArrayConstructors) {
+ const typedArray = new constructor(8);
+ let result = SimpleCache.set("meow", typedArray.buffer, 1)
+ error = assert(result, undefined, `SimpleCache.set("meow", typedArray.buffer, 1) === undefined`)
+ if (error) { return error }
+ }
+ return pass()
+ });
+ routes.set("/simple-cache/set/value-parameter-typed-arrays", () => {
+ const typedArrayConstructors = [
+ Int8Array,
+ Int16Array,
+ Int32Array,
+ Float32Array,
+ Float64Array,
+ BigInt64Array,
+ Uint8Array,
+ Uint8ClampedArray,
+ Uint16Array,
+ Uint32Array,
+ BigUint64Array,
+ ];
+ for (const constructor of typedArrayConstructors) {
+ const typedArray = new constructor(8);
+ let result = SimpleCache.set("meow", typedArray, 1)
+ error = assert(result, undefined, `SimpleCache.set("meow", typedArray, 1) === undefined`)
+ if (error) { return error }
+ }
+ return pass()
+ });
+ routes.set("/simple-cache/set/value-parameter-dataview", () => {
+ const typedArrayConstructors = [
+ Int8Array,
+ Uint8Array,
+ Uint8ClampedArray,
+ Int16Array,
+ Uint16Array,
+ Int32Array,
+ Uint32Array,
+ Float32Array,
+ Float64Array,
+ BigInt64Array,
+ BigUint64Array,
+ ];
+ for (const constructor of typedArrayConstructors) {
+ const typedArray = new constructor(8);
+ const view = new DataView(typedArray.buffer);
+ let result = SimpleCache.set("meow", view, 1)
+ error = assert(result, undefined, `SimpleCache.set("meow", view, 1) === undefined`)
+ if (error) { return error }
+ }
+ return pass()
+ });
+ routes.set("/simple-cache/set/returns-undefined", () => {
+ error = assert(SimpleCache.set('1', 'meow', 1), undefined, "SimpleCache.set('1', 'meow', 1) === undefined")
+ if (error) { return error }
+ return pass()
+ });
+}
+
+// SimpleCache get static method
+// static get(key: string): SimpleCacheEntry | null;
+{
+ routes.set("/simple-cache/get/called-as-constructor", () => {
+ let error = assertThrows(() => {
+ new SimpleCache.get('1')
+ }, TypeError, `SimpleCache.get is not a constructor`)
+ if (error) { return error }
+ return pass()
+ });
+ // https://tc39.es/ecma262/#sec-tostring
+ routes.set("/simple-cache/get/key-parameter-calls-7.1.17-ToString", () => {
+ let sentinel;
+ const test = () => {
+ sentinel = Symbol('sentinel');
+ const key = {
+ toString() {
+ throw sentinel;
+ }
+ }
+ SimpleCache.get(key)
+ }
+ let error = assertThrows(test)
+ if (error) { return error }
+ try {
+ test()
+ } catch (thrownError) {
+ let error = assert(thrownError, sentinel, 'thrownError === sentinel')
+ if (error) { return error }
+ }
+ error = assertThrows(() => {
+ SimpleCache.get(Symbol())
+ }, TypeError, `can't convert symbol to string`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/get/key-parameter-not-supplied", () => {
+ let error = assertThrows(() => {
+ SimpleCache.get()
+ }, TypeError, `SimpleCache.get: At least 1 argument required, but only 0 passed`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/get/key-parameter-empty-string", () => {
+ let error = assertThrows(() => {
+ SimpleCache.get('')
+ }, Error, `SimpleCache.get: key can not be an empty string`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/get/key-parameter-8135-character-string", () => {
+ let error = assertDoesNotThrow(() => {
+ const key = 'a'.repeat(8135)
+ SimpleCache.get(key)
+ })
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/get/key-parameter-8136-character-string", () => {
+ let error = assertThrows(() => {
+ const key = 'a'.repeat(8136)
+ SimpleCache.get(key)
+ }, Error, `SimpleCache.get: key is too long, the maximum allowed length is 8135.`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/get/key-does-not-exist-returns-null", () => {
+ let result = SimpleCache.get(Math.random())
+ error = assert(result, null, `SimpleCache.get(Math.random()) === null`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache/get/key-exists", () => {
+ SimpleCache.set('cat', 'meow', 100);
+ let result = SimpleCache.get('cat');
+ error = assert(result instanceof SimpleCacheEntry, true, `SimpleCache.get('cat') instanceof SimpleCacheEntry`)
+ if (error) { return error }
+ return pass()
+ });
+}
+
+// SimpleCacheEntry
+{
+ routes.set("/simple-cache-entry/interface", async () => {
+ return simpleCacheEntryInterfaceTests()
+ });
+ routes.set("/simple-cache-entry/text/valid", async () => {
+ let key = `entry-text-valid-${FASTLY_SERVICE_VERSION}`;
+ SimpleCache.set(key, 'hello', 100)
+ let entry = SimpleCache.get(key)
+ let result = entry.text()
+ let error = assert(result instanceof Promise, true, `entry.text() instanceof Promise`)
+ if (error) { return error }
+ result = await result
+ error = assert(result, 'hello', `await entry.text()`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache-entry/json/valid", async () => {
+ let key = `entry-json-valid-${FASTLY_SERVICE_VERSION}`;
+ const obj = { a: 1, b: 2, c: 3 }
+ SimpleCache.set(key, JSON.stringify(obj), 100)
+ let entry = SimpleCache.get(key)
+ let result = entry.json()
+ let error = assert(result instanceof Promise, true, `entry.json() instanceof Promise`)
+ if (error) { return error }
+ result = await result
+ error = assert(result, obj, `await entry.json()`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache-entry/json/invalid", async () => {
+ let key = `entry-json-invalid-${FASTLY_SERVICE_VERSION}`;
+ SimpleCache.set(key, "132abc;['-=9", 100)
+ let entry = SimpleCache.get(key)
+ let error = await assertRejects(() => entry.json(), SyntaxError, `JSON.parse: unexpected non-whitespace character after JSON data at line 1 column 4 of the JSON data`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache-entry/arrayBuffer/valid", async () => {
+ let key = `entry-arraybuffer-valid-${FASTLY_SERVICE_VERSION}`;
+ SimpleCache.set(key, new Int8Array([0, 1, 2, 3]), 100)
+ let entry = SimpleCache.get(key)
+ let result = entry.arrayBuffer()
+ let error = assert(result instanceof Promise, true, `entry.arrayBuffer() instanceof Promise`)
+ if (error) { return error }
+ result = await result
+ error = assert(result instanceof ArrayBuffer, true, `(await entry.arrayBuffer()) instanceof ArrayBuffer`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache-entry/body", async () => {
+ let key = `entry-body-${FASTLY_SERVICE_VERSION}`;
+ SimpleCache.set(key, 'body body body', 100)
+ let entry = SimpleCache.get(key)
+ let result = entry.body;
+ let error = assert(result instanceof ReadableStream, true, `entry.body instanceof ReadableStream`)
+ if (error) { return error }
+ let text = await streamToString(result);
+ error = assert(text, 'body body body', `entry.body contents as string`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache-entry/bodyUsed", async () => {
+ let key = `entry-bodyUsed-${FASTLY_SERVICE_VERSION}`;
+ SimpleCache.set(key, 'body body body', 100)
+ let entry = SimpleCache.get(key)
+ let error = assert(entry.bodyUsed, false, `entry.bodyUsed`)
+ if (error) { return error }
+ await entry.text();
+ error = assert(entry.bodyUsed, true, `entry.bodyUsed`)
+ if (error) { return error }
+ return pass()
+ });
+ routes.set("/simple-cache-entry/readablestream", async () => {
+ const res = await fetch('https://compute-sdk-test-backend.edgecompute.app/', {
+ backend: "TheOrigin",
+ })
+ let key = `readablestream-${FASTLY_SERVICE_VERSION}`;
+ SimpleCache.set(key, res.body, 100, res.headers.get('content-length'))
+ let entry = SimpleCache.get(key)
+ error = assert(await entry.text(), 'Compute SDK Test Backend', `await entry.text()`)
+ if (error) { return error }
+ return pass()
+ });
+}
+async function simpleCacheEntryInterfaceTests() {
+ let actual = Reflect.ownKeys(SimpleCacheEntry)
+ let expected = ["prototype", "length", "name"]
+ let error = assert(actual, expected, `Reflect.ownKeys(SimpleCacheEntry)`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry, 'prototype')
+ expected = {
+ "value": SimpleCacheEntry.prototype,
+ "writable": false,
+ "enumerable": false,
+ "configurable": false
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry, 'prototype')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry, 'length')
+ expected = {
+ "value": 0,
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry, 'length')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry, 'name')
+ expected = {
+ "value": "SimpleCacheEntry",
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry, 'name')`)
+ if (error) { return error }
+
+ actual = Reflect.ownKeys(SimpleCacheEntry.prototype)
+ expected = ["constructor", "body", "bodyUsed", "arrayBuffer", "json", "text", Symbol.toStringTag]
+ error = assert(actual, expected, `Reflect.ownKeys(SimpleCacheEntry.prototype)`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'constructor')
+ expected = { "writable": true, "enumerable": false, "configurable": true, value: SimpleCacheEntry.prototype.constructor }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'constructor')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'text')
+ expected = { "writable": true, "enumerable": true, "configurable": true, value: SimpleCacheEntry.prototype.text }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'text')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'json')
+ expected = { "writable": true, "enumerable": true, "configurable": true, value: SimpleCacheEntry.prototype.json }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'json')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'arrayBuffer')
+ expected = { "writable": true, "enumerable": true, "configurable": true, value: SimpleCacheEntry.prototype.arrayBuffer }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'arrayBuffer')`)
+ if (error) { return error }
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'body')
+ error = assert(actual.enumerable, true, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'body').enumerable`)
+ error = assert(actual.configurable, true, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'body').configurable`)
+ error = assert('set' in actual, true, `'set' in Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'body')`)
+ error = assert(actual.set, undefined, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'body').set`)
+ error = assert(typeof actual.get, 'function', `typeof Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'body').get`)
+ if (error) { return error }
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'bodyUsed')
+ error = assert(actual.enumerable, true, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'bodyUsed').enumerable`)
+ error = assert(actual.configurable, true, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'bodyUsed').configurable`)
+ error = assert('set' in actual, true, `'set' in Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'bodyUsed')`)
+ error = assert(actual.set, undefined, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'bodyUsed').set`)
+ error = assert(typeof actual.get, 'function', `typeof Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype, 'bodyUsed').get`)
+ if (error) { return error }
+
+ error = assert(typeof SimpleCacheEntry.prototype.constructor, 'function', `typeof SimpleCacheEntry.prototype.constructor`)
+ if (error) { return error }
+ error = assert(typeof SimpleCacheEntry.prototype.text, 'function', `typeof SimpleCacheEntry.prototype.text`)
+ if (error) { return error }
+ error = assert(typeof SimpleCacheEntry.prototype.json, 'function', `typeof SimpleCacheEntry.prototype.json`)
+ if (error) { return error }
+ error = assert(typeof SimpleCacheEntry.prototype.arrayBuffer, 'function', `typeof SimpleCacheEntry.prototype.arrayBuffer`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.constructor, 'length')
+ expected = {
+ "value": 0,
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.constructor, 'length')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.constructor, 'name')
+ expected = {
+ "value": "SimpleCacheEntry",
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.constructor, 'name')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.text, 'length')
+ expected = {
+ "value": 0,
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.text, 'length')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.text, 'name')
+ expected = {
+ "value": "text",
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.text, 'name')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.json, 'length')
+ expected = {
+ "value": 0,
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.json, 'length')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.json, 'name')
+ expected = {
+ "value": "json",
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.json, 'name')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.arrayBuffer, 'length')
+ expected = {
+ "value": 0,
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.arrayBuffer, 'length')`)
+ if (error) { return error }
+
+ actual = Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.arrayBuffer, 'name')
+ expected = {
+ "value": "arrayBuffer",
+ "writable": false,
+ "enumerable": false,
+ "configurable": true
+ }
+ error = assert(actual, expected, `Reflect.getOwnPropertyDescriptor(SimpleCacheEntry.prototype.arrayBuffer, 'name')`)
+ if (error) { return error }
+
+ return pass()
+}
\ No newline at end of file
diff --git a/integration-tests/js-compute/fixtures/cache-simple/fastly.toml.in b/integration-tests/js-compute/fixtures/cache-simple/fastly.toml.in
new file mode 100644
index 0000000000..6ae31b6749
--- /dev/null
+++ b/integration-tests/js-compute/fixtures/cache-simple/fastly.toml.in
@@ -0,0 +1,27 @@
+# This file describes a Fastly Compute@Edge package. To learn more visit:
+# https://developer.fastly.com/reference/fastly-toml/
+
+authors = ["me@jakechampion.name"]
+description = ""
+language = "other"
+manifest_version = 2
+name = "cache-simple"
+service_id = ""
+
+[scripts]
+ build = "node ../../../../js-compute-runtime-cli.js bin/index.js"
+
+[local_server]
+
+ [local_server.backends]
+
+ [local_server.backends.TheOrigin]
+ url = "JS_COMPUTE_TEST_BACKEND/"
+
+[setup]
+
+ [setup.backends]
+
+ [setup.backends.TheOrigin]
+ address = "compute-sdk-test-backend.edgecompute.app"
+ port = 443
\ No newline at end of file
diff --git a/integration-tests/js-compute/fixtures/cache-simple/tests.json b/integration-tests/js-compute/fixtures/cache-simple/tests.json
new file mode 100644
index 0000000000..f5a7ea6226
--- /dev/null
+++ b/integration-tests/js-compute/fixtures/cache-simple/tests.json
@@ -0,0 +1,542 @@
+{
+ "GET /simple-cache/interface": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/interface"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-store/constructor/called-as-regular-function": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-store/constructor/called-as-regular-function"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/constructor/throws": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/constructor/throws"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/delete/called-as-constructor": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/delete/called-as-constructor"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/delete/key-parameter-calls-7.1.17-ToString": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/delete/key-parameter-calls-7.1.17-ToString"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/delete/key-parameter-not-supplied": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/delete/key-parameter-not-supplied"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/delete/key-parameter-empty-string": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/delete/key-parameter-empty-string"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/delete/key-parameter-1024-character-string": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/delete/key-parameter-1024-character-string"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/delete/key-parameter-1025-character-string": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/delete/key-parameter-1025-character-string"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/delete/returns-undefined": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/delete/returns-undefined"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/called-as-constructor": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/called-as-constructor"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/key-parameter-calls-7.1.17-ToString": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/key-parameter-calls-7.1.17-ToString"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/tll-parameter-7.1.4-ToNumber": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/tll-parameter-7.1.4-ToNumber"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/no-parameters-supplied": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/no-parameters-supplied"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/key-parameter-empty-string": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/key-parameter-empty-string"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/key-parameter-8135-character-string": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/key-parameter-8135-character-string"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/key-parameter-8136-character-string": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/key-parameter-8136-character-string"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/ttl-parameter-negative-number": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/ttl-parameter-negative-number"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/ttl-parameter-NaN": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/ttl-parameter-NaN"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/ttl-parameter-Infinity": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/ttl-parameter-Infinity"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-as-undefined": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-as-undefined"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-readablestream-missing-length-parameter": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-readablestream-missing-length-parameter"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-readablestream-negative-length-parameter": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-readablestream-negative-length-parameter"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-readablestream-nan-length-parameter": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-readablestream-nan-length-parameter"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-readablestream-negative-infinity-length-parameter": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-readablestream-negative-infinity-length-parameter"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-readablestream-positive-infinity-length-parameter": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-readablestream-positive-infinity-length-parameter"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/length-parameter-7.1.4-ToNumber": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/length-parameter-7.1.4-ToNumber"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-readablestream-empty": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-readablestream-empty"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-readablestream-locked": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-readablestream-locked"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-readablestream": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-readablestream"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-URLSearchParams": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-URLSearchParams"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-strings": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-strings"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-calls-7.1.17-ToString": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-calls-7.1.17-ToString"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-buffer": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-buffer"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-arraybuffer": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-arraybuffer"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-typed-arrays": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-typed-arrays"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/value-parameter-dataview": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/value-parameter-dataview"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/set/returns-undefined": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/set/returns-undefined"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/get/called-as-constructor": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/get/called-as-constructor"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/get/key-parameter-calls-7.1.17-ToString": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/get/key-parameter-calls-7.1.17-ToString"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/get/key-parameter-not-supplied": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/get/key-parameter-not-supplied"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/get/key-parameter-empty-string": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/get/key-parameter-empty-string"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/get/key-parameter-8135-character-string": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/get/key-parameter-8135-character-string"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/get/key-parameter-8136-character-string": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/get/key-parameter-8136-character-string"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/get/key-does-not-exist-returns-null": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/get/key-does-not-exist-returns-null"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache/get/key-exists": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache/get/key-exists"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache-entry/interface": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache-entry/interface"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache-entry/text/valid": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache-entry/text/valid"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache-entry/json/valid": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache-entry/json/valid"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache-entry/json/invalid": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache-entry/json/invalid"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache-entry/arrayBuffer/valid": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache-entry/arrayBuffer/valid"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache-entry/body": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache-entry/body"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache-entry/bodyUsed": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache-entry/bodyUsed"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ },
+ "GET /simple-cache-entry/readablestream": {
+ "environments": ["c@e"],
+ "downstream_request": {
+ "method": "GET",
+ "pathname": "/simple-cache-entry/readablestream"
+ },
+ "downstream_response": {
+ "status": 200
+ }
+ }
+}
diff --git a/integration-tests/js-compute/test-harness.js b/integration-tests/js-compute/test-harness.js
index 272a5f1f6f..0dfe7f7dcc 100644
--- a/integration-tests/js-compute/test-harness.js
+++ b/integration-tests/js-compute/test-harness.js
@@ -5,23 +5,32 @@ import { fail } from "./assertions.js";
addEventListener("fetch", event => {
event.respondWith(app(event))
})
+
+export let FASTLY_SERVICE_VERSION;
+
/**
* @param {FetchEvent} event
* @returns {Response}
*/
async function app(event) {
+ let res = new Response('Internal Server Error', { status: 500 });
try {
const path = (new URL(event.request.url)).pathname
console.log(`path: ${path}`)
- console.log(`FASTLY_SERVICE_VERSION: ${env('FASTLY_SERVICE_VERSION')}`)
+ FASTLY_SERVICE_VERSION = env('FASTLY_SERVICE_VERSION')
+ console.log(`FASTLY_SERVICE_VERSION: ${FASTLY_SERVICE_VERSION}`)
if (routes.has(path)) {
const routeHandler = routes.get(path)
- return await routeHandler()
+ res = await routeHandler()
+ } else {
+ res = fail(`${path} endpoint does not exist`)
}
- return fail(`${path} endpoint does not exist`)
} catch (error) {
- return fail(`The routeHandler threw an error: ${error.message}` + '\n' + error.stack)
+ res = fail(`The routeHandler threw an error: ${error.message}` + '\n' + error.stack)
+ } finally {
+ res.headers.set('FASTLY_SERVICE_VERSION', env('FASTLY_SERVICE_VERSION'));
}
+ return res;
}
export const routes = new Map()
diff --git a/runtime/js-compute-runtime/builtins/cache-simple.cpp b/runtime/js-compute-runtime/builtins/cache-simple.cpp
new file mode 100644
index 0000000000..c2ac0327c7
--- /dev/null
+++ b/runtime/js-compute-runtime/builtins/cache-simple.cpp
@@ -0,0 +1,439 @@
+#include "cache-simple.h"
+#include "builtin.h"
+#include "builtins/native-stream-source.h"
+#include "builtins/shared/url.h"
+#include "host_interface/host_api.h"
+#include "host_interface/host_call.h"
+#include "js-compute-builtins.h"
+#include "js/ArrayBuffer.h"
+#include "js/Result.h"
+#include "js/Stream.h"
+#include "openssl/evp.h"
+#include
+
+namespace builtins {
+
+template
+bool SimpleCacheEntry::bodyAll(JSContext *cx, unsigned argc, JS::Value *vp) {
+ METHOD_HEADER(0);
+ return RequestOrResponse::bodyAll(cx, args, self);
+}
+
+bool SimpleCacheEntry::body_get(JSContext *cx, unsigned argc, JS::Value *vp) {
+ METHOD_HEADER(0);
+ if (!JS::GetReservedSlot(self, static_cast(Slots::HasBody)).isBoolean()) {
+ JS::SetReservedSlot(self, static_cast(Slots::HasBody), JS::BooleanValue(false));
+ }
+ return RequestOrResponse::body_get(cx, args, self, true);
+}
+
+bool SimpleCacheEntry::bodyUsed_get(JSContext *cx, unsigned argc, JS::Value *vp) {
+ METHOD_HEADER(0);
+ if (!JS::GetReservedSlot(self, static_cast(Slots::BodyUsed)).isBoolean()) {
+ JS::SetReservedSlot(self, static_cast(Slots::BodyUsed), JS::BooleanValue(false));
+ }
+ args.rval().setBoolean(RequestOrResponse::body_used(self));
+ return true;
+}
+
+const JSFunctionSpec SimpleCacheEntry::static_methods[] = {
+ JS_FS_END,
+};
+
+const JSPropertySpec SimpleCacheEntry::static_properties[] = {
+ JS_PS_END,
+};
+
+const JSFunctionSpec SimpleCacheEntry::methods[] = {
+ JS_FN("arrayBuffer", bodyAll, 0,
+ JSPROP_ENUMERATE),
+ JS_FN("json", bodyAll, 0, JSPROP_ENUMERATE),
+ JS_FN("text", bodyAll, 0, JSPROP_ENUMERATE),
+ JS_FS_END,
+};
+
+const JSPropertySpec SimpleCacheEntry::properties[] = {
+ JS_PSG("body", body_get, JSPROP_ENUMERATE),
+ JS_PSG("bodyUsed", bodyUsed_get, JSPROP_ENUMERATE),
+ JS_STRING_SYM_PS(toStringTag, "SimpleCacheEntry", JSPROP_READONLY),
+ JS_PS_END,
+};
+
+bool SimpleCacheEntry::constructor(JSContext *cx, unsigned argc, JS::Value *vp) {
+ JS_ReportErrorUTF8(cx, "SimpleCacheEntry can't be instantiated directly");
+ return false;
+}
+
+JSObject *SimpleCacheEntry::create(JSContext *cx, fastly_body_handle_t body_handle) {
+ JS::RootedObject SimpleCacheEntry(cx, JS_NewObjectWithGivenProto(cx, &class_, proto_obj));
+ if (!SimpleCacheEntry)
+ return nullptr;
+
+ JS::SetReservedSlot(SimpleCacheEntry, static_cast(Slots::Body),
+ JS::Int32Value(body_handle));
+ JS::SetReservedSlot(SimpleCacheEntry, static_cast(Slots::BodyStream), JS::NullValue());
+ JS::SetReservedSlot(SimpleCacheEntry, static_cast(Slots::HasBody),
+ JS::BooleanValue(true));
+ JS::SetReservedSlot(SimpleCacheEntry, static_cast(Slots::BodyUsed), JS::FalseValue());
+
+ return SimpleCacheEntry;
+}
+
+bool SimpleCacheEntry::init_class(JSContext *cx, JS::HandleObject global) {
+ return init_class_impl(cx, global);
+}
+
+namespace {
+// We currently support five types of body inputs:
+// - byte sequence
+// - buffer source
+// - USV strings
+// - URLSearchParams
+// - ReadableStream (Currently only supports Host-backed ReadableStreams)
+// After the other other options are checked explicitly, all other inputs are
+// encoded to a UTF8 string to be treated as a USV string.
+// TODO: Add support for Blob and FormData when we have implemented those classes.
+JS::Result> convertBodyInit(JSContext *cx,
+ JS::HandleValue bodyInit) {
+ JS::RootedObject bodyObj(cx, bodyInit.isObject() ? &bodyInit.toObject() : nullptr);
+ mozilla::Maybe maybeNoGC;
+ JS::UniqueChars buf;
+ size_t length;
+
+ if (bodyObj && JS_IsArrayBufferViewObject(bodyObj)) {
+ // `maybeNoGC` needs to be populated for the lifetime of `buf` because
+ // short typed arrays have inline data which can move on GC, so assert
+ // that no GC happens. (Which it doesn't, because we're not allocating
+ // before `buf` goes out of scope.)
+ maybeNoGC.emplace(cx);
+ JS::AutoCheckCannotGC &noGC = maybeNoGC.ref();
+ bool is_shared;
+ length = JS_GetArrayBufferViewByteLength(bodyObj);
+ buf = JS::UniqueChars(
+ reinterpret_cast(JS_GetArrayBufferViewData(bodyObj, &is_shared, noGC)));
+ MOZ_ASSERT(!is_shared);
+ } else if (bodyObj && JS::IsArrayBufferObject(bodyObj)) {
+ bool is_shared;
+ uint8_t *bytes;
+ JS::GetArrayBufferLengthAndData(bodyObj, &length, &is_shared, &bytes);
+ MOZ_ASSERT(!is_shared);
+ buf.reset(reinterpret_cast(bytes));
+ } else if (bodyObj && builtins::URLSearchParams::is_instance(bodyObj)) {
+ jsurl::SpecSlice slice = builtins::URLSearchParams::serialize(cx, bodyObj);
+ buf = JS::UniqueChars(reinterpret_cast(const_cast(slice.data)));
+ length = slice.len;
+ } else {
+ // Convert into a String following https://tc39.es/ecma262/#sec-tostring
+ buf = encode(cx, bodyInit, &length);
+ if (!buf) {
+ return JS::Result>(JS::Error());
+ }
+ }
+ return JS::Result>(std::make_tuple(std::move(buf), length));
+}
+
+// Purging/Deleting a cache item within the Compute SDKs via a hostcall is only
+// possible via surrogate-keys. We add a surrogate key to all the cache entries,
+// which is the sha-256 digest of the cache entries cache-key, converted to
+// uppercase hexadecimal.
+// Note: We should keep this consistent across the Compute SDKs, this would allow
+// a Compute Service to move from one SDK to another, and have consistent purging
+// behavior between the Compute Service Versions which were using a different SDK.
+JS::Result createSurrogateKeyFromCacheKey(JSContext *cx,
+ fastly_world_string_t cache_key) {
+ const EVP_MD *algorithm = EVP_sha256();
+ unsigned int size = EVP_MD_size(algorithm);
+ std::vector md(size);
+
+ if (!EVP_Digest(cache_key.ptr, cache_key.len, md.data(), &size, algorithm, nullptr)) {
+ return JS::Result(JS::Error());
+ }
+ JS::UniqueChars data{OPENSSL_buf2hexstr(md.data(), size)};
+ std::string surrogate_key{data.get(), std::remove(data.get(), data.get() + size, ':')};
+
+ return JS::Result(surrogate_key);
+}
+
+} // namespace
+
+// static set(key: string, value: BodyInit, ttl: number): undefined;
+// static set(key: string, value: ReadableStream, ttl: number, length: number): undefined;
+bool SimpleCache::set(JSContext *cx, unsigned argc, JS::Value *vp) {
+ REQUEST_HANDLER_ONLY("The SimpleCache builtin");
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.requireAtLeast(cx, "SimpleCache.set", 3)) {
+ return false;
+ }
+
+ fastly_world_string_t key;
+ // Convert key parameter into a string and check the value adheres to our validation rules.
+ JS::UniqueChars key_chars = encode(cx, args.get(0), &key.len);
+ if (!key_chars) {
+ return false;
+ }
+ key.ptr = key_chars.get();
+
+ if (key.len == 0) {
+ JS_ReportErrorASCII(cx, "SimpleCache.set: key can not be an empty string");
+ return false;
+ }
+ if (key.len > 8135) {
+ JS_ReportErrorASCII(cx,
+ "SimpleCache.set: key is too long, the maximum allowed length is 8135.");
+ return false;
+ }
+
+ fastly_cache_write_options_t options;
+ // Convert ttl (time-to-live) parameter into a number and check the value adheres to our
+ // validation rules.
+ JS::HandleValue ttl_val = args.get(2);
+ std::memset(&options, 0, sizeof(options));
+ double ttl;
+ if (!JS::ToNumber(cx, ttl_val, &ttl)) {
+ return false;
+ }
+ if (ttl < 0 || std::isnan(ttl) || std::isinf(ttl)) {
+ JS_ReportErrorASCII(
+ cx, "SimpleCache.set: TTL parameter is an invalid value, only positive numbers can "
+ "be used for TTL values.");
+ return false;
+ }
+ options.max_age_ns = JS::ToUint64(ttl) *
+ 1'000'000'000; // turn second representation into nanosecond representation
+
+ JS::HandleValue body_val = args.get(1);
+ HttpBody source_body;
+ JS::UniqueChars buf;
+ JS::RootedObject body_obj(cx, body_val.isObject() ? &body_val.toObject() : nullptr);
+ // If the body parameter is a Host-backed ReadableStream we optimise our implementation
+ // by using the ReadableStream's handle directly.
+ if (body_obj && JS::IsReadableStream(body_obj)) {
+ if (RequestOrResponse::body_unusable(cx, body_obj)) {
+ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
+ JSMSG_READABLE_STREAM_LOCKED_OR_DISTRUBED);
+ return false;
+ }
+
+ // If the stream is backed by a C@E body handle, we can use that handle directly.
+ if (builtins::NativeStreamSource::stream_is_body(cx, body_obj)) {
+ JS::RootedObject stream_source(cx,
+ builtins::NativeStreamSource::get_stream_source(cx, body_obj));
+ JS::RootedObject source_owner(cx, builtins::NativeStreamSource::owner(stream_source));
+ source_body = RequestOrResponse::body_handle(source_owner);
+ } else {
+ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
+ JSMSG_SIMPLE_CACHE_SET_CONTENT_STREAM);
+ return false;
+ }
+
+ // The cache APIs require the length to be known upfront, we don't know the length of a
+ // stream upfront, which means the caller will need to supply the information explicitly for us.
+ if (!args.hasDefined(3)) {
+ JS_ReportErrorASCII(cx, "SimpleCache.set: length parameter is required when the value "
+ "parameter is a ReadableStream. The length of the stream needs to be "
+ "known before inserting into the cache.");
+ return false;
+ }
+
+ JS::HandleValue length_val = args.get(3);
+ double number;
+ if (!JS::ToNumber(cx, length_val, &number)) {
+ return false;
+ }
+ if (number < 0 || std::isnan(number) || std::isinf(number)) {
+ JS_ReportErrorASCII(
+ cx, "SimpleCache.set: length parameter is an invalid value, only positive numbers can "
+ "be used for length values.");
+ return false;
+ }
+ options.length = JS::ToInteger(number);
+ } else {
+ auto result = convertBodyInit(cx, body_val);
+ if (result.isErr()) {
+ return false;
+ }
+ std::tie(buf, options.length) = result.unwrap();
+ }
+
+ // We create a surrogate-key from the cache-key, as this allows the cached contents to be purgable
+ // from within the JavaScript application
+ // This is because the cache API currently only supports purging via surrogate-key
+ auto key_result = createSurrogateKeyFromCacheKey(cx, key);
+ if (key_result.isErr()) {
+ return false;
+ }
+ auto surrogate_key = key_result.unwrap();
+ options.surrogate_keys.ptr = const_cast(surrogate_key.c_str());
+ options.surrogate_keys.len = surrogate_key.length();
+
+ fastly_error_t err;
+ fastly_body_handle_t body_handle = INVALID_HANDLE;
+ if (!fastly_cache_insert(&key, &options, &body_handle, &err)) {
+ HANDLE_ERROR(cx, err);
+ return false;
+ }
+
+ auto body = HttpBody(body_handle);
+ if (!body.valid()) {
+ return false;
+ }
+ // source_body will only be valid when the body parameter is a Host-backed ReadableStream
+ if (source_body.valid()) {
+ auto res = body.append(source_body);
+ if (auto *err = res.to_err()) {
+ HANDLE_ERROR(cx, *err);
+ return false;
+ }
+ args.rval().setUndefined();
+ return true;
+ } else {
+ auto write_res = body.write_all(reinterpret_cast(buf.get()), options.length);
+ if (auto *err = write_res.to_err()) {
+ HANDLE_ERROR(cx, *err);
+ return false;
+ }
+ }
+ auto close_res = body.close();
+ if (auto *err = close_res.to_err()) {
+ HANDLE_ERROR(cx, *err);
+ return false;
+ }
+
+ args.rval().setUndefined();
+ return true;
+}
+
+// static get(key: string): SimpleCacheEntry | null;
+bool SimpleCache::get(JSContext *cx, unsigned argc, JS::Value *vp) {
+ REQUEST_HANDLER_ONLY("The SimpleCache builtin");
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.requireAtLeast(cx, "SimpleCache.get", 1)) {
+ return false;
+ }
+
+ fastly_world_string_t key;
+ // Convert key parameter into a string and check the value adheres to our validation rules.
+ JS::UniqueChars key_chars = encode(cx, args[0], &key.len);
+ if (!key_chars) {
+ return false;
+ }
+ key.ptr = key_chars.get();
+
+ if (key.len == 0) {
+ JS_ReportErrorASCII(cx, "SimpleCache.get: key can not be an empty string");
+ return false;
+ }
+ if (key.len > 8135) {
+ JS_ReportErrorASCII(cx,
+ "SimpleCache.get: key is too long, the maximum allowed length is 8135.");
+ return false;
+ }
+
+ fastly_error_t err;
+ fastly_cache_lookup_options_t options;
+ std::memset(&options, 0, sizeof(options));
+
+ fastly_cache_handle_t handle = INVALID_HANDLE;
+ if (!fastly_cache_lookup(&key, &options, &handle, &err)) {
+ HANDLE_ERROR(cx, err);
+ return false;
+ }
+
+ fastly_body_handle_t body = INVALID_HANDLE;
+ fastly_cache_get_body_options_t opts;
+ if (!fastly_cache_get_body(handle, &opts, &body, &err)) {
+ HANDLE_ERROR(cx, err);
+ return false;
+ }
+
+ if (body == INVALID_HANDLE) {
+ args.rval().setNull();
+ } else {
+ JS::RootedObject entry(cx, SimpleCacheEntry::create(cx, body));
+ if (!entry) {
+ return false;
+ }
+ args.rval().setObject(*entry);
+ }
+
+ return true;
+}
+
+// static delete(key: string): undefined;
+bool SimpleCache::delete_(JSContext *cx, unsigned argc, JS::Value *vp) {
+ REQUEST_HANDLER_ONLY("The SimpleCache builtin");
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.requireAtLeast(cx, "SimpleCache.delete", 1)) {
+ return false;
+ }
+
+ fastly_world_string_t key;
+ // Convert key parameter into a string and check the value adheres to our validation rules.
+ JS::UniqueChars key_chars = encode(cx, args.get(0), &key.len);
+ if (!key_chars) {
+ return false;
+ }
+ key.ptr = key_chars.get();
+
+ if (key.len == 0) {
+ JS_ReportErrorASCII(cx, "SimpleCache.delete: key can not be an empty string");
+ return false;
+ }
+ if (key.len > 1024) {
+ JS_ReportErrorASCII(cx,
+ "SimpleCache.delete: key is too long, the maximum allowed length is 1024.");
+ return false;
+ }
+
+ // We create a surrogate-key from the cache-key, as this allows the cached contents to be purgable
+ // from within the JavaScript application
+ // This is because the cache API currently only supports purging via surrogate-key
+ auto surrogate_key_result = createSurrogateKeyFromCacheKey(cx, key);
+ if (surrogate_key_result.isErr()) {
+ return false;
+ }
+ auto surrogate_key = surrogate_key_result.unwrap();
+
+ fastly_world_string_t skey;
+ skey.ptr = const_cast(surrogate_key.c_str());
+ skey.len = surrogate_key.length();
+
+ fastly_error_t err;
+ fastly_world_option_string_t ret;
+ fastly_purge_options_mask_t purge_options = 0;
+ if (!fastly_purge_surrogate_key(&skey, purge_options, &ret, &err)) {
+ HANDLE_ERROR(cx, err);
+ return false;
+ }
+ MOZ_ASSERT(!ret.is_some);
+
+ args.rval().setUndefined();
+ return true;
+}
+
+const JSFunctionSpec SimpleCache::static_methods[] = {
+ JS_FN("delete", delete_, 1, JSPROP_ENUMERATE),
+ JS_FN("get", get, 1, JSPROP_ENUMERATE),
+ JS_FN("set", set, 3, JSPROP_ENUMERATE),
+ JS_FS_END,
+};
+
+const JSPropertySpec SimpleCache::static_properties[] = {
+ JS_PS_END,
+};
+
+const JSFunctionSpec SimpleCache::methods[] = {JS_FS_END};
+
+const JSPropertySpec SimpleCache::properties[] = {
+ JS_STRING_SYM_PS(toStringTag, "SimpleCache", JSPROP_READONLY), JS_PS_END};
+
+bool SimpleCache::constructor(JSContext *cx, unsigned argc, JS::Value *vp) {
+ JS_ReportErrorNumberASCII(cx, GetErrorMessageBuiltin, nullptr, JSMSG_ILLEGAL_CTOR);
+ return false;
+}
+
+bool SimpleCache::init_class(JSContext *cx, JS::HandleObject global) {
+ return BuiltinImpl::init_class_impl(cx, global);
+}
+
+} // namespace builtins
diff --git a/runtime/js-compute-runtime/builtins/cache-simple.h b/runtime/js-compute-runtime/builtins/cache-simple.h
new file mode 100644
index 0000000000..44ecb84522
--- /dev/null
+++ b/runtime/js-compute-runtime/builtins/cache-simple.h
@@ -0,0 +1,55 @@
+#ifndef JS_COMPUTE_RUNTIME_CACHE_SIMPLE_H
+#define JS_COMPUTE_RUNTIME_CACHE_SIMPLE_H
+
+#include "builtin.h"
+#include "js-compute-builtins.h"
+#include "request-response.h"
+
+namespace builtins {
+
+class SimpleCacheEntry final : public BuiltinImpl {
+ template
+ static bool bodyAll(JSContext *cx, unsigned argc, JS::Value *vp);
+ static bool body_get(JSContext *cx, unsigned argc, JS::Value *vp);
+ static bool bodyUsed_get(JSContext *cx, unsigned argc, JS::Value *vp);
+
+public:
+ static constexpr const char *class_name = "SimpleCacheEntry";
+
+ using Slots = RequestOrResponse::Slots;
+ static const JSFunctionSpec static_methods[];
+ static const JSPropertySpec static_properties[];
+ static const JSFunctionSpec methods[];
+ static const JSPropertySpec properties[];
+
+ static const unsigned ctor_length = 0;
+
+ static bool init_class(JSContext *cx, JS::HandleObject global);
+ static bool constructor(JSContext *cx, unsigned argc, JS::Value *vp);
+ static JSObject *create(JSContext *cx, fastly_body_handle_t body_handle);
+};
+
+class SimpleCache : public BuiltinImpl {
+private:
+public:
+ static constexpr const char *class_name = "SimpleCache";
+ static const int ctor_length = 0;
+ enum Slots { Count };
+
+ static const JSFunctionSpec static_methods[];
+ static const JSPropertySpec static_properties[];
+ static const JSFunctionSpec methods[];
+ static const JSPropertySpec properties[];
+
+ static bool delete_(JSContext *cx, unsigned argc, JS::Value *vp);
+ static bool get(JSContext *cx, unsigned argc, JS::Value *vp);
+ static bool set(JSContext *cx, unsigned argc, JS::Value *vp);
+
+ static bool constructor(JSContext *cx, unsigned argc, JS::Value *vp);
+
+ static bool init_class(JSContext *cx, JS::HandleObject global);
+};
+
+} // namespace builtins
+
+#endif
diff --git a/runtime/js-compute-runtime/error-numbers.msg b/runtime/js-compute-runtime/error-numbers.msg
index 06113d5966..13633ab2d4 100644
--- a/runtime/js-compute-runtime/error-numbers.msg
+++ b/runtime/js-compute-runtime/error-numbers.msg
@@ -112,4 +112,5 @@ MSG_DEF(JSMSG_TEXT_DECODER_DECODING_FAILED, 0, JSEXN_TYPEERR,
MSG_DEF(JSMSG_TEXT_DECODER_OPTIONS_NOT_DICTIONARY, 0, JSEXN_TYPEERR, "TextDecoder constructor: options argument can't be converted to a dictionary.")
MSG_DEF(JSMSG_TEXT_DECODER_DECODE_OPTIONS_NOT_DICTIONARY, 0, JSEXN_TYPEERR, "TextDecoder.decode: options argument can't be converted to a dictionary.")
MSG_DEF(JSMSG_TEXT_ENCODER_ENCODEINTO_INVALID_ARRAY, 0, JSEXN_TYPEERR, "TextEncoder.encodeInto: Argument 2 does not implement interface Uint8Array.")
+MSG_DEF(JSMSG_SIMPLE_CACHE_SET_CONTENT_STREAM, 0, JSEXN_TYPEERR, "Content-provided streams are not yet supported for streaming into SimpleCache")
//clang-format on
\ No newline at end of file
diff --git a/runtime/js-compute-runtime/fastly-world/fastly_world.c b/runtime/js-compute-runtime/fastly-world/fastly_world.c
index aab9c6a7e2..2c803dcfa1 100644
--- a/runtime/js-compute-runtime/fastly-world/fastly_world.c
+++ b/runtime/js-compute-runtime/fastly-world/fastly_world.c
@@ -212,10 +212,10 @@ typedef struct {
typedef struct {
bool is_err;
union {
- fastly_purge_result_t ok;
+ fastly_cache_handle_t ok;
fastly_error_t err;
} val;
-} fastly_world_result_purge_result_error_t;
+} fastly_world_result_cache_handle_error_t;
typedef struct {
bool is_err;
@@ -223,229 +223,238 @@ typedef struct {
} val;
} fastly_world_result_void_void_t;
-__attribute__((__import_module__("fastly"), __import_name__("abi-init")))
+__attribute__((import_module("fastly"), import_name("abi-init")))
void __wasm_import_fastly_abi_init(int64_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("uap-parse")))
+__attribute__((import_module("fastly"), import_name("uap-parse")))
void __wasm_import_fastly_uap_parse(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-body-new")))
+__attribute__((import_module("fastly"), import_name("http-body-new")))
void __wasm_import_fastly_http_body_new(int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-body-append")))
+__attribute__((import_module("fastly"), import_name("http-body-append")))
void __wasm_import_fastly_http_body_append(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-body-read")))
+__attribute__((import_module("fastly"), import_name("http-body-read")))
void __wasm_import_fastly_http_body_read(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-body-write")))
+__attribute__((import_module("fastly"), import_name("http-body-write")))
void __wasm_import_fastly_http_body_write(int32_t, int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-body-close")))
+__attribute__((import_module("fastly"), import_name("http-body-close")))
void __wasm_import_fastly_http_body_close(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("log-endpoint-get")))
+__attribute__((import_module("fastly"), import_name("log-endpoint-get")))
void __wasm_import_fastly_log_endpoint_get(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("log-write")))
+__attribute__((import_module("fastly"), import_name("log-write")))
void __wasm_import_fastly_log_write(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-cache-override-set")))
+__attribute__((import_module("fastly"), import_name("http-req-cache-override-set")))
void __wasm_import_fastly_http_req_cache_override_set(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-downstream-client-ip-addr")))
+__attribute__((import_module("fastly"), import_name("http-req-downstream-client-ip-addr")))
void __wasm_import_fastly_http_req_downstream_client_ip_addr(int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-downstream-client-h2-fingerprint")))
+__attribute__((import_module("fastly"), import_name("http-req-downstream-client-h2-fingerprint")))
void __wasm_import_fastly_http_req_downstream_client_h2_fingerprint(int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-downstream-tls-cipher-openssl-name")))
+__attribute__((import_module("fastly"), import_name("http-req-downstream-tls-cipher-openssl-name")))
void __wasm_import_fastly_http_req_downstream_tls_cipher_openssl_name(int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-downstream-tls-protocol")))
+__attribute__((import_module("fastly"), import_name("http-req-downstream-tls-protocol")))
void __wasm_import_fastly_http_req_downstream_tls_protocol(int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-downstream-tls-client-hello")))
+__attribute__((import_module("fastly"), import_name("http-req-downstream-tls-client-hello")))
void __wasm_import_fastly_http_req_downstream_tls_client_hello(int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-downstream-tls-client-certificate")))
+__attribute__((import_module("fastly"), import_name("http-req-downstream-tls-client-certificate")))
void __wasm_import_fastly_http_req_downstream_tls_client_certificate(int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-downstream-tls-client-cert-verify-result")))
+__attribute__((import_module("fastly"), import_name("http-req-downstream-tls-client-cert-verify-result")))
void __wasm_import_fastly_http_req_downstream_tls_client_cert_verify_result(int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-downstream-tls-ja3-md5")))
+__attribute__((import_module("fastly"), import_name("http-req-downstream-tls-ja3-md5")))
void __wasm_import_fastly_http_req_downstream_tls_ja3_md5(int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-new")))
+__attribute__((import_module("fastly"), import_name("http-req-new")))
void __wasm_import_fastly_http_req_new(int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-header-names-get")))
+__attribute__((import_module("fastly"), import_name("http-req-header-names-get")))
void __wasm_import_fastly_http_req_header_names_get(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-header-value-get")))
+__attribute__((import_module("fastly"), import_name("http-req-header-value-get")))
void __wasm_import_fastly_http_req_header_value_get(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-header-values-get")))
+__attribute__((import_module("fastly"), import_name("http-req-header-values-get")))
void __wasm_import_fastly_http_req_header_values_get(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-header-values-set")))
+__attribute__((import_module("fastly"), import_name("http-req-header-values-set")))
void __wasm_import_fastly_http_req_header_values_set(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-header-insert")))
+__attribute__((import_module("fastly"), import_name("http-req-header-insert")))
void __wasm_import_fastly_http_req_header_insert(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-header-append")))
+__attribute__((import_module("fastly"), import_name("http-req-header-append")))
void __wasm_import_fastly_http_req_header_append(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-header-remove")))
+__attribute__((import_module("fastly"), import_name("http-req-header-remove")))
void __wasm_import_fastly_http_req_header_remove(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-method-get")))
+__attribute__((import_module("fastly"), import_name("http-req-method-get")))
void __wasm_import_fastly_http_req_method_get(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-method-set")))
+__attribute__((import_module("fastly"), import_name("http-req-method-set")))
void __wasm_import_fastly_http_req_method_set(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-uri-get")))
+__attribute__((import_module("fastly"), import_name("http-req-uri-get")))
void __wasm_import_fastly_http_req_uri_get(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-uri-set")))
+__attribute__((import_module("fastly"), import_name("http-req-uri-set")))
void __wasm_import_fastly_http_req_uri_set(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-version-get")))
+__attribute__((import_module("fastly"), import_name("http-req-version-get")))
void __wasm_import_fastly_http_req_version_get(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-version-set")))
+__attribute__((import_module("fastly"), import_name("http-req-version-set")))
void __wasm_import_fastly_http_req_version_set(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-send")))
+__attribute__((import_module("fastly"), import_name("http-req-send")))
void __wasm_import_fastly_http_req_send(int32_t, int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-send-async")))
+__attribute__((import_module("fastly"), import_name("http-req-send-async")))
void __wasm_import_fastly_http_req_send_async(int32_t, int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-send-async-streaming")))
+__attribute__((import_module("fastly"), import_name("http-req-send-async-streaming")))
void __wasm_import_fastly_http_req_send_async_streaming(int32_t, int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-pending-req-poll")))
+__attribute__((import_module("fastly"), import_name("http-req-pending-req-poll")))
void __wasm_import_fastly_http_req_pending_req_poll(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-pending-req-wait")))
+__attribute__((import_module("fastly"), import_name("http-req-pending-req-wait")))
void __wasm_import_fastly_http_req_pending_req_wait(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-pending-req-select")))
+__attribute__((import_module("fastly"), import_name("http-req-pending-req-select")))
void __wasm_import_fastly_http_req_pending_req_select(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-key-is-valid")))
+__attribute__((import_module("fastly"), import_name("http-req-key-is-valid")))
void __wasm_import_fastly_http_req_key_is_valid(int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-close")))
+__attribute__((import_module("fastly"), import_name("http-req-close")))
void __wasm_import_fastly_http_req_close(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-auto-decompress-response-set")))
+__attribute__((import_module("fastly"), import_name("http-req-auto-decompress-response-set")))
void __wasm_import_fastly_http_req_auto_decompress_response_set(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-upgrade-websocket")))
+__attribute__((import_module("fastly"), import_name("http-req-upgrade-websocket")))
void __wasm_import_fastly_http_req_upgrade_websocket(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-redirect-to-websocket-proxy")))
+__attribute__((import_module("fastly"), import_name("http-req-redirect-to-websocket-proxy")))
void __wasm_import_fastly_http_req_redirect_to_websocket_proxy(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-redirect-to-grip-proxy")))
+__attribute__((import_module("fastly"), import_name("http-req-redirect-to-grip-proxy")))
void __wasm_import_fastly_http_req_redirect_to_grip_proxy(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-framing-headers-mode-set")))
+__attribute__((import_module("fastly"), import_name("http-req-framing-headers-mode-set")))
void __wasm_import_fastly_http_req_framing_headers_mode_set(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-req-register-dynamic-backend")))
+__attribute__((import_module("fastly"), import_name("http-req-register-dynamic-backend")))
void __wasm_import_fastly_http_req_register_dynamic_backend(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-new")))
+__attribute__((import_module("fastly"), import_name("http-resp-new")))
void __wasm_import_fastly_http_resp_new(int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-header-names-get")))
+__attribute__((import_module("fastly"), import_name("http-resp-header-names-get")))
void __wasm_import_fastly_http_resp_header_names_get(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-header-value-get")))
+__attribute__((import_module("fastly"), import_name("http-resp-header-value-get")))
void __wasm_import_fastly_http_resp_header_value_get(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-header-values-get")))
+__attribute__((import_module("fastly"), import_name("http-resp-header-values-get")))
void __wasm_import_fastly_http_resp_header_values_get(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-header-values-set")))
+__attribute__((import_module("fastly"), import_name("http-resp-header-values-set")))
void __wasm_import_fastly_http_resp_header_values_set(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-header-insert")))
+__attribute__((import_module("fastly"), import_name("http-resp-header-insert")))
void __wasm_import_fastly_http_resp_header_insert(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-header-append")))
+__attribute__((import_module("fastly"), import_name("http-resp-header-append")))
void __wasm_import_fastly_http_resp_header_append(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-header-remove")))
+__attribute__((import_module("fastly"), import_name("http-resp-header-remove")))
void __wasm_import_fastly_http_resp_header_remove(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-version-get")))
+__attribute__((import_module("fastly"), import_name("http-resp-version-get")))
void __wasm_import_fastly_http_resp_version_get(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-version-set")))
+__attribute__((import_module("fastly"), import_name("http-resp-version-set")))
void __wasm_import_fastly_http_resp_version_set(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-send-downstream")))
+__attribute__((import_module("fastly"), import_name("http-resp-send-downstream")))
void __wasm_import_fastly_http_resp_send_downstream(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-status-get")))
+__attribute__((import_module("fastly"), import_name("http-resp-status-get")))
void __wasm_import_fastly_http_resp_status_get(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-status-set")))
+__attribute__((import_module("fastly"), import_name("http-resp-status-set")))
void __wasm_import_fastly_http_resp_status_set(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-close")))
+__attribute__((import_module("fastly"), import_name("http-resp-close")))
void __wasm_import_fastly_http_resp_close(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("http-resp-framing-headers-mode-set")))
+__attribute__((import_module("fastly"), import_name("http-resp-framing-headers-mode-set")))
void __wasm_import_fastly_http_resp_framing_headers_mode_set(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("dictionary-open")))
+__attribute__((import_module("fastly"), import_name("dictionary-open")))
void __wasm_import_fastly_dictionary_open(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("dictionary-get")))
+__attribute__((import_module("fastly"), import_name("dictionary-get")))
void __wasm_import_fastly_dictionary_get(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("geo-lookup")))
+__attribute__((import_module("fastly"), import_name("geo-lookup")))
void __wasm_import_fastly_geo_lookup(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("object-store-open")))
+__attribute__((import_module("fastly"), import_name("object-store-open")))
void __wasm_import_fastly_object_store_open(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("object-store-lookup")))
+__attribute__((import_module("fastly"), import_name("object-store-lookup")))
void __wasm_import_fastly_object_store_lookup(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("object-store-lookup-as-fd")))
+__attribute__((import_module("fastly"), import_name("object-store-lookup-as-fd")))
void __wasm_import_fastly_object_store_lookup_as_fd(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("object-store-insert")))
+__attribute__((import_module("fastly"), import_name("object-store-insert")))
void __wasm_import_fastly_object_store_insert(int32_t, int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("secret-store-open")))
+__attribute__((import_module("fastly"), import_name("secret-store-open")))
void __wasm_import_fastly_secret_store_open(int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("secret-store-get")))
+__attribute__((import_module("fastly"), import_name("secret-store-get")))
void __wasm_import_fastly_secret_store_get(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("secret-store-plaintext")))
+__attribute__((import_module("fastly"), import_name("secret-store-plaintext")))
void __wasm_import_fastly_secret_store_plaintext(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("async-io-select")))
+__attribute__((import_module("fastly"), import_name("async-io-select")))
void __wasm_import_fastly_async_io_select(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("async-io-is-ready")))
+__attribute__((import_module("fastly"), import_name("async-io-is-ready")))
void __wasm_import_fastly_async_io_is_ready(int32_t, int32_t);
-__attribute__((__import_module__("fastly"), __import_name__("purge-surrogate-key")))
+__attribute__((import_module("fastly"), import_name("purge-surrogate-key")))
void __wasm_import_fastly_purge_surrogate_key(int32_t, int32_t, int32_t, int32_t);
-__attribute__((__weak__, __export_name__("cabi_realloc")))
+__attribute__((import_module("fastly"), import_name("cache-lookup")))
+void __wasm_import_fastly_cache_lookup(int32_t, int32_t, int32_t, int32_t, int32_t);
+
+__attribute__((import_module("fastly"), import_name("cache-insert")))
+void __wasm_import_fastly_cache_insert(int32_t, int32_t, int64_t, int32_t, int32_t, int32_t, int64_t, int64_t, int32_t, int32_t, int64_t, int32_t, int32_t, int32_t, int32_t);
+
+__attribute__((import_module("fastly"), import_name("cache-get-body")))
+void __wasm_import_fastly_cache_get_body(int32_t, int64_t, int64_t, int32_t);
+
+__attribute__((weak, export_name("cabi_realloc")))
void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) {
if (new_size == 0) return (void*) align;
void *ret = realloc(ptr, new_size);
@@ -456,7 +465,7 @@ void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) {
// Component Adapters
bool fastly_abi_init(uint64_t abi_version, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_abi_init((int64_t) (abi_version), ptr);
@@ -481,7 +490,7 @@ bool fastly_abi_init(uint64_t abi_version, fastly_error_t *err) {
}
bool fastly_uap_parse(fastly_world_string_t *user_agent, fastly_user_agent_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[36];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_uap_parse((int32_t) (*user_agent).ptr, (int32_t) (*user_agent).len, ptr);
@@ -513,7 +522,7 @@ bool fastly_uap_parse(fastly_world_string_t *user_agent, fastly_user_agent_t *re
}
bool fastly_http_body_new(fastly_body_handle_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[8];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_body_new(ptr);
@@ -540,7 +549,7 @@ bool fastly_http_body_new(fastly_body_handle_t *ret, fastly_error_t *err) {
}
bool fastly_http_body_append(fastly_body_handle_t dest, fastly_body_handle_t src, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_body_append((int32_t) (dest), (int32_t) (src), ptr);
@@ -565,7 +574,7 @@ bool fastly_http_body_append(fastly_body_handle_t dest, fastly_body_handle_t src
}
bool fastly_http_body_read(fastly_body_handle_t h, uint32_t chunk_size, fastly_world_list_u8_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_body_read((int32_t) (h), (int32_t) (chunk_size), ptr);
@@ -592,7 +601,7 @@ bool fastly_http_body_read(fastly_body_handle_t h, uint32_t chunk_size, fastly_w
}
bool fastly_http_body_write(fastly_body_handle_t h, fastly_world_list_u8_t *buf, fastly_body_write_end_t end, uint32_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[8];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_body_write((int32_t) (h), (int32_t) (*buf).ptr, (int32_t) (*buf).len, (int32_t) end, ptr);
@@ -619,7 +628,7 @@ bool fastly_http_body_write(fastly_body_handle_t h, fastly_world_list_u8_t *buf,
}
bool fastly_http_body_close(fastly_body_handle_t h, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_body_close((int32_t) (h), ptr);
@@ -644,7 +653,7 @@ bool fastly_http_body_close(fastly_body_handle_t h, fastly_error_t *err) {
}
bool fastly_log_endpoint_get(fastly_world_string_t *name, fastly_log_endpoint_handle_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[8];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_log_endpoint_get((int32_t) (*name).ptr, (int32_t) (*name).len, ptr);
@@ -671,7 +680,7 @@ bool fastly_log_endpoint_get(fastly_world_string_t *name, fastly_log_endpoint_ha
}
bool fastly_log_write(fastly_log_endpoint_handle_t h, fastly_world_string_t *msg, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_log_write((int32_t) (h), (int32_t) (*msg).ptr, (int32_t) (*msg).len, ptr);
@@ -696,7 +705,7 @@ bool fastly_log_write(fastly_log_endpoint_handle_t h, fastly_world_string_t *msg
}
bool fastly_http_req_cache_override_set(fastly_request_handle_t h, fastly_http_cache_override_tag_t tag, uint32_t *maybe_ttl, uint32_t *maybe_stale_while_revalidate, fastly_world_string_t *maybe_sk, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
fastly_world_option_u32_t ttl;
ttl.is_some = maybe_ttl != NULL;if (maybe_ttl) {
@@ -766,7 +775,7 @@ bool fastly_http_req_cache_override_set(fastly_request_handle_t h, fastly_http_c
}
bool fastly_http_req_downstream_client_ip_addr(fastly_world_list_u8_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_downstream_client_ip_addr(ptr);
@@ -793,7 +802,7 @@ bool fastly_http_req_downstream_client_ip_addr(fastly_world_list_u8_t *ret, fast
}
bool fastly_http_req_downstream_client_h2_fingerprint(fastly_world_list_u8_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_downstream_client_h2_fingerprint(ptr);
@@ -820,7 +829,7 @@ bool fastly_http_req_downstream_client_h2_fingerprint(fastly_world_list_u8_t *re
}
bool fastly_http_req_downstream_tls_cipher_openssl_name(fastly_world_string_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_downstream_tls_cipher_openssl_name(ptr);
@@ -847,7 +856,7 @@ bool fastly_http_req_downstream_tls_cipher_openssl_name(fastly_world_string_t *r
}
bool fastly_http_req_downstream_tls_protocol(fastly_world_string_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_downstream_tls_protocol(ptr);
@@ -874,7 +883,7 @@ bool fastly_http_req_downstream_tls_protocol(fastly_world_string_t *ret, fastly_
}
bool fastly_http_req_downstream_tls_client_hello(fastly_world_list_u8_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_downstream_tls_client_hello(ptr);
@@ -901,7 +910,7 @@ bool fastly_http_req_downstream_tls_client_hello(fastly_world_list_u8_t *ret, fa
}
bool fastly_http_req_downstream_tls_client_certificate(fastly_world_list_u8_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_downstream_tls_client_certificate(ptr);
@@ -928,7 +937,7 @@ bool fastly_http_req_downstream_tls_client_certificate(fastly_world_list_u8_t *r
}
bool fastly_http_req_downstream_tls_client_cert_verify_result(fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_downstream_tls_client_cert_verify_result(ptr);
@@ -953,7 +962,7 @@ bool fastly_http_req_downstream_tls_client_cert_verify_result(fastly_error_t *er
}
bool fastly_http_req_downstream_tls_ja3_md5(fastly_world_list_u8_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_downstream_tls_ja3_md5(ptr);
@@ -980,7 +989,7 @@ bool fastly_http_req_downstream_tls_ja3_md5(fastly_world_list_u8_t *ret, fastly_
}
bool fastly_http_req_new(fastly_request_handle_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[8];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_new(ptr);
@@ -1007,7 +1016,7 @@ bool fastly_http_req_new(fastly_request_handle_t *ret, fastly_error_t *err) {
}
bool fastly_http_req_header_names_get(fastly_request_handle_t h, fastly_world_list_string_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_header_names_get((int32_t) (h), ptr);
@@ -1034,7 +1043,7 @@ bool fastly_http_req_header_names_get(fastly_request_handle_t h, fastly_world_li
}
bool fastly_http_req_header_value_get(fastly_request_handle_t h, fastly_world_string_t *name, fastly_world_option_string_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[16];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_header_value_get((int32_t) (h), (int32_t) (*name).ptr, (int32_t) (*name).len, ptr);
@@ -1074,7 +1083,7 @@ bool fastly_http_req_header_value_get(fastly_request_handle_t h, fastly_world_st
}
bool fastly_http_req_header_values_get(fastly_request_handle_t h, fastly_world_string_t *name, fastly_world_option_list_string_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[16];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_header_values_get((int32_t) (h), (int32_t) (*name).ptr, (int32_t) (*name).len, ptr);
@@ -1114,7 +1123,7 @@ bool fastly_http_req_header_values_get(fastly_request_handle_t h, fastly_world_s
}
bool fastly_http_req_header_values_set(fastly_request_handle_t h, fastly_world_string_t *name, fastly_world_list_string_t *values, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_header_values_set((int32_t) (h), (int32_t) (*name).ptr, (int32_t) (*name).len, (int32_t) (*values).ptr, (int32_t) (*values).len, ptr);
@@ -1139,7 +1148,7 @@ bool fastly_http_req_header_values_set(fastly_request_handle_t h, fastly_world_s
}
bool fastly_http_req_header_insert(fastly_request_handle_t h, fastly_world_string_t *name, fastly_world_string_t *value, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_header_insert((int32_t) (h), (int32_t) (*name).ptr, (int32_t) (*name).len, (int32_t) (*value).ptr, (int32_t) (*value).len, ptr);
@@ -1164,7 +1173,7 @@ bool fastly_http_req_header_insert(fastly_request_handle_t h, fastly_world_strin
}
bool fastly_http_req_header_append(fastly_request_handle_t h, fastly_world_string_t *name, fastly_world_string_t *value, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_header_append((int32_t) (h), (int32_t) (*name).ptr, (int32_t) (*name).len, (int32_t) (*value).ptr, (int32_t) (*value).len, ptr);
@@ -1189,7 +1198,7 @@ bool fastly_http_req_header_append(fastly_request_handle_t h, fastly_world_strin
}
bool fastly_http_req_header_remove(fastly_request_handle_t h, fastly_world_string_t *name, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_header_remove((int32_t) (h), (int32_t) (*name).ptr, (int32_t) (*name).len, ptr);
@@ -1214,7 +1223,7 @@ bool fastly_http_req_header_remove(fastly_request_handle_t h, fastly_world_strin
}
bool fastly_http_req_method_get(fastly_request_handle_t h, fastly_world_string_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_method_get((int32_t) (h), ptr);
@@ -1241,7 +1250,7 @@ bool fastly_http_req_method_get(fastly_request_handle_t h, fastly_world_string_t
}
bool fastly_http_req_method_set(fastly_request_handle_t h, fastly_world_string_t *method, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_method_set((int32_t) (h), (int32_t) (*method).ptr, (int32_t) (*method).len, ptr);
@@ -1266,7 +1275,7 @@ bool fastly_http_req_method_set(fastly_request_handle_t h, fastly_world_string_t
}
bool fastly_http_req_uri_get(fastly_request_handle_t h, fastly_world_string_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_uri_get((int32_t) (h), ptr);
@@ -1293,7 +1302,7 @@ bool fastly_http_req_uri_get(fastly_request_handle_t h, fastly_world_string_t *r
}
bool fastly_http_req_uri_set(fastly_request_handle_t h, fastly_world_string_t *uri, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_uri_set((int32_t) (h), (int32_t) (*uri).ptr, (int32_t) (*uri).len, ptr);
@@ -1318,7 +1327,7 @@ bool fastly_http_req_uri_set(fastly_request_handle_t h, fastly_world_string_t *u
}
bool fastly_http_req_version_get(fastly_request_handle_t h, fastly_http_version_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_version_get((int32_t) (h), ptr);
@@ -1345,7 +1354,7 @@ bool fastly_http_req_version_get(fastly_request_handle_t h, fastly_http_version_
}
bool fastly_http_req_version_set(fastly_request_handle_t h, fastly_http_version_t version, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_version_set((int32_t) (h), (int32_t) version, ptr);
@@ -1370,7 +1379,7 @@ bool fastly_http_req_version_set(fastly_request_handle_t h, fastly_http_version_
}
bool fastly_http_req_send(fastly_request_handle_t h, fastly_body_handle_t b, fastly_world_string_t *backend, fastly_response_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_send((int32_t) (h), (int32_t) (b), (int32_t) (*backend).ptr, (int32_t) (*backend).len, ptr);
@@ -1400,7 +1409,7 @@ bool fastly_http_req_send(fastly_request_handle_t h, fastly_body_handle_t b, fas
}
bool fastly_http_req_send_async(fastly_request_handle_t h, fastly_body_handle_t b, fastly_world_string_t *backend, fastly_pending_request_handle_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[8];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_send_async((int32_t) (h), (int32_t) (b), (int32_t) (*backend).ptr, (int32_t) (*backend).len, ptr);
@@ -1427,7 +1436,7 @@ bool fastly_http_req_send_async(fastly_request_handle_t h, fastly_body_handle_t
}
bool fastly_http_req_send_async_streaming(fastly_request_handle_t h, fastly_body_handle_t b, fastly_world_string_t *backend, fastly_pending_request_handle_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[8];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_send_async_streaming((int32_t) (h), (int32_t) (b), (int32_t) (*backend).ptr, (int32_t) (*backend).len, ptr);
@@ -1454,7 +1463,7 @@ bool fastly_http_req_send_async_streaming(fastly_request_handle_t h, fastly_body
}
bool fastly_http_req_pending_req_poll(fastly_pending_request_handle_t h, fastly_world_option_response_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[16];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_pending_req_poll((int32_t) (h), ptr);
@@ -1497,7 +1506,7 @@ bool fastly_http_req_pending_req_poll(fastly_pending_request_handle_t h, fastly_
}
bool fastly_http_req_pending_req_wait(fastly_pending_request_handle_t h, fastly_response_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_pending_req_wait((int32_t) (h), ptr);
@@ -1527,7 +1536,7 @@ bool fastly_http_req_pending_req_wait(fastly_pending_request_handle_t h, fastly_
}
bool fastly_http_req_pending_req_select(fastly_world_list_pending_request_handle_t *h, fastly_world_tuple2_u32_response_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[16];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_pending_req_select((int32_t) (*h).ptr, (int32_t) (*h).len, ptr);
@@ -1560,7 +1569,7 @@ bool fastly_http_req_pending_req_select(fastly_world_list_pending_request_handle
}
bool fastly_http_req_key_is_valid(bool *ret, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_key_is_valid(ptr);
@@ -1587,7 +1596,7 @@ bool fastly_http_req_key_is_valid(bool *ret, fastly_error_t *err) {
}
bool fastly_http_req_close(fastly_request_handle_t h, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_close((int32_t) (h), ptr);
@@ -1612,7 +1621,7 @@ bool fastly_http_req_close(fastly_request_handle_t h, fastly_error_t *err) {
}
bool fastly_http_req_auto_decompress_response_set(fastly_request_handle_t h, fastly_content_encodings_t encodings, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_auto_decompress_response_set((int32_t) (h), encodings, ptr);
@@ -1637,7 +1646,7 @@ bool fastly_http_req_auto_decompress_response_set(fastly_request_handle_t h, fas
}
bool fastly_http_req_upgrade_websocket(fastly_world_string_t *backend, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_upgrade_websocket((int32_t) (*backend).ptr, (int32_t) (*backend).len, ptr);
@@ -1662,7 +1671,7 @@ bool fastly_http_req_upgrade_websocket(fastly_world_string_t *backend, fastly_er
}
bool fastly_http_req_redirect_to_websocket_proxy(fastly_world_string_t *backend, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_redirect_to_websocket_proxy((int32_t) (*backend).ptr, (int32_t) (*backend).len, ptr);
@@ -1687,7 +1696,7 @@ bool fastly_http_req_redirect_to_websocket_proxy(fastly_world_string_t *backend,
}
bool fastly_http_req_redirect_to_grip_proxy(fastly_world_string_t *backend, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_redirect_to_grip_proxy((int32_t) (*backend).ptr, (int32_t) (*backend).len, ptr);
@@ -1712,7 +1721,7 @@ bool fastly_http_req_redirect_to_grip_proxy(fastly_world_string_t *backend, fast
}
bool fastly_http_req_framing_headers_mode_set(fastly_request_handle_t h, fastly_framing_headers_mode_t mode, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_req_framing_headers_mode_set((int32_t) (h), (int32_t) mode, ptr);
@@ -1737,7 +1746,7 @@ bool fastly_http_req_framing_headers_mode_set(fastly_request_handle_t h, fastly_
}
bool fastly_http_req_register_dynamic_backend(fastly_world_string_t *prefix, fastly_world_string_t *target, fastly_dynamic_backend_config_t *config, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[108];
int32_t ptr = (int32_t) &ret_area;
*((int32_t*)(ptr + 4)) = (int32_t) (*prefix).len;
@@ -1849,7 +1858,7 @@ bool fastly_http_req_register_dynamic_backend(fastly_world_string_t *prefix, fas
}
bool fastly_http_resp_new(fastly_response_handle_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[8];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_new(ptr);
@@ -1876,7 +1885,7 @@ bool fastly_http_resp_new(fastly_response_handle_t *ret, fastly_error_t *err) {
}
bool fastly_http_resp_header_names_get(fastly_response_handle_t h, fastly_world_list_string_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_header_names_get((int32_t) (h), ptr);
@@ -1903,7 +1912,7 @@ bool fastly_http_resp_header_names_get(fastly_response_handle_t h, fastly_world_
}
bool fastly_http_resp_header_value_get(fastly_response_handle_t h, fastly_world_string_t *name, fastly_world_option_string_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[16];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_header_value_get((int32_t) (h), (int32_t) (*name).ptr, (int32_t) (*name).len, ptr);
@@ -1943,7 +1952,7 @@ bool fastly_http_resp_header_value_get(fastly_response_handle_t h, fastly_world_
}
bool fastly_http_resp_header_values_get(fastly_response_handle_t h, fastly_world_string_t *name, fastly_world_option_list_string_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[16];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_header_values_get((int32_t) (h), (int32_t) (*name).ptr, (int32_t) (*name).len, ptr);
@@ -1983,7 +1992,7 @@ bool fastly_http_resp_header_values_get(fastly_response_handle_t h, fastly_world
}
bool fastly_http_resp_header_values_set(fastly_response_handle_t h, fastly_world_string_t *name, fastly_world_list_string_t *values, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_header_values_set((int32_t) (h), (int32_t) (*name).ptr, (int32_t) (*name).len, (int32_t) (*values).ptr, (int32_t) (*values).len, ptr);
@@ -2008,7 +2017,7 @@ bool fastly_http_resp_header_values_set(fastly_response_handle_t h, fastly_world
}
bool fastly_http_resp_header_insert(fastly_response_handle_t h, fastly_world_string_t *name, fastly_world_string_t *value, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_header_insert((int32_t) (h), (int32_t) (*name).ptr, (int32_t) (*name).len, (int32_t) (*value).ptr, (int32_t) (*value).len, ptr);
@@ -2033,7 +2042,7 @@ bool fastly_http_resp_header_insert(fastly_response_handle_t h, fastly_world_str
}
bool fastly_http_resp_header_append(fastly_response_handle_t h, fastly_world_string_t *name, fastly_world_string_t *value, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_header_append((int32_t) (h), (int32_t) (*name).ptr, (int32_t) (*name).len, (int32_t) (*value).ptr, (int32_t) (*value).len, ptr);
@@ -2058,7 +2067,7 @@ bool fastly_http_resp_header_append(fastly_response_handle_t h, fastly_world_str
}
bool fastly_http_resp_header_remove(fastly_response_handle_t h, fastly_world_string_t *name, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_header_remove((int32_t) (h), (int32_t) (*name).ptr, (int32_t) (*name).len, ptr);
@@ -2083,7 +2092,7 @@ bool fastly_http_resp_header_remove(fastly_response_handle_t h, fastly_world_str
}
bool fastly_http_resp_version_get(fastly_response_handle_t h, fastly_http_version_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_version_get((int32_t) (h), ptr);
@@ -2110,7 +2119,7 @@ bool fastly_http_resp_version_get(fastly_response_handle_t h, fastly_http_versio
}
bool fastly_http_resp_version_set(fastly_response_handle_t h, fastly_http_version_t version, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_version_set((int32_t) (h), (int32_t) version, ptr);
@@ -2135,7 +2144,7 @@ bool fastly_http_resp_version_set(fastly_response_handle_t h, fastly_http_versio
}
bool fastly_http_resp_send_downstream(fastly_response_handle_t h, fastly_body_handle_t b, bool streaming, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_send_downstream((int32_t) (h), (int32_t) (b), streaming, ptr);
@@ -2160,7 +2169,7 @@ bool fastly_http_resp_send_downstream(fastly_response_handle_t h, fastly_body_ha
}
bool fastly_http_resp_status_get(fastly_response_handle_t h, fastly_http_status_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(2)))
+ __attribute__((aligned(2)))
uint8_t ret_area[4];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_status_get((int32_t) (h), ptr);
@@ -2187,7 +2196,7 @@ bool fastly_http_resp_status_get(fastly_response_handle_t h, fastly_http_status_
}
bool fastly_http_resp_status_set(fastly_response_handle_t h, fastly_http_status_t status, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_status_set((int32_t) (h), (int32_t) (status), ptr);
@@ -2212,7 +2221,7 @@ bool fastly_http_resp_status_set(fastly_response_handle_t h, fastly_http_status_
}
bool fastly_http_resp_close(fastly_response_handle_t h, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_close((int32_t) (h), ptr);
@@ -2237,7 +2246,7 @@ bool fastly_http_resp_close(fastly_response_handle_t h, fastly_error_t *err) {
}
bool fastly_http_resp_framing_headers_mode_set(fastly_response_handle_t h, fastly_framing_headers_mode_t mode, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_http_resp_framing_headers_mode_set((int32_t) (h), (int32_t) mode, ptr);
@@ -2262,7 +2271,7 @@ bool fastly_http_resp_framing_headers_mode_set(fastly_response_handle_t h, fastl
}
bool fastly_dictionary_open(fastly_world_string_t *name, fastly_dictionary_handle_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[8];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_dictionary_open((int32_t) (*name).ptr, (int32_t) (*name).len, ptr);
@@ -2289,7 +2298,7 @@ bool fastly_dictionary_open(fastly_world_string_t *name, fastly_dictionary_handl
}
bool fastly_dictionary_get(fastly_dictionary_handle_t h, fastly_world_string_t *key, fastly_world_option_string_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[16];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_dictionary_get((int32_t) (h), (int32_t) (*key).ptr, (int32_t) (*key).len, ptr);
@@ -2329,7 +2338,7 @@ bool fastly_dictionary_get(fastly_dictionary_handle_t h, fastly_world_string_t *
}
bool fastly_geo_lookup(fastly_world_list_u8_t *addr_octets, fastly_world_string_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_geo_lookup((int32_t) (*addr_octets).ptr, (int32_t) (*addr_octets).len, ptr);
@@ -2356,7 +2365,7 @@ bool fastly_geo_lookup(fastly_world_list_u8_t *addr_octets, fastly_world_string_
}
bool fastly_object_store_open(fastly_world_string_t *name, fastly_object_store_handle_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[8];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_object_store_open((int32_t) (*name).ptr, (int32_t) (*name).len, ptr);
@@ -2383,7 +2392,7 @@ bool fastly_object_store_open(fastly_world_string_t *name, fastly_object_store_h
}
bool fastly_object_store_lookup(fastly_object_store_handle_t store, fastly_world_string_t *key, fastly_world_option_body_handle_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_object_store_lookup((int32_t) (store), (int32_t) (*key).ptr, (int32_t) (*key).len, ptr);
@@ -2423,7 +2432,7 @@ bool fastly_object_store_lookup(fastly_object_store_handle_t store, fastly_world
}
bool fastly_object_store_lookup_as_fd(fastly_object_store_handle_t store, fastly_world_string_t *key, fastly_world_option_fd_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_object_store_lookup_as_fd((int32_t) (store), (int32_t) (*key).ptr, (int32_t) (*key).len, ptr);
@@ -2463,7 +2472,7 @@ bool fastly_object_store_lookup_as_fd(fastly_object_store_handle_t store, fastly
}
bool fastly_object_store_insert(fastly_object_store_handle_t store, fastly_world_string_t *key, fastly_body_handle_t body_handle, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_object_store_insert((int32_t) (store), (int32_t) (*key).ptr, (int32_t) (*key).len, (int32_t) (body_handle), ptr);
@@ -2488,7 +2497,7 @@ bool fastly_object_store_insert(fastly_object_store_handle_t store, fastly_world
}
bool fastly_secret_store_open(fastly_world_string_t *name, fastly_secret_store_handle_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[8];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_secret_store_open((int32_t) (*name).ptr, (int32_t) (*name).len, ptr);
@@ -2515,7 +2524,7 @@ bool fastly_secret_store_open(fastly_world_string_t *name, fastly_secret_store_h
}
bool fastly_secret_store_get(fastly_secret_store_handle_t store, fastly_world_string_t *key, fastly_world_option_secret_handle_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_secret_store_get((int32_t) (store), (int32_t) (*key).ptr, (int32_t) (*key).len, ptr);
@@ -2555,7 +2564,7 @@ bool fastly_secret_store_get(fastly_secret_store_handle_t store, fastly_world_st
}
bool fastly_secret_store_plaintext(fastly_secret_handle_t secret, fastly_world_option_string_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[16];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_secret_store_plaintext((int32_t) (secret), ptr);
@@ -2595,7 +2604,7 @@ bool fastly_secret_store_plaintext(fastly_secret_handle_t secret, fastly_world_o
}
bool fastly_async_io_select(fastly_world_list_async_handle_t *hs, uint32_t timeout_ms, fastly_world_option_u32_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
+ __attribute__((aligned(4)))
uint8_t ret_area[12];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_async_io_select((int32_t) (*hs).ptr, (int32_t) (*hs).len, (int32_t) (timeout_ms), ptr);
@@ -2635,7 +2644,7 @@ bool fastly_async_io_select(fastly_world_list_async_handle_t *hs, uint32_t timeo
}
bool fastly_async_io_is_ready(fastly_async_handle_t handle, bool *ret, fastly_error_t *err) {
- __attribute__((__aligned__(1)))
+ __attribute__((aligned(1)))
uint8_t ret_area[2];
int32_t ptr = (int32_t) &ret_area;
__wasm_import_fastly_async_io_is_ready((int32_t) (handle), ptr);
@@ -2661,18 +2670,120 @@ bool fastly_async_io_is_ready(fastly_async_handle_t handle, bool *ret, fastly_er
}
}
-bool fastly_purge_surrogate_key(fastly_world_string_t *surrogate_key, bool soft_purge, fastly_purge_result_t *ret, fastly_error_t *err) {
- __attribute__((__aligned__(4)))
- uint8_t ret_area[12];
+bool fastly_purge_surrogate_key(fastly_world_string_t *surrogate_keys, fastly_purge_options_mask_t purge_options, fastly_world_option_string_t *ret, fastly_error_t *err) {
+ __attribute__((aligned(4)))
+ uint8_t ret_area[16];
int32_t ptr = (int32_t) &ret_area;
- __wasm_import_fastly_purge_surrogate_key((int32_t) (*surrogate_key).ptr, (int32_t) (*surrogate_key).len, soft_purge, ptr);
- fastly_world_result_purge_result_error_t result;
+ __wasm_import_fastly_purge_surrogate_key((int32_t) (*surrogate_keys).ptr, (int32_t) (*surrogate_keys).len, purge_options, ptr);
+ fastly_world_result_option_string_error_t result;
switch ((int32_t) (*((uint8_t*) (ptr + 0)))) {
case 0: {
result.is_err = false;
- result.val.ok = (fastly_purge_result_t) {
- (fastly_world_string_t) { (char*)(*((int32_t*) (ptr + 4))), (size_t)(*((int32_t*) (ptr + 8))) },
- };
+ fastly_world_option_string_t option;
+ switch ((int32_t) (*((uint8_t*) (ptr + 4)))) {
+ case 0: {
+ option.is_some = false;
+ break;
+ }
+ case 1: {
+ option.is_some = true;
+ option.val = (fastly_world_string_t) { (char*)(*((int32_t*) (ptr + 8))), (size_t)(*((int32_t*) (ptr + 12))) };
+ break;
+ }
+ }
+
+ result.val.ok = option;
+ break;
+ }
+ case 1: {
+ result.is_err = true;
+ result.val.err = (int32_t) (*((uint8_t*) (ptr + 4)));
+ break;
+ }
+ }
+ if (!result.is_err) {
+ *ret = result.val.ok;
+ return 1;
+ } else {
+ *err = result.val.err;
+ return 0;
+ }
+}
+
+bool fastly_cache_lookup(fastly_world_string_t *cache_key, fastly_cache_lookup_options_t *options, fastly_cache_handle_t *ret, fastly_error_t *err) {
+ __attribute__((aligned(4)))
+ uint8_t ret_area[8];
+ int32_t option;
+ int32_t option1;
+ if (((*options).request_headers).is_some) {
+ const fastly_request_handle_t *payload0 = &((*options).request_headers).val;
+ option = 1;
+ option1 = (int32_t) (*payload0);
+ } else {
+ option = 0;
+ option1 = 0;
+ }
+ int32_t ptr = (int32_t) &ret_area;
+ __wasm_import_fastly_cache_lookup((int32_t) (*cache_key).ptr, (int32_t) (*cache_key).len, option, option1, ptr);
+ fastly_world_result_cache_handle_error_t result;
+ switch ((int32_t) (*((uint8_t*) (ptr + 0)))) {
+ case 0: {
+ result.is_err = false;
+ result.val.ok = (uint32_t) (*((int32_t*) (ptr + 4)));
+ break;
+ }
+ case 1: {
+ result.is_err = true;
+ result.val.err = (int32_t) (*((uint8_t*) (ptr + 4)));
+ break;
+ }
+ }
+ if (!result.is_err) {
+ *ret = result.val.ok;
+ return 1;
+ } else {
+ *err = result.val.err;
+ return 0;
+ }
+}
+
+bool fastly_cache_insert(fastly_world_string_t *cache_key, fastly_cache_write_options_t *options, fastly_body_handle_t *ret, fastly_error_t *err) {
+ __attribute__((aligned(4)))
+ uint8_t ret_area[8];
+ int32_t ptr = (int32_t) &ret_area;
+ __wasm_import_fastly_cache_insert((int32_t) (*cache_key).ptr, (int32_t) (*cache_key).len, (int64_t) ((*options).max_age_ns), (int32_t) ((*options).request_headers), (int32_t) ((*options).vary_rule).ptr, (int32_t) ((*options).vary_rule).len, (int64_t) ((*options).initial_age_ns), (int64_t) ((*options).stale_while_revalidate_ns), (int32_t) ((*options).surrogate_keys).ptr, (int32_t) ((*options).surrogate_keys).len, (int64_t) ((*options).length), (int32_t) ((*options).user_metadata).ptr, (int32_t) ((*options).user_metadata).len, (*options).sensitive_data, ptr);
+ fastly_world_result_body_handle_error_t result;
+ switch ((int32_t) (*((uint8_t*) (ptr + 0)))) {
+ case 0: {
+ result.is_err = false;
+ result.val.ok = (uint32_t) (*((int32_t*) (ptr + 4)));
+ break;
+ }
+ case 1: {
+ result.is_err = true;
+ result.val.err = (int32_t) (*((uint8_t*) (ptr + 4)));
+ break;
+ }
+ }
+ if (!result.is_err) {
+ *ret = result.val.ok;
+ return 1;
+ } else {
+ *err = result.val.err;
+ return 0;
+ }
+}
+
+bool fastly_cache_get_body(fastly_cache_handle_t handle, fastly_cache_get_body_options_t *options, fastly_body_handle_t *ret, fastly_error_t *err) {
+ __attribute__((aligned(4)))
+ uint8_t ret_area[8];
+ int32_t ptr = (int32_t) &ret_area;
+ __wasm_import_fastly_cache_get_body((int32_t) (handle), (int64_t) ((*options).start), (int64_t) ((*options).end), ptr);
+ fastly_world_result_body_handle_error_t result;
+ switch ((int32_t) (*((uint8_t*) (ptr + 0)))) {
+ case 0: {
+ result.is_err = false;
+ result.val.ok = (uint32_t) (*((int32_t*) (ptr + 4)));
break;
}
case 1: {
@@ -2690,7 +2801,7 @@ bool fastly_purge_surrogate_key(fastly_world_string_t *surrogate_key, bool soft_
}
}
-__attribute__((__export_name__("compute-at-edge#serve")))
+__attribute__((export_name("compute-at-edge#serve")))
int32_t __wasm_export_compute_at_edge_serve(int32_t arg, int32_t arg0) {
compute_at_edge_request_t arg1 = (compute_at_edge_request_t) {
(uint32_t) (arg),
diff --git a/runtime/js-compute-runtime/fastly-world/fastly_world.h b/runtime/js-compute-runtime/fastly-world/fastly_world.h
index e6523e5fd4..743d0b1ac0 100644
--- a/runtime/js-compute-runtime/fastly-world/fastly_world.h
+++ b/runtime/js-compute-runtime/fastly-world/fastly_world.h
@@ -37,9 +37,10 @@ typedef uint32_t fastly_response_handle_t;
typedef uint32_t fastly_request_handle_t;
-typedef struct {
- fastly_world_string_t id;
-} fastly_purge_result_t;
+typedef uint8_t fastly_purge_options_mask_t;
+
+#define FASTLY_PURGE_OPTIONS_MASK_SOFT_PURGE (1 << 0)
+#define FASTLY_PURGE_OPTIONS_MASK_RET_BUF (1 << 1)
typedef uint32_t fastly_pending_request_handle_t;
@@ -59,7 +60,6 @@ typedef uint16_t fastly_http_status_t;
typedef uint8_t fastly_http_cache_override_tag_t;
-// Do not cache the response to this request, regardless of the origin response's headers.
#define FASTLY_HTTP_CACHE_OVERRIDE_TAG_PASS (1 << 0)
#define FASTLY_HTTP_CACHE_OVERRIDE_TAG_TTL (1 << 1)
#define FASTLY_HTTP_CACHE_OVERRIDE_TAG_STALE_WHILE_REVALIDATE (1 << 2)
@@ -81,84 +81,24 @@ typedef struct {
} fastly_world_option_float32_t;
typedef struct {
- // * The name of the organization associated with as_number.
- // *
- // * For example, fastly is the value given for IP addresses under AS-54113.
fastly_world_option_string_t as_name;
- // * [Autonomous system](https://en.wikipedia.org/wiki/Autonomous_system_(Internet)) (AS) number.
fastly_world_option_u32_t as_number;
- // * The telephone area code associated with an IP address.
- // *
- // * These are only available for IP addresses in the United States, its territories, and
- // Canada.
fastly_world_option_u32_t area_code;
- // * City or town name.
fastly_world_option_string_t city;
- // * Connection speed.
fastly_world_option_string_t conn_speed;
- // * Connection type.
fastly_world_option_string_t conn_type;
- // * Continent.
fastly_world_option_string_t continent;
- // * A two-character [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1) country code for the
- // country associated with an IP address.
- // *
- // * The US country code is returned for IP addresses associated with overseas United States
- // military bases.
- // *
- // * These values include subdivisions that are assigned their own country codes in ISO
- // 3166-1. For example, subdivisions NO-21 and NO-22 are presented with the country code SJ
- // for Svalbard and the Jan Mayen Islands.
fastly_world_option_string_t country_code;
- // * A three-character [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)
- // country code for the country associated with the IP address.
- // *
- // * The USA country code is returned for IP addresses associated with overseas United
- // States military bases.
fastly_world_option_string_t country_code3;
- // * Country name.
- // *
- // * This field is the [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1) English short
- // name for a country.
fastly_world_option_string_t country_name;
- // * Time zone offset from Greenwich Mean Time (GMT) for `city`.
fastly_world_option_string_t gmt_offset;
- // * Latitude, in units of degrees from the equator.
- // *
- // * Values range from -90.0 to +90.0 inclusive, and are based on the [WGS
- // 84](https://en.wikipedia.org/wiki/World_Geodetic_System) coordinate reference system.
fastly_world_option_float32_t latitude;
- // * Longitude, in units of degrees from the [IERS Reference
- // Meridian](https://en.wikipedia.org/wiki/IERS_Reference_Meridian).
- // *
- // * Values range from -180.0 to +180.0 inclusive, and are based on the [WGS
- // 84](https://en.wikipedia.org/wiki/World_Geodetic_System) coordinate reference system.
fastly_world_option_float32_t longitude;
- // * Metro code, representing designated market areas (DMAs) in the United States.
fastly_world_option_u32_t metro_code;
- // * The postal code associated with the IP address.
- // *
- // * These are available for some IP addresses in Australia, Canada, France, Germany, Italy,
- // Spain, Switzerland, the United Kingdom, and the United States.
- // *
- // * For Canadian postal codes, this is the first 3 characters. For the United Kingdom, this
- // is the first 2-4 characters (outward code). For countries with alphanumeric postal codes,
- // this field is a lowercase transliteration.
fastly_world_option_string_t postal_code;
- // * Client proxy description.
fastly_world_option_string_t proxy_description;
- // * Client proxy type.
fastly_world_option_string_t proxy_type;
- // * [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) country subdivision code.
- // *
- // * For countries with multiple levels of subdivision (for example, nations within the
- // United Kingdom), this variable gives the more specific subdivision.
- // *
- // * This field can be None for countries that do not have ISO country subdivision codes.
- // For example, None is given for IP addresses assigned to the Åland Islands (country code
- // AX, illustrated below).
fastly_world_option_string_t region;
- // * Time zone offset from coordinated universal time (UTC) for `city`.
fastly_world_option_u32_t utc_offset;
} fastly_geo_data_t;
@@ -172,51 +112,19 @@ typedef uint32_t fastly_fd_t;
typedef uint8_t fastly_error_t;
-// Unknown error value.
-// It should be an internal error if this is returned.
#define FASTLY_ERROR_UNKNOWN_ERROR 0
-// Generic error value.
-// This means that some unexpected error occurred during a hostcall.
#define FASTLY_ERROR_GENERIC_ERROR 1
-// Invalid argument.
#define FASTLY_ERROR_INVALID_ARGUMENT 2
-// Invalid handle.
-// Thrown when a handle is not valid. E.G. No dictionary exists with the given name.
#define FASTLY_ERROR_BAD_HANDLE 3
-// Buffer length error.
-// Thrown when a buffer is too long.
#define FASTLY_ERROR_BUFFER_LEN 4
-// Unsupported operation error.
-// This error is thrown when some operation cannot be performed, because it is not supported.
#define FASTLY_ERROR_UNSUPPORTED 5
-// Alignment error.
-// This is thrown when a pointer does not point to a properly aligned slice of memory.
#define FASTLY_ERROR_BAD_ALIGN 6
-// Invalid HTTP error.
-// This can be thrown when a method, URI, header, or status is not valid. This can also
-// be thrown if a message head is too large.
#define FASTLY_ERROR_HTTP_INVALID 7
-// HTTP user error.
-// This is thrown in cases where user code caused an HTTP error. For example, attempt to send
-// a 1xx response code, or a request with a non-absolute URI. This can also be caused by
-// an unexpected header: both `content-length` and `transfer-encoding`, for example.
#define FASTLY_ERROR_HTTP_USER 8
-// HTTP incomplete message error.
-// This can be thrown when a stream ended unexpectedly.
#define FASTLY_ERROR_HTTP_INCOMPLETE 9
-// A `None` error.
-// This status code is used to indicate when an optional value did not exist, as opposed to
-// an empty value.
-// Note, this value should no longer be used, as we have explicit optional types now.
#define FASTLY_ERROR_OPTIONAL_NONE 10
-// Message head too large.
#define FASTLY_ERROR_HTTP_HEAD_TOO_LARGE 11
-// Invalid HTTP status.
#define FASTLY_ERROR_HTTP_INVALID_STATUS 12
-// Limit exceeded
-//
-// This is returned when an attempt to allocate a resource has exceeded the maximum number of
-// resources permitted. For example, creating too many response handles.
#define FASTLY_ERROR_LIMIT_EXCEEDED 13
typedef struct {
@@ -250,6 +158,55 @@ typedef uint8_t fastly_content_encodings_t;
#define FASTLY_CONTENT_ENCODINGS_GZIP (1 << 0)
+typedef uint64_t fastly_cache_object_length_t;
+
+typedef struct {
+ bool is_some;
+ fastly_request_handle_t val;
+} fastly_world_option_request_handle_t;
+
+// Extensible options for cache lookup operations; currently used for both `lookup` and
+// `transaction_lookup`.
+typedef struct {
+ fastly_world_option_request_handle_t request_headers;
+} fastly_cache_lookup_options_t;
+
+typedef uint64_t fastly_cache_hit_count_t;
+
+// The outcome of a cache lookup (either bare or as part of a cache transaction)
+typedef uint32_t fastly_cache_handle_t;
+
+typedef struct {
+ uint64_t start;
+ uint64_t end;
+} fastly_cache_get_body_options_t;
+
+typedef uint64_t fastly_cache_duration_ns_t;
+
+typedef struct {
+ uint8_t *ptr;
+ size_t len;
+} fastly_world_list_u8_t;
+
+// Configuration for several hostcalls that write to the cache:
+// - `insert`
+// - `transaction-insert`
+// - `transaction-insert-and-stream-back`
+// - `transaction-update`
+//
+// Some options are only allowed for certain of these hostcalls; see `cache-write-options-mask`.
+typedef struct {
+ fastly_cache_duration_ns_t max_age_ns;
+ fastly_request_handle_t request_headers;
+ fastly_world_string_t vary_rule;
+ fastly_cache_duration_ns_t initial_age_ns;
+ fastly_cache_duration_ns_t stale_while_revalidate_ns;
+ fastly_world_string_t surrogate_keys;
+ fastly_cache_object_length_t length;
+ fastly_world_list_u8_t user_metadata;
+ bool sensitive_data;
+} fastly_cache_write_options_t;
+
typedef uint8_t fastly_body_write_end_t;
#define FASTLY_BODY_WRITE_END_BACK 0
@@ -280,11 +237,6 @@ typedef struct {
// into, even before the origin itself consumes that data.
typedef uint32_t fastly_async_handle_t;
-typedef struct {
- uint8_t *ptr;
- size_t len;
-} fastly_world_list_u8_t;
-
typedef struct {
fastly_world_string_t *ptr;
size_t len;
@@ -414,9 +366,6 @@ bool fastly_http_req_pending_req_wait(fastly_pending_request_handle_t h, fastly_
bool fastly_http_req_pending_req_select(fastly_world_list_pending_request_handle_t *h,
fastly_world_tuple2_u32_response_t *ret,
fastly_error_t *err);
-// Returns whether or not the original client request arrived with a
-// Fastly-Key belonging to a user with the rights to purge content on this
-// service.
bool fastly_http_req_key_is_valid(bool *ret, fastly_error_t *err);
bool fastly_http_req_close(fastly_request_handle_t h, fastly_error_t *err);
bool fastly_http_req_auto_decompress_response_set(fastly_request_handle_t h,
@@ -460,7 +409,6 @@ bool fastly_http_resp_status_get(fastly_response_handle_t h, fastly_http_status_
bool fastly_http_resp_status_set(fastly_response_handle_t h, fastly_http_status_t status,
fastly_error_t *err);
bool fastly_http_resp_close(fastly_response_handle_t h, fastly_error_t *err);
-// Adjust how this response's framing headers are determined.
bool fastly_http_resp_framing_headers_mode_set(fastly_response_handle_t h,
fastly_framing_headers_mode_t mode,
fastly_error_t *err);
@@ -468,7 +416,6 @@ bool fastly_dictionary_open(fastly_world_string_t *name, fastly_dictionary_handl
fastly_error_t *err);
bool fastly_dictionary_get(fastly_dictionary_handle_t h, fastly_world_string_t *key,
fastly_world_option_string_t *ret, fastly_error_t *err);
-// JSON string for now
bool fastly_geo_lookup(fastly_world_list_u8_t *addr_octets, fastly_world_string_t *ret,
fastly_error_t *err);
bool fastly_object_store_open(fastly_world_string_t *name, fastly_object_store_handle_t *ret,
@@ -486,28 +433,18 @@ bool fastly_secret_store_get(fastly_secret_store_handle_t store, fastly_world_st
fastly_world_option_secret_handle_t *ret, fastly_error_t *err);
bool fastly_secret_store_plaintext(fastly_secret_handle_t secret, fastly_world_option_string_t *ret,
fastly_error_t *err);
-// Blocks until one of the given objects is ready for I/O, or the optional timeout expires.
-//
-// Valid object handles includes bodies and pending requests. See the `async_item_handle`
-// definition for more details, including what I/O actions are associated with each handle
-// type.
-//
-// The timeout is specified in milliseconds, or 0 if no timeout is desired.
-//
-// Returns the _index_ (not handle!) of the first object that is ready, or u32::MAX if the
-// timeout expires before any objects are ready for I/O.
bool fastly_async_io_select(fastly_world_list_async_handle_t *hs, uint32_t timeout_ms,
fastly_world_option_u32_t *ret, fastly_error_t *err);
-// Returns 1 if the given async item is "ready" for its associated I/O action, 0 otherwise.
-//
-// If an object is ready, the I/O action is guaranteed to complete without blocking.
-//
-// Valid object handles includes bodies and pending requests. See the `async_item_handle`
-// definition for more details, including what I/O actions are associated with each handle
-// type.
bool fastly_async_io_is_ready(fastly_async_handle_t handle, bool *ret, fastly_error_t *err);
-bool fastly_purge_surrogate_key(fastly_world_string_t *surrogate_key, bool soft_purge,
- fastly_purge_result_t *ret, fastly_error_t *err);
+bool fastly_purge_surrogate_key(fastly_world_string_t *surrogate_keys,
+ fastly_purge_options_mask_t purge_options,
+ fastly_world_option_string_t *ret, fastly_error_t *err);
+bool fastly_cache_lookup(fastly_world_string_t *cache_key, fastly_cache_lookup_options_t *options,
+ fastly_cache_handle_t *ret, fastly_error_t *err);
+bool fastly_cache_insert(fastly_world_string_t *cache_key, fastly_cache_write_options_t *options,
+ fastly_body_handle_t *ret, fastly_error_t *err);
+bool fastly_cache_get_body(fastly_cache_handle_t handle, fastly_cache_get_body_options_t *options,
+ fastly_body_handle_t *ret, fastly_error_t *err);
// Exported Functions from `compute-at-edge`
bool compute_at_edge_serve(compute_at_edge_request_t *req);
diff --git a/runtime/js-compute-runtime/fastly-world/fastly_world_adapter.cpp b/runtime/js-compute-runtime/fastly-world/fastly_world_adapter.cpp
index d2f4ba7105..43808a96c9 100644
--- a/runtime/js-compute-runtime/fastly-world/fastly_world_adapter.cpp
+++ b/runtime/js-compute-runtime/fastly-world/fastly_world_adapter.cpp
@@ -701,3 +701,99 @@ bool fastly_async_io_is_ready(fastly_async_handle_t handle, bool *ret, fastly_er
*ret = (bool)ret_int;
return true;
}
+
+bool fastly_purge_surrogate_key(fastly_world_string_t *surrogate_key,
+ fastly_purge_options_mask_t options_mask,
+ fastly_world_option_string_t *ret, fastly_error_t *err) {
+ fastly::PurgeOptions options{nullptr, 0, nullptr};
+
+ // Currently this host-call has been implemented to support the `SimpleCache.delete(key)` method,
+ // which uses hard-purging and not soft-purging.
+ // TODO: Create a JS API for this hostcall which supports hard-purging and another which supports
+ // soft-purging. E.G. `fastly.purgeSurrogateKey(key)` and `fastly.softPurgeSurrogateKey(key)`
+ MOZ_ASSERT(!(options_mask & FASTLY_PURGE_OPTIONS_MASK_SOFT_PURGE));
+ MOZ_ASSERT(!(options_mask & FASTLY_PURGE_OPTIONS_MASK_RET_BUF));
+
+ ret->is_some = false;
+
+ return convert_result(
+ fastly::purge_surrogate_key(surrogate_key->ptr, surrogate_key->len, options_mask, &options),
+ err);
+}
+
+#define FASTLY_CACHE_LOOKUP_OPTIONS_MASK_RESERVED (1 << 0)
+#define FASTLY_CACHE_LOOKUP_OPTIONS_MASK_REQUEST_HEADERS (1 << 1)
+
+bool fastly_cache_lookup(fastly_world_string_t *cache_key, fastly_cache_lookup_options_t *options,
+ fastly_cache_handle_t *ret, fastly_error_t *err) {
+ // Currently this host-call has been implemented to support the `SimpleCache.get(key)` method,
+ // which does not use any fields from `fastly_cache_lookup_options_t`.
+ uint8_t options_mask = 0;
+ return convert_result(
+ fastly::cache_lookup(cache_key->ptr, cache_key->len, options_mask, options, ret), err);
+}
+
+#define FASTLY_CACHE_WRITE_OPTIONS_MASK_RESERVED (1 << 0)
+#define FASTLY_CACHE_WRITE_OPTIONS_MASK_REQUEST_HEADERS (1 << 1)
+#define FASTLY_CACHE_WRITE_OPTIONS_MASK_VARY_RULE (1 << 2)
+#define FASTLY_CACHE_WRITE_OPTIONS_MASK_INITIAL_AGE_NS (1 << 3)
+#define FASTLY_CACHE_WRITE_OPTIONS_MASK_STALE_WHILE_REVALIDATE_NS (1 << 4)
+#define FASTLY_CACHE_WRITE_OPTIONS_MASK_SURROGATE_KEYS (1 << 5)
+#define FASTLY_CACHE_WRITE_OPTIONS_MASK_LENGTH (1 << 6)
+#define FASTLY_CACHE_WRITE_OPTIONS_MASK_USER_METADATA (1 << 7)
+#define FASTLY_CACHE_WRITE_OPTIONS_MASK_SENSITIVE_DATA (1 << 8)
+
+bool fastly_cache_insert(fastly_world_string_t *cache_key, fastly_cache_write_options_t *options,
+ fastly_body_handle_t *ret, fastly_error_t *err) {
+ uint16_t options_mask = 0;
+ fastly::CacheWriteOptions opts;
+ std::memset(&opts, 0, sizeof(opts));
+ opts.max_age_ns = options->max_age_ns;
+
+ if (options->request_headers != INVALID_HANDLE && options->request_headers != 0) {
+ options_mask |= FASTLY_CACHE_WRITE_OPTIONS_MASK_REQUEST_HEADERS;
+ opts.request_headers = options->request_headers;
+ }
+ if (options->vary_rule.ptr != nullptr) {
+ options_mask |= FASTLY_CACHE_WRITE_OPTIONS_MASK_VARY_RULE;
+ opts.vary_rule_len = options->vary_rule.len;
+ opts.vary_rule_ptr = reinterpret_cast(options->vary_rule.ptr);
+ }
+ if (options->initial_age_ns != 0) {
+ options_mask |= FASTLY_CACHE_WRITE_OPTIONS_MASK_INITIAL_AGE_NS;
+ opts.initial_age_ns = options->initial_age_ns;
+ }
+ if (options->stale_while_revalidate_ns != 0) {
+ options_mask |= FASTLY_CACHE_WRITE_OPTIONS_MASK_STALE_WHILE_REVALIDATE_NS;
+ opts.stale_while_revalidate_ns = options->stale_while_revalidate_ns;
+ }
+ if (options->surrogate_keys.ptr != nullptr) {
+ options_mask |= FASTLY_CACHE_WRITE_OPTIONS_MASK_SURROGATE_KEYS;
+ opts.surrogate_keys_len = options->surrogate_keys.len;
+ opts.surrogate_keys_ptr = reinterpret_cast(options->surrogate_keys.ptr);
+ }
+ if (options->length != 0) {
+ options_mask |= FASTLY_CACHE_WRITE_OPTIONS_MASK_LENGTH;
+ opts.length = options->length;
+ }
+ if (options->user_metadata.ptr != nullptr) {
+ options_mask |= FASTLY_CACHE_WRITE_OPTIONS_MASK_USER_METADATA;
+ opts.user_metadata_len = options->user_metadata.len;
+ opts.user_metadata_ptr = options->user_metadata.ptr;
+ }
+ if (options->sensitive_data) {
+ options_mask |= FASTLY_CACHE_WRITE_OPTIONS_MASK_SENSITIVE_DATA;
+ }
+ return convert_result(
+ fastly::cache_insert(cache_key->ptr, cache_key->len, options_mask, &opts, ret), err);
+}
+bool fastly_cache_get_body(fastly_cache_handle_t handle, fastly_cache_get_body_options_t *options,
+ fastly_body_handle_t *ret, fastly_error_t *err) {
+ uint32_t options_mask = 0;
+ bool ok = convert_result(fastly::cache_get_body(handle, options_mask, options, ret), err);
+ if (!ok && *err == FASTLY_ERROR_OPTIONAL_NONE) {
+ *ret = INVALID_HANDLE;
+ return true;
+ }
+ return ok;
+}
\ No newline at end of file
diff --git a/runtime/js-compute-runtime/fastly-world/fastly_world_component_type.o b/runtime/js-compute-runtime/fastly-world/fastly_world_component_type.o
index 86f89ba958..c3055cfc22 100644
Binary files a/runtime/js-compute-runtime/fastly-world/fastly_world_component_type.o and b/runtime/js-compute-runtime/fastly-world/fastly_world_component_type.o differ
diff --git a/runtime/js-compute-runtime/fastly.wit b/runtime/js-compute-runtime/fastly.wit
index f244a3e567..ec73786930 100644
--- a/runtime/js-compute-runtime/fastly.wit
+++ b/runtime/js-compute-runtime/fastly.wit
@@ -45,7 +45,7 @@ default world fastly-world {
http-invalid-status,
/// Limit exceeded
///
- /// This is returned when an attempt to allocate a resource has exceeded the maximum number of
+ /// This is returned when an attempt to allocate a resource has exceeded the maximum number of
/// resources permitted. For example, creating too many response handles.
limit-exceeded
}
@@ -479,11 +479,91 @@ default world fastly-world {
/*
* Fastly Purge
*/
- record purge-result {
- id: string
+
+ flags purge-options-mask {
+ soft-purge,
+ ret-buf
+ }
+
+ /*
+ * A surrogate key can be a max of 1024 characters.
+ * A surrogate key must contain only printable ASCII characters (those between `0x21` and `0x7E`, inclusive).
+ */
+ purge-surrogate-key: func(surrogate-keys: string, purge-options: purge-options-mask) -> result