Skip to content

Commit c7f07bf

Browse files
Jake ChampionJakeChampion
authored andcommitted
use JS_NewObjectForConstructor to construct instances of Request class instead of JS_NewObjectWithGivenProto as JS_NewObjectForConstructor will use the callee to determine parentage and
[[Prototype]], which allows applications to extend from Request
1 parent d9ef0a1 commit c7f07bf

File tree

5 files changed

+112
-34
lines changed

5 files changed

+112
-34
lines changed

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22

33
# Integration Tests build output
44
integration-tests/**/fixtures/**/*.tar.gz
5-
integration-tests/**/fixtures/**/fastly.toml
5+
integration-tests/**/fixtures/**/pkg/**/fastly.toml
66
integration-tests/**/fixtures/**/*.wasm
77
integration-tests/**/fixtures/**/*.js
88
integration-tests/**/fixtures/**/*.js.map
9+
integration-tests/**/fixtures/**/compiler_flags
10+
integration-tests/**/fixtures/**/js-compute-builtins.d
11+
integration-tests/**/fixtures/**/js-compute-builtins.o
12+
integration-tests/**/fixtures/**/js-compute-runtime.d
13+
integration-tests/**/fixtures/**/js-compute-runtime.o
14+
integration-tests/**/fixtures/**/rusturl
915

1016
# Ignore Reference Docs
1117
# TODO

c-dependencies/js-compute-runtime/js-compute-builtins.cpp

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4086,19 +4086,6 @@ bool apply_cache_override(JSContext *cx, HandleObject self) {
40864086
sk_chars.get(), sk_len));
40874087
}
40884088

4089-
JSObject *create(JSContext *cx, HandleValue input, HandleValue init);
4090-
4091-
bool constructor(JSContext *cx, unsigned argc, Value *vp) {
4092-
REQUEST_HANDLER_ONLY("The Request builtin");
4093-
CTOR_HEADER("Request", 1);
4094-
RootedObject request(cx, create(cx, args[0], args.get(1)));
4095-
if (!request)
4096-
return false;
4097-
4098-
args.rval().setObject(*request);
4099-
return true;
4100-
}
4101-
41024089
const unsigned ctor_length = 1;
41034090

