Closed Bug 22048 Opened 25 years ago Closed 24 years ago

XUL brutal sharing needs super-prototype love

Categories

(Core :: JavaScript Engine, defect, P1)

All
Windows NT
defect

Tracking

()

RESOLVED FIXED

People

(Reporter: mcafee, Assigned: brendan)

Details

(Keywords: js1.5)

Attachments

(5 files)

Got a JS emoticon error this morning,
input text field stopped accepting input and
I had to quit the app.  Not sure how I did this,
if you need more info I can research the problem more.
Status: NEW → ASSIGNED
Component: XPApps → chatzilla
Summary: IRC: JS emoticon error → IRC: JS emoticon error
(changing component to chatzilla)

Was the message something like "emoticon.search has no properties" around line
193 in test-static.js?

afaik, that's the only place in the code it's actually referred to as an
"emoticon".  This patch *should* prevent the hard error, but I've got no idea
how it actually occurs.  I'll check this in when the tree opens.

Index: munger.js
===================================================================
RCS file: /cvsroot/mozilla/extensions/irc/xul/lib/munger.js,v
retrieving revision 1.1
diff -u -r1.1 munger.js
--- munger.js   1999/11/29 03:57:33     1.1
+++ munger.js   1999/12/17 21:38:10
@@ -64,7 +64,7 @@
         else
             ary = text.match(this.entries[entry].regex);

-        if (ary != null)
+        if ((ary != null) && (ary[1]))
         {
             var startPos = text.indexOf(ary[1]);
yes, the error looked like that.
Didn't know about chatzilla component, nice!
Status: ASSIGNED → RESOLVED
Closed: 25 years ago
Resolution: --- → DUPLICATE
this seems to be cause by the sharing bug secribed in bug 22098

*** This bug has been marked as a duplicate of 22098 ***
Status: RESOLVED → REOPENED
THis
Assignee: rginda → brendan
Status: REOPENED → NEW
Status: NEW → ASSIGNED
Resolution: DUPLICATE → ---
Priority: P3 → P1
Er, that is to say: this is a distinct bug from 22098 -- see my comment with two
alternative fixes in bug 22098 for more.

/be
Target Milestone: M13
Summary: IRC: JS emoticon error → JS compiler-looks-up-RegExp bug exposed by brutal sharing in XUL
Summary: JS compiler-looks-up-RegExp bug exposed by brutal sharing in XUL → JS compiler-looks-up-RegExp bug exposed by XUL brutal sharing
Summary: JS compiler-looks-up-RegExp bug exposed by XUL brutal sharing → JS compiler-looks-up-RegExp (exposed by XUL brutal sharing)
The real patch to make chatzilla work is:

Index: test3-static.js
===================================================================
RCS file: /cvsroot/mozilla/extensions/irc/xul/tests/test3-static.js,v
retrieving revision 1.11
@@ -131,7 +132,8 @@
                                "event-tracer", true /* negate */,
                                false /* disable */);

-    obj.munger = new CMunger();
+    obj.munger = new CMunger();
+    /*
     obj.munger.addRule ("you-talking-to-me?", matchMyNick, "");
     obj.munger.addRule
         ("link", /((http|mailto|ftp)\:\/\/[^\)\s]*|www\.\S+\.\S[^\)\s]*)/,
@@ -140,13 +142,14 @@
         ("face",

/((^|\s)[\<\>]?[\;\=\:\8]\~?[\-\^\v]?[\)\|\(pP\<\>oO0\[\]\/\\](\s|$))/,
          insertSmiley);
-    obj.munger.addRule ("rheet", /(rhe+t\!*)/i, "rheet");
+    obj.munger.addRule ("rheet", /(rhee+t\!*)/i, "rheet");
     obj.munger.addRule ("bold", /(\*.*\*)/, "bold");
     obj.munger.addRule ("italic", /[^sS](\/.*\/)/, "italic");
     obj.munger.addRule ("teletype", /(\|.*\|)/, "teletype");
     obj.munger.addRule ("underline", /(\_.*\_)/, "underline");
     //obj.munger.addRule ("strikethrough", /(\-.*\-)/, "strikethrough");
     obj.munger.addRule ("smallcap", /(\#.*\#)/, "smallcap");
+    */

 }
Keywords: js1.5
OS: other → All
Hardware: Other → All
I'm going with my solution #1: Call JS_InitStandardClasses(cx) in the XUL code
that makes this "prototype global" object against which XUL scripts are
compiled."  Auto-cloning RegExp objects created by the JS compiler for literal
regular expressions imposes too much overhead on compile/exec evaluation (where
there is no brutal compile early, exec later in multiple contexts, sharing).

