Closed Bug 22048 Opened 26 years ago Closed 25 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: 26 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: 26 years ago26 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: 26 years ago25 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: