From 978dc9c3c2d8352afac800a2953e78f29153109c Mon Sep 17 00:00:00 2001 From: zhangjipeng Date: Tue, 15 Oct 2024 20:37:27 +0800 Subject: [PATCH] update mark call --- src/webcore/bindings/qjs/QJSEventTargetNode.h | 66 +++++++ src/webcore/bindings/qjs/qjs_binding.h | 181 ++++++++++++++++++ .../bindings/scripts/CodeGeneratorQJS.pm | 77 +++++--- 3 files changed, 297 insertions(+), 27 deletions(-) create mode 100644 src/webcore/bindings/qjs/QJSEventTargetNode.h create mode 100644 src/webcore/bindings/qjs/qjs_binding.h diff --git a/src/webcore/bindings/qjs/QJSEventTargetNode.h b/src/webcore/bindings/qjs/QJSEventTargetNode.h new file mode 100644 index 0000000..a365836 --- /dev/null +++ b/src/webcore/bindings/qjs/QJSEventTargetNode.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSEventTargetNode_h +#define JSEventTargetNode_h + +#include "QJSNode.h" + +namespace WebCore { + + class EventTargetNode; + class Node; + + class JSEventTargetNode : public JSNode { + public: + JSEventTargetNode(KJS::ExecState*, Node* n); + + void setListener(KJS::ExecState*, const AtomicString& eventType, KJS::JSValue* func) const; + KJS::JSValue* getListener(const AtomicString& eventType) const; + virtual void pushEventHandlerScope(KJS::ExecState*, KJS::ScopeChain&) const; + + bool getOwnPropertySlot(KJS::ExecState*, const KJS::Identifier&, KJS::PropertySlot&); + KJS::JSValue* getValueProperty(KJS::ExecState*, int token) const; + virtual void put(KJS::ExecState*, const KJS::Identifier&, KJS::JSValue* value, int attr); + void putValueProperty(KJS::ExecState*, int token, KJS::JSValue* value, int attr); + + enum { + AddEventListener, RemoveEventListener, DispatchEvent, + OnAbort, OnBlur, OnChange, OnClick, OnContextMenu, OnDblClick, OnError, + OnDragEnter, OnDragOver, OnDragLeave, OnDrop, OnDragStart, OnDrag, OnDragEnd, + OnBeforeCut, OnCut, OnBeforeCopy, OnCopy, OnBeforePaste, OnPaste, OnSelectStart, + OnFocus, OnInput, OnKeyDown, OnKeyPress, OnKeyUp, OnLoad, OnMouseDown, + OnMouseMove, OnMouseOut, OnMouseOver, OnMouseUp, OnMouseWheel, OnReset, + OnResize, OnScroll, OnSearch, OnSelect, OnSubmit, OnUnload + }; + }; + + EventTargetNode* toEventTargetNode(KJS::JSValue*); + + KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(JSEventTargetNodePrototype, JSNodePrototype) + +} // namespace WebCore + +#endif // JSEventTargetNode_h diff --git a/src/webcore/bindings/qjs/qjs_binding.h b/src/webcore/bindings/qjs/qjs_binding.h new file mode 100644 index 0000000..84b32d2 --- /dev/null +++ b/src/webcore/bindings/qjs/qjs_binding.h @@ -0,0 +1,181 @@ +// -*- c-basic-offset: 4 -*- +/* + * This file is part of the KDE libraries + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. + * Copyright (C) 2007 Samuel Weinig + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef kjs_binding_h +#define kjs_binding_h + +#include +#include +#include + +#include + + +namespace WebCore { + class AtomicString; + class Document; + class Event; + class Frame; + class Node; + class String; + class JSNode; + + typedef int ExceptionCode; + +#if ENABLE(SVG) + class SVGElement; +#endif +} + +namespace KJS { + + /** + * Base class for all objects in this binding. + */ + class DOMObject : public JSObject { + protected: + DOMObject() + { + // DOMObject destruction is not thread-safe because DOMObjects wrap + // unsafe WebCore DOM data structures. + Collector::collectOnMainThreadOnly(this); + } +#ifndef NDEBUG + virtual ~DOMObject(); +#endif + }; + + /** + * We inherit from Interpreter, to save a pointer to the HTML part + * that the interpreter runs for. + * The interpreter also stores the DOM object -> KJS::DOMObject cache. + */ + class ScriptInterpreter : public Interpreter { + public: + ScriptInterpreter(JSObject* global, WebCore::Frame*); + + static DOMObject* getDOMObject(void* objectHandle); + static void putDOMObject(void* objectHandle, DOMObject*); + static void forgetDOMObject(void* objectHandle); + + static WebCore::JSNode* getDOMNodeForDocument(WebCore::Document*, WebCore::Node*); + static void putDOMNodeForDocument(WebCore::Document*, WebCore::Node*, WebCore::JSNode* nodeWrapper); + static void forgetDOMNodeForDocument(WebCore::Document*, WebCore::Node*); + static void forgetAllDOMNodesForDocument(WebCore::Document*); + static void updateDOMNodeDocument(WebCore::Node*, WebCore::Document* oldDoc, WebCore::Document* newDoc); + static void markDOMNodesForDocument(WebCore::Document*); + + WebCore::Frame* frame() const { return m_frame; } + + /** + * Set the event that is triggering the execution of a script, if any + */ + void setCurrentEvent(WebCore::Event* event) { m_currentEvent = event; } + void setInlineCode(bool inlineCode) { m_inlineCode = inlineCode; } + void setProcessingTimerCallback(bool timerCallback) { m_timerCallback = timerCallback; } + + /** + * "Smart" window.open policy + */ + bool wasRunByUserGesture() const; + + virtual ExecState* globalExec(); + + WebCore::Event* getCurrentEvent() const { return m_currentEvent; } + + virtual bool isGlobalObject(JSValue*); + virtual Interpreter* interpreterForGlobalObject(const JSValue*); + virtual bool isSafeScript(const Interpreter* target); + + virtual bool shouldInterruptScript() const; + + private: + virtual ~ScriptInterpreter() { } // only deref on the base class should delete us + + WebCore::Frame* m_frame; + WebCore::Event* m_currentEvent; + bool m_inlineCode; + bool m_timerCallback; + }; + + /** + * Retrieve from cache, or create, a KJS object around a DOM object + */ + template inline JSValue *cacheDOMObject(ExecState* exec, DOMObj* domObj) + { + if (!domObj) + return jsNull(); + ScriptInterpreter* interp = static_cast(exec->dynamicInterpreter()); + if (DOMObject* ret = interp->getDOMObject(domObj)) + return ret; + DOMObject* ret = new KJSDOMObj(exec, domObj); + interp->putDOMObject(domObj, ret); + return ret; + } + +#if ENABLE(SVG) + /** + * Retrieve from cache, or create, a KJS object around a SVG DOM object + */ + template inline JSValue* cacheSVGDOMObject(ExecState* exec, DOMObj* domObj, WebCore::SVGElement* context) + { + if (!domObj) + return jsNull(); + ScriptInterpreter* interp = static_cast(exec->dynamicInterpreter()); + if (DOMObject* ret = interp->getDOMObject(domObj)) + return ret; + DOMObject* ret = new KJSDOMObj(exec, domObj, context); + interp->putDOMObject(domObj, ret); + return ret; + } +#endif + + // Convert a DOM implementation exception code into a JavaScript exception in the execution state. + void setDOMException(ExecState*, WebCore::ExceptionCode); + + // Helper class to call setDOMException on exit without adding lots of separate calls to that function. + class DOMExceptionTranslator : Noncopyable { + public: + explicit DOMExceptionTranslator(ExecState* exec) : m_exec(exec), m_code(0) { } + ~DOMExceptionTranslator() { setDOMException(m_exec, m_code); } + operator WebCore::ExceptionCode&() { return m_code; } + private: + ExecState* m_exec; + WebCore::ExceptionCode m_code; + }; + + JSValue* jsStringOrNull(const WebCore::String&); // null if the string is null + JSValue* jsStringOrUndefined(const WebCore::String&); // undefined if the string is null + JSValue* jsStringOrFalse(const WebCore::String&); // boolean false if the string is null + + // see JavaScriptCore for explanation should be used for UString that is already owned + // by another object, so that collecting the JSString wrapper is unlikely to save memory. + JSValue* jsOwnedStringOrNull(const KJS::UString&); + + WebCore::String valueToStringWithNullCheck(ExecState*, JSValue*); // null String if the value is null + WebCore::String valueToStringWithUndefinedOrNullCheck(ExecState*, JSValue*); // null String if the value is null or undefined + + template inline JSValue* toJS(ExecState* exec, PassRefPtr ptr) { return toJS(exec, ptr.get()); } + +} // namespace + +#endif diff --git a/src/webcore/bindings/scripts/CodeGeneratorQJS.pm b/src/webcore/bindings/scripts/CodeGeneratorQJS.pm index 5115f35..ca010e2 100644 --- a/src/webcore/bindings/scripts/CodeGeneratorQJS.pm +++ b/src/webcore/bindings/scripts/CodeGeneratorQJS.pm @@ -295,7 +295,7 @@ sub GenerateHeader push(@headerContent, GetLegacyHeaderIncludes($dataNode->extendedAttributes->{"LegacyParent"})); } else { if ($hasParent) { - push(@headerContent, "#include \"$parentClassName.h\"\n"); + push(@headerContent, "#include \"Q$parentClassName.h\"\n"); } else { push(@headerContent, "#include \"qjs_binding.h\"\n"); } @@ -373,8 +373,8 @@ sub GenerateHeader push(@headerContent, " static JSClassID js_class_id;\n\n"); # Custom mark function - if ($dataNode->extendedAttributes->{"CustomMarkFunction"}) { - push(@headerContent, " virtual void mark(exec);\n\n"); + if ($dataNode->extendedAttributes->{"CustomMarkFunction"} || $hasRealParent) { + push(@headerContent, " static void mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);\n\n"); } # Custom pushEventHandlerScope function @@ -624,8 +624,7 @@ sub GenerateImplementation @implContent = (); - push(@implContent, "\nusing namespace QJS;\n\n"); - push(@implContent, "namespace WebCore {\n\n"); + push(@implContent, "\nnamespace WebCore {\n\n"); push(@implContent, "#define countof(x) (sizeof(x) / sizeof((x)[0]))\n"); # - Add all attributes in a hashtable definition @@ -709,13 +708,21 @@ sub GenerateImplementation } push(@implContent, "JSValue ${className}Constructor::self(JSContext * ctx)\n{\n"); - if ($canConstruct) { - push(@implContent, "// construct !!\n"); + push(@implContent, " JSValue globalObj = JS_GetGlobalObject(ctx);\n"); + push(@implContent, " JSValue obj = JS_GetPropertyStr(ctx, globalObj, \"[[${interfaceName}.constructor]]\")\n"); + push(@implContent, " if (JS_IsException(obj)) {\n"); + if ($dataNode->extendedAttributes->{"CanBeConstructed"}) { + push(@implContent, " obj = JS_NewCFunction2(ctx, ${className}Constructor::construct, \"${interfaceName}\", 0, JS_CFUNC_constructor, 0);\n"); } else { - push(@implContent, " setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype()); \n"); - push(@implContent, " putDirect(exec->propertyNames().prototype, ${protoClassName}::self(exec), None);\n"); - push(@implContent, " KJS::cacheGlobalObject<${className}Constructor>(ctx, \"[[${interfaceName}.constructor]]\");\n"); + push(@implContent, " obj = JS_NewObject(ctx);\n"); } + push(@implContent, " ${className}Constructor::initConstructor(ctx, obj);\n"); + push(@implContent, " JS_SetPropertyStr(ctx, globalObj, \"[[${interfaceName}.constructor]]\", obj);\n"); + push(@implContent, " obj = JS_DupValue(ctx, obj);\n"); + push(@implContent, " }\n"); + push(@implContent, " JS_FreeValue(ctx, globalObj)\n"); + push(@implContent, " JS_FreeValue(ctx, obj)\n"); + push(@implContent, " return obj;\n"); push(@implContent, "}\n\n"); push(@implContent, "void ${className}Constructor::initConstructor(JSContext * ctx, JSValue this_obj)\n{\n"); @@ -723,6 +730,12 @@ sub GenerateImplementation push(@implContent, " JS_SetPropertyFunctionList(ctx, this_obj, ${className}ConstructorFunctions, countof(${className}ConstructorFunctions));\n"); } push(@implContent, "}\n\n"); + + if ($dataNode->extendedAttributes->{"CanBeConstructed"}) { + push(@implContent, "JSValue ${className}Constructor::construct(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv)\n{\n"); + push(@implContent, " return toJS(ctx, new $interfaceName);\n"); + push(@implContent, "}\n\n"); + } } if ($numConstants > 0) { @@ -787,9 +800,14 @@ sub GenerateImplementation push(@implContent, " JSValue globalObj = JS_GetGlobalObject(ctx);\n"); push(@implContent, " JSValue obj = JS_GetPropertyStr(ctx, globalObj, \"[[${className}.prototype]]\")\n"); push(@implContent, " if (JS_IsException(obj)) {\n"); - push(@implContent, " obj = JS_NewObjectProto(ctx, ${parentClassName}Prototype::self(ctx));\n"); + if ($hasParent) { + push(@implContent, " obj = JS_NewObjectProto(ctx, ${parentClassName}Prototype::self(ctx));\n"); + } else { + push(@implContent, " obj = JS_NewObject(ctx);\n"); + } push(@implContent, " ${className}Prototype::initPrototype(ctx, obj);\n"); push(@implContent, " JS_SetPropertyStr(ctx, globalObj, \"[[${className}.prototype]]\", obj);\n"); + push(@implContent, " obj = JS_DupValue(ctx, obj);\n"); push(@implContent, " }\n"); push(@implContent, " JS_FreeValue(ctx, globalObj)\n"); push(@implContent, " JS_FreeValue(ctx, obj)\n"); @@ -844,6 +862,9 @@ sub GenerateImplementation push(@implContent, "static JSClassDef ${className}ClassDefine = \n\{\n"); push(@implContent, " \"${interfaceName}\",\n"); push(@implContent, " .finalizer = ${className}::finalizer,\n"); + if ($dataNode->extendedAttributes->{"CustomMarkFunction"} || $hasRealParent) { + push(@implContent, " .gc_mark = ${className}::mark,\n"); + } push(@implContent, "};\n\n"); push(@implContent, "JSClassID ${className}::js_class_id = 0;\n\n"); @@ -906,6 +927,13 @@ sub GenerateImplementation push(@implContent, "{\n ScriptInterpreter::forgetDOMObject(static_cast<${implClassName}*>(impl()));\n}\n\n"); } + if (!$dataNode->extendedAttributes->{"CustomMarkFunction"} and $hasRealParent) { + push(@implContent, "void ${className}::mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)\n{\n"); + push(@implContent, " ${parentClassName}::mark(rt, val, mark_func);\n"); + push(@implContent, "}\n\n"); + } + + # Attributes if ($numAttributes ne 0) { ## @@ -1139,21 +1167,18 @@ sub GenerateImplementation #push(@implContent, "JSValue ${className}::getConstructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv)\n{\n"); push(@implContent, "JSValue ${className}::getConstructor(JSContext *ctx)\n{\n"); push(@implContent, " return ${className}Constructor::self(ctx);\n"); - push(@implContent, "}\n"); + push(@implContent, "}\n\n"); } # Functions if ($numFunctions ne 0) { push(@implContent, "JSValue ${className}PrototypeFunction::callAsFunction(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst *argv, int token)\n{\n"); - push(@implContent, " if (!thisObj->inherits(&${className}::info))\n"); - push(@implContent, " return throwError(exec, TypeError);\n\n"); - push(@implContent, " $implClassName* imp = JS_GetOpaque2(ctx, this_val, ${className}::js_class_id);\n"); push(@implContent, " if (!imp)\n"); - push(@implContent, " return JS_EXCEPTION;\n\n"); + push(@implContent, " return throwError(ctx, TypeError);\n\n"); if ($podType) { - ##push(@implContent, " JSSVGPODTypeWrapper<$podType>* wrapper = castedThisObj->impl();\n"); - ##push(@implContent, " $podType imp(*wrapper);\n\n"); + push(@implContent, " JSSVGPODTypeWrapper<$podType>* wrapper = castedThisObj->impl();\n"); + push(@implContent, " $podType imp(*wrapper);\n\n"); } else { } @@ -1243,10 +1268,10 @@ sub GenerateImplementation push(@implContent, " }\n"); # end switch push(@implContent, " (void)imp;\n") if $hasCustomFunctionsOnly; push(@implContent, " return 0;\n"); - push(@implContent, "}\n"); + push(@implContent, "}\n\n"); } - push(@implContent, "\n"); if ($dataNode->extendedAttributes->{"HasIndexGetter"}) { + push(@implContent, "\n"); push(@implContent, "\nJSValue ${className}::indexGetter(JSContext *ctx, JSValueConst this_obj, uint32_t idx)\n"); push(@implContent, "{\n"); push(@implContent, " ${className}* thisObj = static_cast<$className*>(slot.slotBase());\n"); @@ -1283,9 +1308,8 @@ sub GenerateImplementation push(@implContent, "}\n"); } - push(@implContent, "\n"); - if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateNativeConverter"}) and !$dataNode->extendedAttributes->{"CustomNativeConverter"}) { + push(@implContent, "\n"); if ($podType) { push(@implContent, "$podType to${interfaceName}(JSValue val)\n"); } else { @@ -1463,7 +1487,7 @@ sub JSValueToNative } if ($type eq "EventTarget") { - $implIncludes{"JSEventTargetNode.h"} = 1; + $implIncludes{"QJSEventTargetNode.h"} = 1; return "toEventTargetNode($value)"; } @@ -1561,12 +1585,12 @@ sub NativeToJSValue if ($type eq "EventTarget") { $implIncludes{"EventTargetNode.h"} = 1; - $implIncludes{"JSEventTargetNode.h"} = 1; + $implIncludes{"QJSEventTargetNode.h"} = 1; $implIncludes{"qjs_dom.h"} = 1; } elsif ($type eq "DOMWindow") { $implIncludes{"qjs_window.h"} = 1; } elsif ($type eq "DOMObject") { - $implIncludes{"JSCanvasRenderingContext2D.h"} = 1; + $implIncludes{"QJSCanvasRenderingContext2D.h"} = 1; } elsif ($type eq "Clipboard") { $implIncludes{"qjs_events.h"} = 1; $implIncludes{"Clipboard.h"} = 1; @@ -1956,8 +1980,7 @@ EOF if ($canConstruct) { $implContent .= << "EOF"; - virtual bool implementsConstruct() const { return true; } - virtual JSObject* construct(ExecState* exec, const List& args) { return static_cast(toJS(exec, new $interfaceName)); } + static JSValue construct(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv); EOF }