Closed Bug 417342 Opened 14 years ago Closed 3 years ago

[web compat] Standard global object semantics


(Tamarin Graveyard :: Virtual Machine, enhancement)

Not set


(Not tracked)



(Reporter: lhansen, Unassigned)



We need web-compatible global object semantics.  Please add your thoughts here about what specifically that entails, and how the problem may be addressed.
CCing some people who I think can give useful feedback here...
Duplicate of this bug: 415723
FYI, bug 415723 has some comments from Edwin I pasted from email that might be worth reading for context.
Summarizing a discussion with Edwin today.

These are the features we are looking for.  Assume A and B are independently compiled scripts:

* If script A captures the global as X and script B captures it as Y, X === Y.

* If script A defines a name V by "var" or similar mechanism then V is visible in script B, and vice versa, and V is DontDelete.  (Consider also classes.)

* If script A defines a name V by assignment then V is visible in script A, and vice versa, and V is deletable.

The way Tamarin is currently structured is apparently as follows.

Every script gets a global object all its own, it is an instance of a type that is specific to that object (ie each global is a singleton), and the object has fixtures (traits) for all nondeletable bindings (var, function, class, etc).

Scripts are loaded in order 1..N, and this order informs name lookup in the following way.  Script k looking up global V looks first in script 1, then in script 2, ..., then in its own global object, then all the way down to N, and the first global that has a traits binding gets the hit.  (So if a script tries to override a binding in an earlier script the override is not actually visible to anyone, it's as if it doesn't exist.  Initialization of the override overwrites the original value.)  If the name is not found then script k's global object is hit.

As a consequence of this expandos are always added to script k's global object and are never visible to other scripts.

(Simple experiments with the ESC shell are consistent with that story.)

What we almost certainly want is a single proxy object that sits in front of this sea of global objects and is a container for expandos while it picks up trait bindings from the global objects.  Edwin says there's a proxy like this in the Player but that it might usefully move into Tamarin.

One piece of the puzzle is that it's the proxy object needs to be pushed onto the scope as the global object at the start of each script, not the script's global object.
In tamarin-central, ScriptObject has a bunch of virtual methods: hasProperty, getProperty, callProperty, etc.  If we wanted to write this mega-global-object-proxy in C++, all we have to do is subclass ScriptObject, and put the necessary smarts into those methods.  (if all we needed was the expando then we're done, ScriptObject does that).

flash.utils.Proxy simply exposes those virtual method calls as overrideable AS3 methods, which lets users hook into the same meta-object protocol.  So if we do this is ESC (pure user code), we need Proxy.  

Proxy belongs in the vm code, since it's so tightly coupled to the VM's meta-object protocol.  ES4 has its own designs on the same idea, so Proxy should remain a tamarin-specific thing.
From comment#4
> Scripts are loaded in order 1..N, and this order informs name 
> lookup in the following way.  Script k looking up global V 
> looks first in script 1, then in script 2, ..., then in its 
> own global object, then all the way down to N,
> If the name is not found then script k's
> global object is hit.

It's not particularly relevant, but the above description has k's global object being searched twice.  Also, when stepping through the code, it seems script k looking up global V causes a DomainEnv hashtable to be searched to locate the script defining the name, then that script is handed the object via a slot-set opcode, for example.

Which got me thinking that the ScriptEnv implementation already does much of what we want.  Given a set of scripts, each with its own global, it already "merges" them into a single namespace with variables set in one script available in other scripts.  In other words, we want the 'Window' object to be more like a ScriptEnv than single script global.  A proxy around a ScriptEnv doesn't sound that hard.

But that got me to thinking about 'this' semantics.  For example, (window===this) returns True, but IIUC, in tamarin, |this| refers to the individual script's global.  For example, via ESC:

es> var a = this;print(a===this);
es> print(a===this);

in other words, I don't see how 'window===this' could return True for each individual script (or for *any* script using a proxy).  If we ignore that problem, I can see a proxy working (and it would help me a lot to know how the player proxy works.)  I'll play a little more with this, but in the meantime, is there something here I'm missing?
|this| can mean anything esc wants it to mean; esc can ocmpile |this| as code to fetch that proxy.
This problem causes numerous failures of Tamarin+ESC on the spidermonkey test suite.
Severity: normal → enhancement
Priority: -- → P1
Is there a write-up of what needs to be done in Tamarin? Maybe in bug 415723, it seems. Would be great to put in wikimo and link from this bug's URL.

OS: Windows XP → All
Priority: P1 → --
Hardware: x86 → All
Summary: Web-compatible global object semantics → [web compat] Standard global object semantics
Flags: flashplayer-qrb+
Priority: -- → P3
Target Milestone: --- → Future
Priority: P3 → --
Tamarin is a dead project now. Mass WONTFIX.
Closed: 3 years ago
Resolution: --- → WONTFIX
Tamarin isn't maintained anymore. WONTFIX remaining bugs.
You need to log in before you can comment on or make changes to this bug.