41044091
bool check_receiver(JSContext *cx, HandleValue receiver, const char *method_name);
@@ -4183,6 +4170,8 @@ const JSPropertySpec properties[] = {JS_PSG("method", method_get, JSPROP_ENUMERA
41834170
JS_PSG("bodyUsed", bodyUsed_get, JSPROP_ENUMERATE),
41844171
JS_PS_END};
41854172

4173+
bool constructor(JSContext *cx, unsigned argc, Value *vp);
4174+
41864175
CLASS_BOILERPLATE_CUSTOM_INIT(Request)
41874176

41884177
JSString *GET_atom;
@@ -4198,23 +4187,19 @@ bool init_class(JSContext *cx, HandleObject global) {
41984187
return !!GET_atom;
41994188
}
42004189

4201-
JSObject *create(JSContext *cx, RequestHandle request_handle, BodyHandle body_handle,
4202-
bool is_downstream) {
4203-
RootedObject request(cx, JS_NewObjectWithGivenProto(cx, &class_, proto_obj));
4204-
if (!request)
4205-
return nullptr;
4206-
4207-
JS::SetReservedSlot(request, Slots::Request, JS::Int32Value(request_handle.handle));
4208-
JS::SetReservedSlot(request, Slots::Headers, JS::NullValue());
4209-
JS::SetReservedSlot(request, Slots::Body, JS::Int32Value(body_handle.handle));
4210-
JS::SetReservedSlot(request, Slots::BodyStream, JS::NullValue());
4211-
JS::SetReservedSlot(request, Slots::HasBody, JS::FalseValue());
4212-
JS::SetReservedSlot(request, Slots::BodyUsed, JS::FalseValue());
4213-
JS::SetReservedSlot(request, Slots::Method, JS::StringValue(GET_atom));
4214-
JS::SetReservedSlot(request, Slots::CacheOverride, JS::NullValue());
4215-
JS::SetReservedSlot(request, Slots::IsDownstream, JS::BooleanValue(is_downstream));
4190+
JSObject *create(JSContext *cx, HandleObject requestInstance, RequestHandle request_handle,
4191+
BodyHandle body_handle, bool is_downstream) {
4192+
JS::SetReservedSlot(requestInstance, Slots::Request, JS::Int32Value(request_handle.handle));
4193+
JS::SetReservedSlot(requestInstance, Slots::Headers, JS::NullValue());
4194+
JS::SetReservedSlot(requestInstance, Slots::Body, JS::Int32Value(body_handle.handle));
4195+
JS::SetReservedSlot(requestInstance, Slots::BodyStream, JS::NullValue());
4196+
JS::SetReservedSlot(requestInstance, Slots::HasBody, JS::FalseValue());
4197+
JS::SetReservedSlot(requestInstance, Slots::BodyUsed, JS::FalseValue());
4198+
JS::SetReservedSlot(requestInstance, Slots::Method, JS::StringValue(GET_atom));
4199+
JS::SetReservedSlot(requestInstance, Slots::CacheOverride, JS::NullValue());
4200+
JS::SetReservedSlot(requestInstance, Slots::IsDownstream, JS::BooleanValue(is_downstream));
42164201

4217-
return request;
4202+
return requestInstance;
42184203
}
42194204

42204205
/**
@@ -4224,7 +4209,8 @@ JSObject *create(JSContext *cx, RequestHandle request_handle, BodyHandle body_ha
42244209
* "Roughly" because not all aspects of Request handling make sense in C@E.
42254210
* The places where we deviate from the spec are called out inline.
42264211
*/
4227-
JSObject *create(JSContext *cx, HandleValue input, HandleValue init_val) {
4212+
JSObject *create(JSContext *cx, HandleObject requestInstance, HandleValue input,
4213+
HandleValue init_val) {
42284214
RequestHandle request_handle = {INVALID_HANDLE};
42294215
if (!HANDLE_RESULT(cx, xqd_req_new(&request_handle))) {
42304216
return nullptr;
@@ -4235,7 +4221,7 @@ JSObject *create(JSContext *cx, HandleValue input, HandleValue init_val) {
42354221
return nullptr;
42364222
}
42374223

4238-
RootedObject request(cx, create(cx, request_handle, body_handle, false));
4224+
RootedObject request(cx, create(cx, requestInstance, request_handle, body_handle, false));
42394225
if (!request) {
42404226
return nullptr;
42414227
}
@@ -4652,6 +4638,18 @@ JSObject *create(JSContext *cx, HandleValue input, HandleValue init_val) {
46524638

46534639
return request;
46544640
}
4641+
4642+
bool constructor(JSContext *cx, unsigned argc, Value *vp) {
4643+
REQUEST_HANDLER_ONLY("The Request builtin");
4644+
CTOR_HEADER("Request", 1);
4645+
RootedObject requestInstance(cx, JS_NewObjectForConstructor(cx, &class_, args));
4646+
RootedObject request(cx, create(cx, requestInstance, args[0], args.get(1)));
4647+
if (!request)
4648+
return false;
4649+
4650+
args.rval().setObject(*request);
4651+
return true;
4652+
}
46554653
} // namespace Request
46564654

46574655
namespace Response {
@@ -6287,7 +6285,12 @@ bool client_get(JSContext *cx, unsigned argc, Value *vp) {
62876285
* initialized. It's filled in at runtime using `init_downstream_request`.
62886286
*/
62896287
static JSObject *prepare_downstream_request(JSContext *cx) {
6290-
return Request::create(cx, RequestHandle{INVALID_HANDLE}, BodyHandle{INVALID_HANDLE}, true);
6288+
RootedObject requestInstance(
6289+
cx, JS_NewObjectWithGivenProto(cx, &Request::class_, Request::proto_obj));
6290+
if (!requestInstance)
6291+
return nullptr;
6292+
return Request::create(cx, requestInstance, RequestHandle{INVALID_HANDLE},
6293+
BodyHandle{INVALID_HANDLE}, true);
62916294
}
62926295

62936296
/**
@@ -7318,7 +7321,12 @@ bool fetch(JSContext *cx, unsigned argc, Value *vp) {
73187321
return ReturnPromiseRejectedWithPendingError(cx, args);
73197322
}
73207323

7321-
RootedObject request(cx, Request::create(cx, args[0], args.get(1)));
7324+
RootedObject requestInstance(
7325+
cx, JS_NewObjectWithGivenProto(cx, &Request::class_, Request::proto_obj));
7326+
if (!requestInstance)
7327+
return false;
7328+
7329+
RootedObject request(cx, Request::create(cx, requestInstance, args[0], args.get(1)));
73227330
if (!request) {
73237331
return ReturnPromiseRejectedWithPendingError(cx, args);
73247332
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/// <reference types="@fastly/js-compute" />
2+
3+
class MyRequest extends Request {
4+
constructor(input: RequestInfo, init?: RequestInit) {
5+
super(input, init);
6+
}
7+
bar() { return 'bar'; }
8+
}
9+
10+
addEventListener("fetch", event => {
11+
const request = new MyRequest('https://www.google.com/');
12+
if (Reflect.getPrototypeOf(request) !== MyRequest.prototype) {
13+
throw new Error(
14+
"Expected `Reflect.getPrototypeOf(request) === MyRequest.prototype` to be `true`, instead found: `false`"
15+
);
16+
}
17+
if ((request instanceof MyRequest) !== true) {
18+
throw new Error(
19+
"Expected `request instanceof MyRequest` to be `true`, instead found: `false`"
20+
);
21+
}
22+
if (Reflect.has(request, "bar") !== true) {
23+
throw new Error(
24+
"Expected `Reflect.has(request, \"bar\")` to be `true`, instead found: `false`"
25+
);
26+
}
27+
if (typeof request.bar !== "function") {
28+
throw new Error(
29+
"Expected `typeof request.bar` to be `function`, instead found: `"+typeof request.bar+"`"
30+
);
31+
}
32+
33+
let response = new Response('');
34+
event.respondWith(response);
35+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# This file describes a Fastly Compute@Edge package. To learn more visit:
2+
# https://developer.fastly.com/reference/fastly-toml/
3+
4+
authors = [""]
5+
description = ""
6+
language = "javascript"
7+
manifest_version = 2
8+
name = "extend-from-request"
9+
service_id = ""

integration-tests/js-compute/sdk-test-config.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,26 @@
308308
}
309309
}
310310
}
311+
},
312+
313+
"extend-from-request" : {
314+
"build": "(cd integration-tests/js-compute && npm install && npm run build:test --test=extend-from-request) && (cd ./integration-tests/js-compute/fixtures/extend-from-request && fastly compute pack --verbose --wasm-binary ./extend-from-request.wasm)",
315+
"fastly_toml_path": "./integration-tests/js-compute/fixtures/extend-from-request/fastly.toml",
316+
"wasm_path": "./integration-tests/js-compute/fixtures/extend-from-request/extend-from-request.wasm",
317+
"pkg_path": "./integration-tests/js-compute/fixtures/extend-from-request/pkg/extend-from-request.tar.gz",
318+
"tests": {
319+
"GET /": {
320+
"environments": ["viceroy"],
321+
"downstream_request": {
322+
"method": "GET",
323+
"pathname": "/"
324+
},
325+
"downstream_response": {
326+
"status": 200,
327+
"body": ""
328+
}
329+
}
330+
}
311331
}
312332

313333
}

0 commit comments

Comments
 (0)