Patch coming up.

/be
Patch fixes both bugs.
Status: ASSIGNED → RESOLVED
Closed: 25 years ago25 years ago
Resolution: --- → FIXED
Fixed in rdf/content/src/nsXULPrototypeDocument.cpp.

/be
This is still showing up in the WinNT builds.
/foo/ instanceof RegExp fails in windows, works as expected in linux debug and
opt.
Status: RESOLVED → REOPENED
Component: chatzilla → Javascript Engine
OS: All → Windows NT
not sure who is JS qa, trying prashant
QA Contact: paulmac → desale
Clearing FIXED resolution due to reopen.  Setting QA Contact to rginda
QA Contact: desale → rginda
Resolution: FIXED → ---
Not an M13 stopper.  The problem is no longer that /hi/.test is not defined -- we 

fixed that.  Now the problem is that /hi/ instanceof RegExp is false in XUL 

windows because brutal sharing uses a secret global object to scope the 

compilation of /hi/, and then at runtime uses a DOM XUL window to scope the right 

operand, RegExp.  We've broken prototype identity, yay!



This can be fixed in M14, either by sharing one set of standard classes among all 

XUL windows, or by two-layer prototype hierarchy.



/be

Status: REOPENED → ASSIGNED
Target Milestone: M13 → M14
Summary: JS compiler-looks-up-RegExp (exposed by XUL brutal sharing) → XUL brutal sharing needs super-prototype love
uuh, ignore that attachment.  Wrong bug.
Argh, two-layer prototype hierarchy is impossible: say you have a XUL window, x, 
and the prototype document d.  Then if you make

d.Object.prototype === x.Object.prototype.__proto__

you can't arrange for

(new x.RegExp("hi")) instanceof x.Object

because JS supports only a single prototype per object 
(x.RegExp.prototype.__proto__ === x.RegExp.prototype, and 
x.RegExp.prototype.__proto__ === x.Object.prototype, and 
x.Object.prototype.__proto__ === null, but there cannot be any 
x.Object.prototype along that chain).

So we're left with one set of standard classes for all XUL windows.  This is 
certainly faster, too.  It requires changing the DOM code in nsGlobalWindow.cpp 
so that ::JS_InitStandardClasses is not always called.  For XUL windows, I think 
we want to clone each standard class constructor function; non-constructors such 
as Math we can share by reference.  We need constructor clones so that instances 
get parented by their particular XUL windows, not by the hidden XUL prototype 
document script object used for compilation.  Hope this is clear enough!

I'll hack up a patch to extend the JS API with JS_CloneStandardClasses.

/be
Assignee: brendan → waterson
Status: ASSIGNED → NEW
Remember, all XUL cometh not from the same security domain. We can load XUL
files just like regular content. So this may require some cleverness in the code
that is init-ing standard classes to determine whether it can share or not.
Status: NEW → ASSIGNED
moving to M15 because i am doomed.
Target Milestone: M14 → M15
I'd go further: XUL loaded from untrusted domains (not from the unified, 
singular domain of chrome:) should not brutally share the prototype document's 
script object for compile-time constructors (Function, RegExp).  Can we have a 
per-origin compile-time scope object?  That would seem to preserve the identity 
relations we crave, without compromising security.

/be
I'm a dumbass, typos messed up my example (note d for x everywhere after the 
first ==='s left operand):

(x.RegExp.prototype.__proto__ === d.RegExp.prototype, and 
d.RegExp.prototype.__proto__ === d.Object.prototype, and 
d.Object.prototype.__proto__ === null, but there cannot be any 
x.Object.prototype along that chain).

Anyway, same punchline: no "MI" or multiple prototype delegation a la Self in 
JS, wahhh.

/be
I promised a JS_CloneStandardObjects patch, but thinking about it more, I bet we 
can do even better, in terms of per-XUL-window set-new-document cost.

Instead of cloning a bunch of constructors, some of which may never be called, 
we should specialize the XUL window resolve hook (JSClass.resolve, or perhaps 
better: nsIJSScriptObject::Resolve) to look for undefined properties named by 
XUL scripts in the prototype document's script object.  If a property of the 
same name is found there, check its type (JS_TypeOfValue).  If JSTYPE_FUNCTION, 
then JS_CloneFunctionObject and JS_DefineProperty; else just JS_DefineProperty 
to share the value.

Waterson, I may cough up a patch for this if it'll help you.  I probably won't 
do the work in dom/src/base to avoid calling ::JS_InitStandardClasses, or the 
work to make a per-trust-domain locus of compilation scope and standard classes.

/be
OK, I don't think this is a js1.5 bug any more (although I still question the 
special case whereby e instanceof Exception is true no matter which 
Exception.prototype e delegates to, in a world of multiple top-level objects and 
their standard classes (including Exception)).

/be
Keywords: js1.5
brendan: backatcha.
Assignee: waterson → brendan
Status: ASSIGNED → NEW
Target Milestone: M15 → M16
I'm actually interested in revamping the context-universal e instanceof 
SyntaxError (e.g.) behavior, generalizing it so that instanceof works for brutal 
sharing embeddings of JS too.  Also, the way jsfun.c and jsexn.c conspire to 
implement this (js_exnHasInstance) seems flimsy, or hokey, or something -- but I 
haven't spent the time to think of a general way.  I'll do that now.

/be
Status: NEW → ASSIGNED
Keywords: js1.5
Target Milestone: M16 → M15
Read the -wu diffs for best code-buddying results.  Note also that I'm checking
in the fix for http://bugzilla.mozilla.org/show_bug.cgi?id=33391 (included in
jsfun.c).

/be
Looking for some r= love tonight (M15 deadline).

/be
Attached file minimal xul testcase
js engine passes all tests, mozilla passes testcase.
Adding jband.

/be
r=jband
Thanks to jband's review, I fixed the #undef WRAP_EXCEPTION to be #undef
MAKE_EXCEPTION_CTOR, and I squished a warning by making the sentinel initializer
at the end of the exceptions table be {0,0,NULL} rather than {0,0}.

/be
Fixed, thanks to jband, mccabe, and rginda.

/be
Status: ASSIGNED → RESOLVED
Closed: 25 years ago24 years ago
Resolution: --- → FIXED
This patch is an improvement for native objects, but I'm not sure it's as
general as it could be for user-defined functions.

With a little dredging, I remembered the original problem with using the
'constructor' property to implement.  (Apologies to Brendan, if this is what you
showed me on John's whiteboard.)  This objection applies to user-generated
functions, might apply to brutal-shared functions, and doesn't apply to
builtins.

The constructor property is a property of the initial, default .prototype
property of newly generated user functions.  In general, user-generated function
hierarchies are built by assinging to function .prototype properties.  This
overwrites the .constructor information, so it can't be used to test whether an
object was built by a given function.


Function A() {}
// A gets .prototype property, and .prototype.constructor === A

Function B() {}
// ditto

// Make A instances get behavior from B.prototype
A.prototype = new B // overwrites A.prototype.constructor
a = new A(); // a.__proto__ === B.prototype
a.__proto__.constructor === B // !

a instanceof A
a instanceof B

In the single-window case, these expressions are both true, by the
prototype-chasing hasInstance.  Is the first expression true in the
brutal-sharing case?  Does the question even come up, for brutally-shared
user-defined functions?
Good point, the first expression (a instanceof A) is false in the brutal sharing 
case, unless you add A.prototype.constructor = A; after A.prototype = new B.

The (a.__proto__.constructor === B) invariant that you commented with // ! has 
always been an anomaly in this kind of JS, brutal sharing or no brutal sharing. 
I mean, we just constructed a via (new A), so you'd think a's constructor was A, 
eh? [sorry]  OTOH, A.prototype was set to a (new B), and all instances of B 

I remember this coming up in the ancient days, 3.0 or so, and I advised folks 
then to set A.prototype.constructor = A after setting A.prototype = new B.  This 
is exactly what the JS engine does (js_SetClassPrototype) for natives: when you 
set constructor.prototype, you set .prototype.constructor to point back.  So, is 
this policy good enough (if documented -- help me, rginda!) to close the bug?

/be
Oops, didn't finish editing that last sentence of paragraph 2: "OTOH, 
A.prototype was set to a (new B), and all instances of B " should have read 
"OTOH, A.prototype was set to an instance of B (new B), whose constructor is 
naturally enough B."

Notice that any brutal sharer may set A.prototype.constructor = A, even though 
each sharer gets its own function-object clone for A.  Brutal sharing means that 
either all the function objects (clone-parent when brutally-shared source was 
loaded; clones for each sharing "context") have the same native function 
pointer, or they all have the same shared JSScript.  Brutal sharing thus reduces 
JS-compiled scripts to equivalence in number and shared-ness with C or C++ 
compiled native functions.

/be
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: