Breaking the grip JS has on the DOM: Difference between revisions

Jump to navigation Jump to search
Updated to reflect current implementation work
No edit summary
(Updated to reflect current implementation work)
Line 19: Line 19:


* No sharing of language namespaces.  Only the "global DOM namespace" (ie, the nsIScriptGlobalObject) will be shared.
* No sharing of language namespaces.  Only the "global DOM namespace" (ie, the nsIScriptGlobalObject) will be shared.
* A nsIScriptGlobalObject will maintain multiple nsIScriptContexts, one for each language supported.  There will be no sharing among nsIScriptContexts - ie, each language is completely independent, sharing only the nsIScriptGlobalObject.


== Identified task list ==
== Identified task list ==
Line 40: Line 42:
nsDOMClassInfo will need a fair bit of work, and significant help from Mozilla resources.  It may be able to be split into a language neutral nsDOMClassInfo, and a JS specific nsIXPCScriptable.  The JS specific code in this file will need to be re-written for Python, but this should allow all DOM knowledge to be reused by the Python implementation.
nsDOMClassInfo will need a fair bit of work, and significant help from Mozilla resources.  It may be able to be split into a language neutral nsDOMClassInfo, and a JS specific nsIXPCScriptable.  The JS specific code in this file will need to be re-written for Python, but this should allow all DOM knowledge to be reused by the Python implementation.


Need to agree on a single "script language ID"nsIProgrammingLanguage defines a set of integers, while nsIScriptElement uses a generic "char *". This document assumes an integer.
nsIProgrammingLanguage constants will identify a language.  Existing occurances of a char * identifying a language or version may also be changed to also use an integer, allowing bitmasks etc.


Below are specific implementation notes:
Below are specific implementation notes:
Line 53: Line 55:


* Existing "void *aScopeObject" (ExecuteScript/EvaluateStringWithValue/CompileScript), replaced with nsIScriptGlobalObject.  The language impl can then get its "void *" via either sgo->GetLanguageContext() or provide a default via its own private means.
* Existing "void *aScopeObject" (ExecuteScript/EvaluateStringWithValue/CompileScript), replaced with nsIScriptGlobalObject.  The language impl can then get its "void *" via either sgo->GetLanguageContext() or provide a default via its own private means.
This may require a helper function to return a (temporary?) nsIScriptGlobalObject for a given JSObject - eg, plugin code, nsXBLProtoImplField::InstallMember.
[actually, the above may be gratuitious and cause unnecessary problems][Actually, XBL has an nsIScriptGlobalObject around when it's installing members; it'd just need to pass it around --[[User:Bzbarsky|Bzbarsky]] 18:55, 15 Aug 2005 (PDT)]


* Need a "WrapNative" type function (or maybe not - this may end up being able to be hidden behind Get/SetProperty functions?
* FinalizeClasses method - JS does the ClearScope/ClearWatchpointsForObject/ClearRegExpStatistics?


* FinalizeClasses method - JS does the ClearScope/ClearWatchpointsForObject/ClearRegExpStatistics?
* nsIArray to be used in place of JSVal argc/argv used now.


* Some kind of "SetProperty" function - as needed by nsGlobalWindow - "arguments", "navigator" etc.  http://lxr.mozilla.org/seamonkey/source/dom/src/base/nsGlobalWindow.cpp#871 [Not sure this is needed. IMO we should make "arguments" be XPCOM objects, i.e. an nsIPropertyBag or whatnot and we'd finally be able to get to the arguments passed to window.open() from *any* language. "navigator" is just a property of a window like all others, except that there's some JS:isms around it that I think we can easily ignore for Python -- jst]
* Maybe some kind of "SetProperty" function - as needed by nsGlobalWindow - "arguments", "navigator" etc.  http://lxr.mozilla.org/seamonkey/source/dom/src/base/nsGlobalWindow.cpp#871 [Not sure this is needed. IMO we should make "arguments" be XPCOM objects, i.e. [nsIArray -- markh] and we'd finally be able to get to the arguments passed to window.open() from *any* language. "navigator" is just a property of a window like all others, except that there's some JS:isms around it that I think we can easily ignore for Python -- jst]


* SetTerminationFunction needs thinking through - this does *not* seem to be a per-language thing.  Maybe could be on the nsIDOMContextStackItem proposed below?  Only few callers though.
* SetTerminationFunction needs thinking through - this does *not* seem to be a per-language thing.  Maybe could be on the nsIDOMContextStackItem proposed below?  Only few callers though.
* New method:
  void *GetNativeGlobal() to return the "global object" used by nsIScriptGlobalWindow (previously stored in mJSObject) for this context.  nsIScriptGlobalObject calls this method during language init to setup its environment.


=== nsIScriptGlobalObject / nsGlobalWindow ===
=== nsIScriptGlobalObject / nsGlobalWindow ===
Line 68: Line 71:
http://lxr.mozilla.org/seamonkey/source/dom/public/nsIScriptGlobalObject.h
http://lxr.mozilla.org/seamonkey/source/dom/public/nsIScriptGlobalObject.h


nsGlobalWindow is the main implemention of nsIScriptGlobalObject, but XUL has one too.
nsGlobalWindow is the main implemention of nsIScriptGlobalObject, but XUL and XBL have a few.


* Still need to understand callers of GetNativeContext - they will not be language neutral
* nsIScriptGlobalObject remains a single object (ie, not per language).  It will keep a list of "nsIScriptContext *ctx, void *global" items, one for each language.  New methods:
 
   nsIScriptContext *GetLanguageContext(PRUint32 lang_id);
* nsIScriptGlobalObject probably needs to remain a single object (ie, not per language).  It will move towards keeping a list of "IScriptContext *ctx, void *global" items, one for each language.  New method:
  void *GetLanguageGlobal(PRUint32 lang_id);
   nsresult GetLanguageContext( [in] language_id language, [out] nsIScriptContext **retLangContext, [out]void **retLangGlobal);
The concept of a single context/global will be deprecated - callers will be encouraged to use the new method.
The concept of a single context/global will be deprecated - callers will be encouraged to use the new method.
GetContext()/GetGlobalJSObject() remain for b/w compat.  They are equivalent to "GetLanguageContext('js', ...)"
GetContext()/GetGlobalJSObject() remain for b/w compat.  They are equivalent to "GetLanguageContext('js', ...)"
SetContext replaced with SetLanguageContext().  New nsIScriptContext::GetNativeGlobal() used to populate the "native global" for each language.


* New method to ensure the nsIScriptGlobal is initialized for a specific language.  This may be called at any time - whenever someone needs to run a script in a language.
* New method to ensure the nsIScriptGlobal is initialized for a specific language.  This may be called at any time - whenever someone needs to run a script in a language.
Line 83: Line 86:
** Properties fetched seem arbitrary.
** Properties fetched seem arbitrary.


* SetNewArguments will need to be specified as an nsISupports.  This trickles down into a number of things, including the concept of "extra args" nsGlobalWindow has.  May need to supply *2* nsISupports.
* SetNewArguments uses nsIArray


* New method to push all current contexts onto the context stack.
* New method to push all current contexts onto the context stack.


* Serializing scripts?
* Serializing scripts and fast-load needs thought.  Python could benefit from caching its compiled "code objects" to avoid parser overhead on each reload.  These "code objects" are just another "PyObject *", so abstracting and delegating fast-load to nsIScriptContext may be possible.


* CompileScript:
* CompileScript - We should consider fixing this:
   nsXulElement.  Line 3666:
   nsXulElement.  Line 3666:
   // XXXbe violate nsIScriptContext layering because its version parameter
   // XXXbe violate nsIScriptContext layering because its version parameter
   // is mis-typed as const char *  
   // is mis-typed as const char *  
   sets mJSObject
    


=== nsDOMClassInfo ===
=== nsDOMClassInfo ===
Note: Work on nsDOMClassInfo could be done by a Mozilla resource in parallel with this other work.  We will not need to use this enhanced class info until we already have Python code being executed and that code trying to work with a "dumb" DOM object.


One radical alternative: Invent a new "nsIDynamicClassInfo" or similar interface that allows the additional class info to be expressed.  Modify the JS XPConnect code to also use that new interface is supported regardless of implementor.  Python's xpcom code would do likewise.  nsIDOMClassInfo is responsible only for implementing this new interface.  It is possible this could also subsume your existing IDispatch support.
nsDOMClassInfo provides 2 key functions:


Notes assuming a less radical evolution of the existing code:
* standard nsIClassInfo implementations for DOM.


Lots of DOM namespace magic happens here, but it is very JS specificWe will try to split the implementation:
* Enhanced type info for DOM which can not be expressed using nsIClassInfoThese are the "scriptable helpers"


* Create ns(I)DOMClassInfoIt contains all the existing code that works with nsDOMClassInfoData - that includes most of the "tables" defined using macros.
The extra nsIClassInfo implementation is suitable for all languagesHowever, the scriptable helpers have lots of DOM namespace magic, and are very JS specific.  Its not clear how much if this is needed for other languages, but presumably some is.  This section discusses only that JS specific magic.


* nsDOMXPC will have all the JS specific code, which is currently implementing nsIXPCScriptable.  This is the bulk of the existing nsDOMClassInfo implementation.
The implementation is now at a point where Python requires this enhanced class info (ie, Python is being called with a DOM object - at the moment it can only use what is reflected in standard nsIClassInfo.


This language neutral interface will allow language "helpers" to be explicitly installed, and will then be able to be fetched by the existing nsIClassInfo::GetLanguageHelper() functionThus, anyone with an nsIDOMClassInfo will still be able to get the JS helper.
Note: Work on nsDOMClassInfo could be done by a Mozilla resource in parallel with this other workWe will not need to use this enhanced class info until we already have Python code being executed and that code trying to work with a "dumb" DOM object.


The Python language implementation will then need to write an equivalent to the new nsDOMXPCThis will be the magic where attributes are got/set for objects, etcThis Python implementation will need to lean heavily on nsDOMClassInfo.
One radical alternative: Invent a new "nsIDynamicClassInfo" or similar interface that allows the additional class info to be expressed.  Modify the JS XPConnect code to also use that new interface is supported regardless of implementor.  Python's xpcom code would do likewisensIDOMClassInfo is responsible only for implementing this new interfaceIt is possible this could also subsume your existing IDispatch support.


Decide what to do with the various flags - eg, ALLOW_PROP_MODS_TO_PROTOTYPE.  Presumably these will have some meaning to languages other than JS, but they are defined in a JS specific interface (nsIXPCScriptable)
It is not clear to MarkH how to make the existing scriptable helpers language agnostic


The following "public" functions are problematic:
=== Context Stack ===
* nsWindowSH::InvalidateGlobalScopePolluter referenced by nsGlobalWindow.
* GC
* oops - lost the other one!


=== Context Stack ===
[MarkH - I've managed to completely ignore this for the time being]


Existing nsIJSContextStack "@mozilla.org/js/xpc/ContextStack;1" service is replaced with language generic ContextStack.  This is almost identical to the JS version, but all operations work for the entire set of languages in use, not just the language about to be executed.
Existing nsIJSContextStack "@mozilla.org/js/xpc/ContextStack;1" service is replaced with language generic ContextStack.  This is almost identical to the JS version, but all operations work for the entire set of languages in use, not just the language about to be executed.
32

edits

Navigation menu