Closed Bug 1269327 Opened 8 years ago Closed 8 years ago

Structured clone does not support Proxy objects

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
normal

Tracking

()

RESOLVED INVALID
Tracking Status
firefox49 --- affected

People

(Reporter: jwkbugzilla, Unassigned)

Details

Attachments

(1 file)

Attached file Minimal test extension
Steps to reproduce:

1. Download attached extension.
2. Go to about:config and set xpinstall.signatures.required to false.
3. Open Add-ons Manager and install the extension from file.
4. Press Ctrl-Shift-J (Cmd-Shift-J on OS X) to open the Browser Console.

Expected results:

The extension reports receiving the object {"regular": {"1": 2}, "proxied": {"3", 4}}. That's what you get in Chrome.

Actual results:

The object {"regular": {"1": 2}} is received. The property "proxied" was dropped because the object stored there is wrapped in a proxy - new Proxy({"3": 4}, {}). Note that this is unexpected as JSON.stringify() doesn't have any issues dealing with that object, passing the data through JSON.parse(JSON.stringify(...)) makes things work correctly.
I think this is intentional behavior. Structured clone has no provisions for proxies, and it's not even clear to me what it should do with them, given that proxy traps can't be attached to the cloned object.
Component: WebExtensions → JavaScript Engine
Product: Toolkit → Core
Summary: Messaging ignores JavaScript objects wrapped in a proxy → Structured clone does not support Proxy objects
IMHO it shouldn't treat them differently from regular objects - just like JSON.stringify() does. In my particular case the purpose of the proxy was being notified when something changes.
Proxies are frankly a pretty odd beast, with many algorithms not seeing through them, e.g. approximately all the non-generic class methods:

js> "".toString.call(new Proxy(new String("foo"), {}))
typein:2:1 TypeError: toString method called on incompatible Proxy
Stack:
  @typein:2:1

..and only some other algorithms seeing through them, like ECMAScript's IsArray operation as used within the JSON.stringify algorithm.

It's not immediately obvious to me that Proxy objects should be "seen through" this way.  What happens if the associated handler object defines custom behaviors (and not necessarily just "now", but *ever* -- every [[Get]] on a proxy, for example, redoes Get(handler, "get") internally)?  What happens if the handler object is *itself* a proxy?  What happens if the proxy object is "seen through" early in the structured clone algorithm, then some step in there revokes the proxy object?  There are a lot of questions to answer here, to do something that might accord with some "intuitions" about what should happen here.

In the meantime, Chrome's behavior is a bug, and the spec clearly says to do what we're doing.  Feel free to file an issue against the spec if you want this changed, ideally carefully describing the behavior of different edge cases that may arise (e.g. in your example, is it really a faithful transfer if someone added, say, Object.prototype.get = function() { ... } that totally changed the meaning of your proxy).  Should the spec change, we'll change accordingly.
Status: NEW → RESOLVED
Closed: 8 years ago
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: