Commit 77d8fc4c authored by ggaren's avatar ggaren

JavaScriptCore:

        Reviewed by Maciej.

        - JSC support for the fix for <rdar://problem/4467143> JavaScript 
        enumeration of HTML element properties skips DOM node properties

        * kjs/lookup.h: 
        (1) Added the KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE macro. The 
        class definiton macro needs to know about the prototype's prototype so 
        that the class constructor properly sets it. 
        (2) Removed the KJS_IMPLEMENT_PROTOTYPE_WITH_PARENT macro. The class
        implementation macro does not need to know about the prototype's
        prototype, since getOwnPropertySlot should only look in the current 
        object's property map, and not its prototype's.

LayoutTests:

        Reviewed by Maciej.

        - Layout test for <rdar://problem/4467143> JavaScript enumeration of 
        HTML element properties skips DOM node properties

        * fast/dom/prototype-chain-expected.txt: Added.
        * fast/dom/prototype-chain.html: Added.

WebCore:

        Reviewed by Maciej.

        - Second cut at fixing <rdar://problem/4467143> JavaScript enumeration 
        of HTML element properties skips DOM node properties
 
        The approach here is for prototypes, in their constructor methods, 
        to set their own prototypes, preserving the prototype 
        chain in cases of multiple levels of inheritance. (Previously, our
        code assumed that a prototype never had a prototype of its own,
        and always used an empty object as a prototype's prototype).

        * bindings/scripts/CodeGeneratorJS.pm: Use the new
        DEFINE_PROTOTYPE_WITH_PROTOTYPE macro in place of the  
        KJS_IMPLEMENT_PROTOTYPE_WITH_PARENT macro.
        * khtml/ecma/kjs_dom.cpp: Ditto.
        * khtml/ecma/kjs_dom.h: Ditto.
        * khtml/ecma/kjs_events.cpp: Ditto.

        Touched these files to force a rebuild:

        * bindings/js/JSDOMCore.cpp:
        * bindings/js/JSDOMEvents.cpp:
        * dom/Attr.idl:
        * dom/CharacterData.idl:
        * dom/DOMImplementation.idl:
        * dom/DocumentType.idl:
        * dom/Element.idl:
        * dom/Entity.idl:
        * dom/MutationEvent.idl:
        * dom/Notation.idl:
        * dom/ProcessingInstruction.idl:
        * dom/Text.idl:
        * dom/WheelEvent.idl:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@13150 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 08191d5b
2006-03-05 Geoffrey Garen <ggaren@apple.com>
Reviewed by Maciej.
- JSC support for the fix for <rdar://problem/4467143> JavaScript
enumeration of HTML element properties skips DOM node properties
* kjs/lookup.h:
(1) Added the KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE macro. The
class definiton macro needs to know about the prototype's prototype so
that the class constructor properly sets it.
(2) Removed the KJS_IMPLEMENT_PROTOTYPE_WITH_PARENT macro. The class
implementation macro does not need to know about the prototype's
prototype, since getOwnPropertySlot should only look in the current
object's property map, and not its prototype's.
2006-03-05 Andrew Wellington <proton@wiretapped.net>
Reviewed by Eric, landed by ap.
......
......@@ -295,7 +295,7 @@ inline KJS::JSObject *cacheGlobalObject(KJS::ExecState *exec, const KJS::Identif
* KJS_IMPLEMENT_PROTOTYPE("DOMNode", DOMNodeProto,DOMNodeProtoFunc)
* and use DOMNodeProto::self(exec) as prototype in the DOMNode constructor.
* If the prototype has a "parent prototype", e.g. DOMElementProto falls back on DOMNodeProto,
* then the last line will use IMPLEMENT_PROTOTYPE_WITH_PARENT, with DOMNodeProto as last argument.
* then the first line will use KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE, with DOMNodeProto as the second argument.
*/
// Work around a bug in GCC 4.1
......@@ -305,6 +305,7 @@ inline KJS::JSObject *cacheGlobalObject(KJS::ExecState *exec, const KJS::Identif
#define KJS_GCC_ROOT_NS_HACK
#endif
// These macros assume that a prototype's only properties are functions
#define KJS_DEFINE_PROTOTYPE(ClassProto) \
class ClassProto : public KJS::JSObject { \
friend KJS::JSObject *KJS_GCC_ROOT_NS_HACK cacheGlobalObject<ClassProto>(KJS::ExecState *exec, const KJS::Identifier &propertyName); \
......@@ -315,22 +316,25 @@ inline KJS::JSObject *cacheGlobalObject(KJS::ExecState *exec, const KJS::Identif
bool getOwnPropertySlot(KJS::ExecState *, const KJS::Identifier&, KJS::PropertySlot&); \
protected: \
ClassProto(KJS::ExecState *exec) \
: JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()) { } \
: KJS::JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()) { } \
\
};
#define KJS_IMPLEMENT_PROTOTYPE(ClassName, ClassProto,ClassFunc) \
const ClassInfo ClassProto::info = { ClassName, 0, &ClassProto##Table, 0 }; \
JSObject *ClassProto::self(ExecState *exec) \
{ \
return ::cacheGlobalObject<ClassProto>(exec, "[[" ClassName ".prototype]]"); \
} \
bool ClassProto::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) \
{ \
return getStaticFunctionSlot<ClassFunc,JSObject>(exec, &ClassProto##Table, this, propertyName, slot); \
}
#define KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(ClassProto, ClassProtoProto) \
class ClassProto : public KJS::JSObject { \
friend KJS::JSObject* KJS_GCC_ROOT_NS_HACK cacheGlobalObject<ClassProto>(KJS::ExecState* exec, const KJS::Identifier& propertyName); \
public: \
static KJS::JSObject* self(KJS::ExecState* exec); \
virtual const KJS::ClassInfo* classInfo() const { return &info; } \
static const KJS::ClassInfo info; \
bool getOwnPropertySlot(KJS::ExecState*, const KJS::Identifier&, KJS::PropertySlot&); \
protected: \
ClassProto(KJS::ExecState* exec) \
: KJS::JSObject(ClassProtoProto::self(exec)) { } \
\
};
#define KJS_IMPLEMENT_PROTOTYPE_WITH_PARENT(ClassName, ClassProto,ClassFunc,ParentProto) \
#define KJS_IMPLEMENT_PROTOTYPE(ClassName, ClassProto, ClassFunc) \
const ClassInfo ClassProto::info = { ClassName, 0, &ClassProto##Table, 0 }; \
JSObject *ClassProto::self(ExecState *exec) \
{ \
......@@ -338,9 +342,7 @@ inline KJS::JSObject *cacheGlobalObject(KJS::ExecState *exec, const KJS::Identif
} \
bool ClassProto::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) \
{ \
if (getStaticFunctionSlot<ClassFunc,JSObject>(exec, &ClassProto##Table, this, propertyName, slot)) \
return true; \
return ParentProto::self(exec)->getOwnPropertySlot(exec, propertyName, slot); \
return getStaticFunctionSlot<ClassFunc, JSObject>(exec, &ClassProto##Table, this, propertyName, slot); \
}
#define KJS_IMPLEMENT_PROTOFUNC(ClassFunc) \
......
2006-03-05 Geoffrey Garen <ggaren@apple.com>
Reviewed by Maciej.
- Layout test for <rdar://problem/4467143> JavaScript enumeration of
HTML element properties skips DOM node properties
* fast/dom/prototype-chain-expected.txt: Added.
* fast/dom/prototype-chain.html: Added.
2006-03-05 Alexander Kellett <lypanov@kde.org>
Reviewed by Eric.
......
This page prints out the prototype chains of select DOM objects. Older versions of WebCore didn't properly implement prototype chaining for these objects.
NOTE: This test will start failing if you change the layout of a related prototype chain in WebCore. That does not necessarily mean that you have done something wrong; you may just need to check in new results.
----- [object HTMLDocument] (3 prototypes) -----
[object Object]
[object DOMNode]
[object DOMDocument]
----- [object DIV] (4 prototypes) -----
[object Object]
[object DOMNode]
[object DOMElement]
[object Element]
----- [object UIEvent] (3 prototypes) -----
[object Object]
[object DOMEvent]
[object DOMUIEvent]
----- [object MouseEvent] (4 prototypes) -----
[object Object]
[object DOMEvent]
[object DOMUIEvent]
[object DOMMouseEvent]
----- [object KeyboardEvent] (4 prototypes) -----
[object Object]
[object DOMEvent]
[object DOMUIEvent]
[object DOMKeyboardEvent]
<html>
<head>
<script>
function print(message, color) {
var paragraph = document.createElement("p");
if (color)
paragraph.style.color = color;
paragraph.appendChild(document.createTextNode(message));
document.getElementById("console").appendChild(paragraph);
}
function printPrototypes(e)
{
var a = new Array();
for (p = e.__proto__; p != null; p = p.__proto__) {
a.push(p);
}
print("----- " + e + " (" + a.length + " prototypes) -----", "blue");
// Print back-to-front so the root of the chain comes out on top
for (var i = a.length - 1; i >= 0; i--) { /* > */
print(a[i]);
}
}
function test()
{
if (window.layoutTestController)
layoutTestController.dumpAsText();
var e;
e = document;
printPrototypes(e);
e = document.getElementById("div");
printPrototypes(e);
e = document.createEvent("UIEvents");
printPrototypes(e);
e = document.createEvent("MouseEvents");
printPrototypes(e);
e = document.createEvent("KeyboardEvents");
printPrototypes(e);
}
</script>
</head>
<body onload="test()">
<p>This page prints out the prototype chains of select DOM objects. Older versions of WebCore didn't
properly implement prototype chaining for these objects.</p>
<p>NOTE: This test will start failing if you change the layout of a related prototype chain in WebCore.
That does not necessarily mean that you have done something wrong; you may just need to check in new
results.</p>
<hr>
<div id="console"></div>
<div id="div"></div>
</body>
</html>
2006-03-05 Geoffrey Garen <ggaren@apple.com>
Reviewed by Maciej.
- Second cut at fixing <rdar://problem/4467143> JavaScript enumeration
of HTML element properties skips DOM node properties
The approach here is for prototypes, in their constructor methods,
to set their own prototypes, preserving the prototype
chain in cases of multiple levels of inheritance. (Previously, our
code assumed that a prototype never had a prototype of its own,
and always used an empty object as a prototype's prototype).
* bindings/scripts/CodeGeneratorJS.pm: Use the new
DEFINE_PROTOTYPE_WITH_PROTOTYPE macro in place of the
KJS_IMPLEMENT_PROTOTYPE_WITH_PARENT macro.
* khtml/ecma/kjs_dom.cpp: Ditto.
* khtml/ecma/kjs_dom.h: Ditto.
* khtml/ecma/kjs_events.cpp: Ditto.
Touched these files to force a rebuild:
* bindings/js/JSDOMCore.cpp:
* bindings/js/JSDOMEvents.cpp:
* dom/Attr.idl:
* dom/CharacterData.idl:
* dom/DOMImplementation.idl:
* dom/DocumentType.idl:
* dom/Element.idl:
* dom/Entity.idl:
* dom/MutationEvent.idl:
* dom/Notation.idl:
* dom/ProcessingInstruction.idl:
* dom/Text.idl:
* dom/WheelEvent.idl:
2006-03-05 Maciej Stachowiak <mjs@apple.com>
Reviewed by Darin.
......
......@@ -11,3 +11,4 @@
#include "JSNotation.cpp"
#include "JSProcessingInstruction.cpp"
#include "JSText.cpp"
......@@ -4,3 +4,4 @@
#include "JSMutationEvent.cpp"
#include "JSWheelEvent.cpp"
......@@ -368,8 +368,12 @@ sub GenerateHeader
push(@headerContent, "};\n\n");
# Add prototype declaration
if ($numFunctions > 0) {
push(@headerContent, "KJS_DEFINE_PROTOTYPE(${className}Proto);\n\n");
if ($numFunctions > 0) {
if ($hasParent) {
push(@headerContent, "KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(${className}Proto, ${parentClassName}Proto);\n\n");
} else {
push(@headerContent, "KJS_DEFINE_PROTOTYPE(${className}Proto);\n\n");
}
}
push(@headerContent, "}\n\n#endif\n");
......@@ -513,14 +517,7 @@ sub GenerateImplementation
\@hashSpecials, \@hashParameters);
push(@implContent, "KJS_IMPLEMENT_PROTOFUNC(${className}ProtoFunc)\n");
if ($hasParent) {
push(@implContent, "KJS_IMPLEMENT_PROTOTYPE_WITH_PARENT(\"$interfaceName\", " .
"${className}Proto, ${className}ProtoFunc, ${parentClassName}Proto)\n\n");
} else {
push(@implContent, "KJS_IMPLEMENT_PROTOTYPE(\"$className\", ${className}Proto, ${className}ProtoFunc)\n\n");
}
push(@implContent, "KJS_IMPLEMENT_PROTOTYPE(\"$className\", ${className}Proto, ${className}ProtoFunc)\n\n");
}
# - Initialize static ClassInfo object
......
......@@ -10,3 +10,4 @@ module core {
readonly attribute CSSStyleDeclaration style;
};
}
......@@ -27,3 +27,4 @@ module core {
};
}
......@@ -21,3 +21,4 @@ module core {
HTMLDocument createHTMLDocument(in DOMString title);
};
}
......@@ -9,3 +9,4 @@ module core {
readonly attribute [ConvertNullStringTo=Null] DOMString internalSubset;
};
}
......@@ -61,3 +61,4 @@ module core {
};
}
......@@ -5,3 +5,4 @@ module core {
readonly attribute [ConvertNullStringTo=Null] DOMString notationName;
};
}
......@@ -20,3 +20,4 @@ module events {
in unsigned short attrChangeArg);
};
}
......@@ -4,3 +4,4 @@ module core {
readonly attribute [ConvertNullStringTo=Null] DOMString systemId;
};
}
......@@ -6,3 +6,4 @@ module core {
readonly attribute StyleSheet sheet;
};
}
......@@ -5,3 +5,4 @@ module core {
raises (DOMException);
};
}
......@@ -18,3 +18,4 @@ module events {
};
}
......@@ -833,9 +833,9 @@ AttrImpl *toAttr(JSValue *val)
queryCommandValue DOMDocument::QueryCommandValue DontDelete|Function 1
@end
*/
KJS_DEFINE_PROTOTYPE(DOMDocumentProto)
KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMDocumentProto, DOMNodeProto)
KJS_IMPLEMENT_PROTOFUNC(DOMDocumentProtoFunc)
KJS_IMPLEMENT_PROTOTYPE_WITH_PARENT("DOMDocument", DOMDocumentProto, DOMDocumentProtoFunc, DOMNodeProto)
KJS_IMPLEMENT_PROTOTYPE("DOMDocument", DOMDocumentProto, DOMDocumentProtoFunc)
const ClassInfo DOMDocument::info = { "Document", &DOMNode::info, &DOMDocumentTable, 0 };
......@@ -1059,7 +1059,7 @@ JSValue *DOMDocumentProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj
@end
*/
KJS_IMPLEMENT_PROTOFUNC(DOMElementProtoFunc)
KJS_IMPLEMENT_PROTOTYPE_WITH_PARENT("DOMElement",DOMElementProto,DOMElementProtoFunc,DOMNodeProto)
KJS_IMPLEMENT_PROTOTYPE("DOMElement", DOMElementProto, DOMElementProtoFunc)
const ClassInfo DOMElement::info = { "Element", &DOMNode::info, &DOMElementTable, 0 };
/* Source for DOMElementTable. Use "make hashtables" to regenerate.
......
......@@ -145,7 +145,7 @@ namespace KJS {
DOM::AttrImpl *toAttr(JSValue *); // returns 0 if passed-in value is not a DOMAttr object
KJS_DEFINE_PROTOTYPE(DOMElementProto)
KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMElementProto, DOMNodeProto)
class DOMElement : public DOMNode {
public:
......
......@@ -565,9 +565,9 @@ const ClassInfo DOMUIEvent::info = { "UIEvent", &DOMEvent::info, &DOMUIEventTabl
initUIEvent DOMUIEvent::InitUIEvent DontDelete|Function 5
@end
*/
KJS_DEFINE_PROTOTYPE(DOMUIEventProto)
KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMUIEventProto, DOMEventProto)
KJS_IMPLEMENT_PROTOFUNC(DOMUIEventProtoFunc)
KJS_IMPLEMENT_PROTOTYPE_WITH_PARENT("DOMUIEvent",DOMUIEventProto,DOMUIEventProtoFunc,DOMEventProto)
KJS_IMPLEMENT_PROTOTYPE("DOMUIEvent", DOMUIEventProto, DOMUIEventProtoFunc)
DOMUIEvent::DOMUIEvent(ExecState *exec, UIEventImpl *e)
: DOMEvent(exec, e)
......@@ -651,9 +651,9 @@ const ClassInfo DOMMouseEvent::info = { "MouseEvent", &DOMUIEvent::info, &DOMMou
initMouseEvent DOMMouseEvent::InitMouseEvent DontDelete|Function 15
@end
*/
KJS_DEFINE_PROTOTYPE(DOMMouseEventProto)
KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMMouseEventProto, DOMUIEventProto)
KJS_IMPLEMENT_PROTOFUNC(DOMMouseEventProtoFunc)
KJS_IMPLEMENT_PROTOTYPE_WITH_PARENT("DOMMouseEvent",DOMMouseEventProto,DOMMouseEventProtoFunc,DOMUIEventProto)
KJS_IMPLEMENT_PROTOTYPE("DOMMouseEvent", DOMMouseEventProto, DOMMouseEventProtoFunc)
DOMMouseEvent::DOMMouseEvent(ExecState *exec, MouseEventImpl *e)
: DOMUIEvent(exec, e)
......@@ -752,9 +752,9 @@ const ClassInfo DOMKeyboardEvent::info = { "KeyboardEvent", &DOMUIEvent::info, &
initKeyboardEvent DOMKeyboardEvent::InitKeyboardEvent DontDelete|Function 11
@end
*/
KJS_DEFINE_PROTOTYPE(DOMKeyboardEventProto)
KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMKeyboardEventProto, DOMUIEventProto)
KJS_IMPLEMENT_PROTOFUNC(DOMKeyboardEventProtoFunc)
KJS_IMPLEMENT_PROTOTYPE_WITH_PARENT("DOMKeyboardEvent", DOMKeyboardEventProto, DOMKeyboardEventProtoFunc, DOMUIEventProto)
KJS_IMPLEMENT_PROTOTYPE("DOMKeyboardEvent", DOMKeyboardEventProto, DOMKeyboardEventProtoFunc)
DOMKeyboardEvent::DOMKeyboardEvent(ExecState *exec, KeyboardEventImpl *e)
: DOMUIEvent(exec, e)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment