-
Notifications
You must be signed in to change notification settings - Fork 772
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[miniflare] fix: make the magic proxy able to proxy objects containing functions #5670
Conversation
🦋 Changeset detectedLatest commit: 1531565 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
A wrangler prerelease is available for testing. You can install this latest build in your project with: npm install --save-dev https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/9008096780/npm-package-wrangler-5670 You can reference the automatically updated head of this PR with: npm install --save-dev https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/prs/5670/npm-package-wrangler-5670 Or you can use npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/9008096780/npm-package-wrangler-5670 dev path/to/script.js Additional artifacts:npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/9008096780/npm-package-create-cloudflare-5670 --no-auto-update npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/9008096780/npm-package-cloudflare-kv-asset-handler-5670 npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/9008096780/npm-package-miniflare-5670 npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/9008096780/npm-package-cloudflare-pages-shared-5670 npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/9008096780/npm-package-cloudflare-vitest-pool-workers-5670 Note that these links will no longer work once the GitHub Actions artifact expires.
Please ensure constraints are pinned, and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth adding tests that reads non-function properties off an object that also has functions?
yeah that's a good shout, I'll look into adding that 🙂👍 |
.changeset/wet-taxis-share.md
Outdated
"miniflare": patch | ||
--- | ||
|
||
fix: make the magic proxy able to serialize objects containing functions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you make clear that this fix doesn't allow those functions to be callable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that true? JS RPC does allow methods and callback to be called I believe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't JS RPC – it's the miniflare magic proxy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But isn't it using JS RPC under the hood? Perhaps I am misunderstanding.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@petebacondarwin no this is unrelated to JS RPC 🙂, it is using the magic proxy and saving such object on the heap (in workerd) so that they can be referenced later.
JS RPC is implemented in the same sort of way:
workers-sdk/packages/miniflare/src/workers/core/proxy.worker.ts
Lines 55 to 57 in 66bdad0
if(value?.constructor?.name === 'RpcStub') { | |
return false; | |
} |
but one is not necessary related to the other
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@RamIdeas The functions are callable, as you can see from the unit tests below 👇
or am I misunderstanding your comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PS: I've updated the changeset as I can see that serialize
here is not really the right word and can lead to confusion 🙂
(my changes are not actually serializing such objects but allowing us to handle them)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yeah sorry I didn't see any implementation changes so assumed you were simply allowing the object to be serialised whereas before it was prevented from proxying.
Am I right to now think that proxying objects with functions always worked? If so, do we know why we explicitly prevented it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Am I right to now think that proxying objects with functions always worked?
No, they never worked, only the rpc stubs ones but that's because we're specifically handling them ad-hoc
If so, do we know why we explicitly prevented it?
The thing is that with my changes we check if an object contains functions and if so we mark as a non-plain object.
Basically my changes make the !isPlainObject(object)
trigger here:
workers-sdk/packages/miniflare/src/workers/core/proxy.worker.ts
Lines 88 to 93 in c0b057b
if ((type === "Object" && !isPlainObject(value)) || type === "Promise") { | |
const address = this.nextHeapAddress++; | |
this.heap.set(address, value); | |
assert(value !== null); | |
return [address, value?.constructor.name]; | |
} |
making it so that the object doesn't get sent to devalue which would otherwise complain when trying to serialize it (saying that it doesn't know how to serialize functions).
a727ec8
to
05f77a9
Compare
@petebacondarwin I've added a non-function property usage to one of the tests (I was considering adding a test just for this but it felt a bit overkill... 🤔) Please have a look and let me know if you're ok with this 🙏 🙂 |
This PR needs rebasing ("Required Github CI checks have changed for workers-sdk. Please rebase on main to get the required jobs to run") |
36176f7
to
10e714b
Compare
What this PR solves / how to test
This PR makes it so that "magic" proxy objects can contain functions, something that is not currently possible.
To test the changes in this PR you can try this minimal reproduction/example with both the latest version of miniflare and this PR's miniflare prerelease. You can see how the example errors with the former but succeeds with the latter.
Note
This improves the situation but the magic proxy's handling of functions is not yet perfect, for example functions inside arrays (e.g.
return [() => 'Hello']
) still don't work. Also functions returning functions do not work either.In any case I believe that the changes here improve the situation and are unlikely to conflict with any fix for the above points, so I think that it should be safe to proceed with these changes (and address the other points separately).
Author has addressed the following