Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
top-level method calls, working
top-level property access, working
chained promise property access, wip
  • Loading branch information
RamIdeas committed Oct 28, 2024
1 parent 51d7d1d commit 1fe06a5
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 59 deletions.
17 changes: 16 additions & 1 deletion fixtures/do-bound/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DurableObject } from "cloudflare:workers";
import { DurableObject, RpcTarget } from "cloudflare:workers";

export class ThingObject extends DurableObject {
fetch(request) {
Expand All @@ -7,9 +7,24 @@ export class ThingObject extends DurableObject {
get property() {
return "property:ping";
}
get prop1() {
return new Deep1();
}
method() {
return "method:ping";
}
}

class Deep1 extends RpcTarget {
get prop2() {
return "deep:prop2";
}
}

// class Deep2 extends RpcTarget {
// get prop3() {
// return "deep property";
// }
// }

export default {}; // Required to treat as modules format worker
7 changes: 6 additions & 1 deletion fixtures/do-bound/wrangler.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@

name = "do-bound"
main = "index.ts"
compatibility_date = "2024-10-28"

[durable_objects]
bindings = [
{ name = "OBJECT", class_name = "ThingObject" }
]
]

[[migrations]]
tag = "v1" # Should be unique for each
new_classes = ["ThingObject"]
8 changes: 8 additions & 0 deletions fixtures/do-entry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ export default {
return Response.json(await stub.property);
}

if (pathname === "/deep-1") {
return Response.json(await stub.prop1.prop2);
}

if (pathname === "/deep-2") {
return Response.json(await stub.prop1.prop2.prop3);
}

return stub.fetch("https://placeholder:9999/", {
method: "POST",
cf: { thing: true },
Expand Down
1 change: 1 addition & 0 deletions fixtures/do-entry/wrangler.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

name = "do-entry"
main = "index.ts"
compatibility_date = "2024-10-28"

[durable_objects]
bindings = [
Expand Down
1 change: 1 addition & 0 deletions fixtures/entrypoints-rpc-tests/tests/entrypoints.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@ test.only("should support binding to Durable Object in another worker", async ({
const { pathname } = new URL(request.url);
if (pathname === "/rpc") {
return Response.json(await stub.property);
return Response.json(await stub.method());
}
Expand Down
165 changes: 108 additions & 57 deletions packages/wrangler/src/dev/miniflare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ import type { Readable } from "node:stream";
const EXTERNAL_SERVICE_WORKER_NAME =
"__WRANGLER_EXTERNAL_DURABLE_OBJECTS_WORKER";
const EXTERNAL_SERVICE_WORKER_SCRIPT = `
import { DurableObject, WorkerEntrypoint } from "cloudflare:workers";
import { DurableObject, WorkerEntrypoint, RpcStub, RpcTarget } from "cloudflare:workers";
const HEADER_URL = "X-Miniflare-Durable-Object-URL";
const HEADER_NAME = "X-Miniflare-Durable-Object-Name";
Expand Down Expand Up @@ -109,63 +109,112 @@ function createDurableObjectClass({ externalBindingName, internalBindingName })
super(ctx, env);
return new Proxy(this, {
get(target, key, receiver) {
const value = Reflect.get(target, key, receiver);
get(target, prop1, receiver) {
console.log('get', { prop1 });
const value = Reflect.get(target, prop1, receiver);
if (value !== undefined) return value;
if (HANDLER_RESERVED_KEYS.has(key)) return;
return env[internalBindingName].proxyProperty({
bindingName: externalBindingName,
doId: ctx.id,
property: key,
});
return new Proxy({}, {
get(_target, key) {
if(key === "then"){
return () => env[internalBindingName].proxyProperty({
bindingName: externalBindingName,
doId: ctx.id,
property: key,
});
}
},
apply(target, thisArg, args) {
return env[internalBindingName].proxyMethod({
bindingName: externalBindingName,
doId: ctx.id,
method: key,
args,
});
},
});
// get:
// "then" returns a function which returns a promise
// optionally "catch" returns a function which returns a promise
// optionally "finally" returns a function which returns a promise
// return recursive proxy
// apply:
// call the method async
// return the promise
// });
// assuming a method
// return (...args) => {
// console.log("about to call proxy method", key )
// return env[internalBindingName].proxyMethod({
// bindingName: externalBindingName,
// doId: ctx.id,
// method: key,
// args,
// });
// }
if (HANDLER_RESERVED_KEYS.has(prop1)) return;
return new Proxy(() => {}, {
get: (target, prop2, receiver) => {
console.log('sub get', { prop2 });
const topLevelPropAccessPromise = env[internalBindingName].proxyProperty({
bindingName: externalBindingName,
doId: ctx.id,
property: prop1,
});
if (prop2 === "then" || prop2 === "catch" || prop2 === "finally") {
return (...args) => topLevelPropAccessPromise[prop2](...args);
}
return new Proxy(() => {}, {
get: (target, prop3, receiver) => {
const subPropAccessPromise = topLevelPropAccessPromise.then(value => {
return value[prop2];
});
if (prop3 === "then" || prop3 === "catch" || prop3 === "finally") {
console.log('subPropAccessPromise then', { prop3 });
return (...args) => subPropAccessPromise[prop3](...args);
}
// return new Proxy(() => {}, {
// get: (target, key, receiver) => {
// if (key === "then" || key === "catch" || key === "finally") {
// return (...args) => subPropAccessPromise[key](...args);
// }
// const subPropAccessPromise = topLevelPropAccessPromise.then(value => {
// return value[key];
// });
// return subPropAccessPromise;
// },
// getPrototypeOf: (target) => {
// console.log('sub getPrototypeOf', { });
// return new RpcTarget();
// },
// getOwnPropertyDescriptor: (target, key) => {
// const x = Reflect.getOwnPropertyDescriptor(target, key);
// console.log('sub getOwnPropertyDescriptor', { key, x });
// return { configurable: true, enumerable: true, value: 5 };
// },
// });
},
getPrototypeOf: (target) => {
console.log('sub getPrototypeOf', { });
return new RpcTarget();
},
getOwnPropertyDescriptor: (target, key) => {
const x = Reflect.getOwnPropertyDescriptor(target, key);
console.log('sub getOwnPropertyDescriptor', { key, x });
return { configurable: true, enumerable: true, value: 5 };
},
});
},
apply(target, thisArg, args) {
console.log('sub apply', { prop1 });
return env[internalBindingName].proxyMethod({
bindingName: externalBindingName,
doId: ctx.id,
method: prop1,
args,
});
},
getPrototypeOf: (target) => {
console.log('sub getPrototypeOf', { });
return new RpcTarget();
},
getOwnPropertyDescriptor: (target, key) => {
const x = Reflect.getOwnPropertyDescriptor(target, key);
console.log('sub getOwnPropertyDescriptor', { key, x });
return { configurable: true, enumerable: true, value: 5 };
},
// traps for all other traps that just console.log
set: (target, key, value, receiver) => {
console.log('sub set', { key, value });
return Reflect.set(target, key, value, receiver);
},
has: (target, key) => {
console.log('sub has', { key });
return Reflect.has(target, key);
},
ownKeys: (target) => {
console.log('sub ownKeys', { });
return Reflect.ownKeys(target);
},
});
}
});
}
Expand Down Expand Up @@ -223,11 +272,13 @@ export class ${EXTERNAL_SERVICE_RECEIVER_NAME} extends __Wrangler__LocalOnly__Wo
const stub = ns.get(ns.idFromString(idString));
return stub.fetch(request, { cf });
}
async proxyMethod({ bindingName, doId, method, args }) {
const ns = this.env[bindingName];
const stub = ns.get(ns.idFromString(doId));
return stub[method](...args);
}
async proxyProperty({ bindingName, doId, property }) {
const ns = this.env[bindingName];
const stub = ns.get(ns.idFromString(doId));
Expand Down

0 comments on commit 1fe06a5

Please sign in to comment.