WebKit compilation rules under Win32 (9)

Source: Internet
Author: User

In the compilation rules (7) of WebKit under Win32, I mentioned that I want to introduce JS binding, but I forgot it later. Recently, some netizens mentioned that, this section introduces JS binding.

First, it is the JS engine, and the JS engine is an interpreter. In the command line, the interpreter parses the script and runs it. Similarly, we can also write the command in the batfile, and then let cmd.exe execute. Similar to this, the JS engine executes JS scripts. Input a script in the command line, which is equivalent to the script embedded in the execution label in the JS engine, for example, onclick = "javascript: window. alert (1); "; execute the bat script, which is equivalent to the interpretation in the JS engine to run a JS file.

For ease of introduction, the following section describes criptcore JS engine (Squirrelfish or squirrelfish extreme). V8 and other engines are similar in principle, but their implementations are different.

In javascriptcore, the function in the main line is:

Jsvalue JSC: Evaluate (execstate * exec, scopechainnode * scopechain, const sourcecode & source, jsvalue thisvalue, jsvalue * returnedexception)

This function completes the specific parsing and execution of JavaScript. If this function is not called, JS engine will not do anything. In WebKit, The jsmainthreadexecstate: Evaluate function of WebCore is called. When WebKit downloads a JS file or the embedded JS script in the tag is triggered, jsmainthreadexecstate: Evaluate will be called, resulting in JSC: Evaluate being called. JS engine is single-threaded. A page (or a window object) is generally configured with a JS engine. If a page has multiple frames, multiple JS Engines
These JS engines run in different threads. The following code calls the JSC: Evaluate stack after JS script is run for HTML parse:

Webkit_debug.dll! WebCore: jsmainthreadexecstate: Evaluate (JSC: execstate * exec, JSC: scopechainnode * chain, const JSC: sourcecode & source, JSC: jsvalue thisvalue, JSC :: jsvalue * exception) Row 57 c ++> webkit_debug.dll! WebCore: scriptcontroller: evaluateinworld (const WebCore: scriptsourcecode & sourcecode, WebCore: domwrapperworld * World) Line 144 + 0x33 bytes C ++ webkit_debug.dll! WebCore: scriptcontroller: Evaluate (const WebCore: scriptsourcecode & sourcecode) line 161 + 0x16 bytes C ++ webkit_debug.dll! WebCore: scriptelement: executescript (const WebCore: scriptsourcecode & sourcecode) line 292 + 0x17 bytes C ++ webkit_debug.dll! WebCore: htmlscriptrunner: executependingscriptanddispatchevent (WebCore: pendingscript & pendingscript) Row 140 C ++ webkit_debug.dll! WebCore: htmlscriptrunner: executeparsingblockingscript () line 119 C ++ webkit_debug.dll! WebCore: htmlscriptrunner: executeparsingblockingscripts () line 196 C ++ webkit_debug.dll! WebCore: htmlscriptrunner: executescriptswaitingforload (WebCore: cachedresource * cachedscript) Row 207 C ++ webkit_debug.dll! WebCore: htmldocumentparser: policyfinished (WebCore: cachedresource * cachedresource) line 517 + 0x19 bytes C ++ webkit_debug.dll! WebCore: cachedresource: checknotid () Row 151 + 0x13 bytes C ++ webkit_debug.dll! WebCore: cachedscript: Data (WTF: passrefptr <WebCore: sharedbuffer> data, bool alldatareceived) Row 105 C ++ webkit_debug.dll! WebCore: cachedresourcerequest: didfinishloading (WebCore: subresourceloader * loader, double _ formal) Row 170 C ++ webkit_debug.dll! WebCore: subresourceloader: didfinishloading (double finishtime) line 196 + 0x28 bytes C ++ webkit_debug.dll! WebCore: resourceloader: didfinishloading (WebCore: resourcehandle * _ formal, double finishtime) Row 472 + 0x18 bytes C ++ webkit_debug.dll! WebCore: resourcehandlemanager: downloadtimercallback (WebCore: timer <WebCore: resourcehandlemanager> * timer) line 400 + 0x35 bytes C ++ webkit_debug.dll! WebCore: timer <WebCore: resourcehandlemanager>: fired () Row 100 + 0x23 bytes C ++ webkit_debug.dll! WebCore: threadtimers: sharedtimerfiredinternal () Row 115 + 0xf byte C ++ webkit_debug.dll! WebCore: threadtimers: sharedtimerfired () Row 94 C ++ webkit_debug.dll! WebCore: timer1_wwndproc (hwnd _ * hwnd, unsigned int message, unsigned int wparam, long lparam) Row 103 + 0x8 bytes C ++

JSC: Evaluate has five parameters: execstate * exec indicates the overall running environment of the JS engine, for example, the value of the global variable; scopechainnode * scopechain indicates the current running scope chain, this is related to the closure (closure) of JS. Const sourcecode & source indicates the content of the JS script; jsvalue thisvalue indicates the this object of the script; jsvalue * returnedexception indicates the exception information after script execution.

Let's take a look at the code of scriptcontroller: evaluateinworld:

ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld* world){    const SourceCode& jsSourceCode = sourceCode.jsSourceCode();    String sourceURL = ustringToString(jsSourceCode.provider()->url());    // evaluate code. Returns the JS return value or 0    // if there was none, an error occurred or the type couldn't be converted.    // inlineCode is true for <a href="javascript:doSomething()">    // and false for <script>doSomething()</script>. Check if it has the    // expected value in all cases.    // See smart window.open policy for where this is used.    JSDOMWindowShell* shell = windowShell(world);    ExecState* exec = shell->window()->globalExec();    const String* savedSourceURL = m_sourceURL;    m_sourceURL = &sourceURL;    JSLock lock(SilenceAssertionsOnly);    RefPtr<Frame> protect = m_frame;    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(m_frame, sourceURL, sourceCode.startLine());    JSValue evaluationException;    exec->globalData().timeoutChecker.start();    JSValue returnValue = JSMainThreadExecState::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), jsSourceCode, shell, &evaluationException);    exec->globalData().timeoutChecker.stop();    InspectorInstrumentation::didEvaluateScript(cookie);    if (evaluationException) {        reportException(exec, evaluationException);        m_sourceURL = savedSourceURL;        return ScriptValue();    }    m_sourceURL = savedSourceURL;    return ScriptValue(exec->globalData(), returnValue);}

We can see that the exec, scopechain, and thisvalue of jsmainthreadexecstate: Evaluate are related to the jsdomwindowshell object. From the jsdomwindowshell name, we can see that WebKit compares the execution of JS scripts to the input of commands in shell. If thisvalue is jsdomwindowshell, this indicates that this is the window object at the top of the JS script, which is consistent with the window object in the DOM model at the top.

In the preceding jsdomwindowshell * shell = windowshell (World); During execution, jsdomwindowshell: setwindow is called, and the call stack is as follows:

Webkit_debug.dll! WebCore: jsdomwindowshell: setwindow (WTF: passrefptr <WebCore: domwindow> domwindow) line 75 C ++ webkit_debug.dll! WebCore: jsdomwindowshell: finishcreation (JSC: jsglobaldata & globaldata, WTF: passrefptr <WebCore: domwindow> window) Row 57 c ++ webkit_debug.dll! WebCore: jsdomwindowshell: Create (WTF: passrefptr <WebCore: domwindow> window, JSC: Structure * structure, WebCore: domwrapperworld * World) row 62 C ++ webkit_debug.dll! WebCore: scriptcontroller: createwindowshell (WebCore: domwrapperworld * World) Row 111 + 0x21 bytes C ++ webkit_debug.dll! WebCore: scriptcontroller: initscript (WebCore: domwrapperworld * World) line 213 + 0xc byte C ++ webkit_debug.dll! WebCore: scriptcontroller: windowshell (WebCore: domwrapperworld * World) Row 79 + 0x43 bytes C ++> webkit_debug.dll! WebCore: scriptcontroller: evaluateinworld (const WebCore: scriptsourcecode & sourcecode, WebCore: domwrapperworld * World) Row 130 + 0xc byte C ++

Jsdomwindowshell: setwindow will call jsdomwindow: Create to create a real window object:

JSDOMWindow* jsDOMWindow = JSDOMWindow::create(*JSDOMWindow::commonJSGlobalData(), structure, domWindow, this);

Then, the setwindow of the two parameters is called to assign the jsdomwindow value to the member variable m_window of jsdomwindowshell.

void setWindow(JSC::JSGlobalData& globalData, JSDOMWindow* window)        {            ASSERT_ARG(window, window);            m_window.set(globalData, this, window);            setPrototype(globalData, window->prototype());        }

Next let's take a look at the definition of jsdomwindowshell, as follows:

Class jsdomwindowshell: Public JSC: jsnonfinalobject

Jsdomwindowshell inherits from JSC: jsnonfinalobject, JSC: jsnonfinalobject inherits from jsobject. In short, jsdomwindowshell is a jsobject. Jsobject has the following functions that can be overloaded (polymorphism ):

        virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);        virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);        virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);        virtual void putWithAttributes(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, unsigned attributes);        virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName);        virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);        virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);        virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);        virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes);        virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);        virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);        virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);

Jsdomwindowshell reloads these functions, so these functions are called when js-related functions are executed, for example

Window. onload = function (){}

The JS engine calls the jsdomwindowshell: Put function, jsdomwindowshell: put, and then calls jsdomwindow: Put.

void JSDOMWindowShell::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot){    m_window->put(exec, propertyName, value, slot);}

Jsdomwindow: Put will lookupput in s_info to find the function corresponding to onload and execute:

void JSDOMWindow::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot){    if (!impl()->frame())        return;    // Optimization: access JavaScript global variables directly before involving the DOM.    if (JSGlobalObject::hasOwnPropertyForWrite(exec, propertyName)) {        if (allowsAccessFrom(exec))            JSGlobalObject::put(exec, propertyName, value, slot);        return;    }    if (lookupPut<JSDOMWindow>(exec, propertyName, value, s_info.propHashTable(exec), this))        return;    if (allowsAccessFrom(exec))        Base::put(exec, propertyName, value, slot);}

Let's take a look at the definition of jsdomwindow: s_info:

const ClassInfo JSDOMWindow::s_info = { "DOMWindow", &JSDOMWindowBase::s_info, &JSDOMWindowTable, 0 };

The parentclass of s_info is jsdomwindowbase: s_info, and staticprophashtable is jsdomwindowtable. Jsdomwindowtable is defined in D: \ project \ WebKit \ webkitbuild \ debug_cairo_cflite \ OBJ \ WebCore \ derivedsources \ jsdomwindow. CPP, jsdomwindow. CPP is composed of domwindow. IDL is generated by generate-bindings.pl, which has been explained in the compilation rules of WebKit under Win32 (7:

static JSC_CONST_HASHTABLE HashTable JSDOMWindowTable = { 1125, 1023, JSDOMWindowTableValues, 0 };

It is a hashtable whose value is in jsdomwindowtablevalues. Part of jsdomwindowtablevalues is intercepted below:

static const HashTableValue JSDOMWindowTableValues[] ={    { "screen", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowScreen), (intptr_t)setJSDOMWindowScreen THUNK_GENERATOR(0) },    { "history", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowHistory), (intptr_t)setJSDOMWindowHistory THUNK_GENERATOR(0) },    { "locationbar", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowLocationbar), (intptr_t)setJSDOMWindowLocationbar THUNK_GENERATOR(0) },    { "menubar", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowMenubar), (intptr_t)setJSDOMWindowMenubar THUNK_GENERATOR(0) },    { "personalbar", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowPersonalbar), (intptr_t)setJSDOMWindowPersonalbar THUNK_GENERATOR(0) },    { "scrollbars", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowScrollbars), (intptr_t)setJSDOMWindowScrollbars THUNK_GENERATOR(0) },    { "statusbar", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowStatusbar), (intptr_t)setJSDOMWindowStatusbar THUNK_GENERATOR(0) },    { "toolbar", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowToolbar), (intptr_t)setJSDOMWindowToolbar THUNK_GENERATOR(0) },    { "navigator", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowNavigator), (intptr_t)setJSDOMWindowNavigator THUNK_GENERATOR(0) },    { "clientInformation", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowClientInformation), (intptr_t)setJSDOMWindowClientInformation THUNK_GENERATOR(0) },……………     { "document", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowDocument), (intptr_t)0 THUNK_GENERATOR(0) },   ……………     { "console", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowConsole), (intptr_t)setJSDOMWindowConsole THUNK_GENERATOR(0) },    { "onabort", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowOnabort), (intptr_t)setJSDOMWindowOnabort THUNK_GENERATOR(0) },    { "onbeforeunload", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowOnbeforeunload), (intptr_t)setJSDOMWindowOnbeforeunload THUNK_GENERATOR(0) },    { "onblur", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowOnblur), (intptr_t)setJSDOMWindowOnblur THUNK_GENERATOR(0) },    { "oncanplay", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowOncanplay), (intptr_t)setJSDOMWindowOncanplay THUNK_GENERATOR(0) },    { "oncanplaythrough", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowOncanplaythrough), (intptr_t)setJSDOMWindowOncanplaythrough THUNK_GENERATOR(0) },    { "onchange", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowOnchange), (intptr_t)setJSDOMWindowOnchange THUNK_GENERATOR(0) },    { "onclick", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowOnclick), (intptr_t)setJSDOMWindowOnclick THUNK_GENERATOR(0) },    { "oncontextmenu", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowOncontextmenu), (intptr_t)setJSDOMWindowOncontextmenu THUNK_GENERATOR(0) },    { "ondblclick", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowOndblclick), (intptr_t)setJSDOMWindowOndblclick THUNK_GENERATOR(0) },   ……………     { "onkeypress", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowOnkeypress), (intptr_t)setJSDOMWindowOnkeypress THUNK_GENERATOR(0) },    { "onkeyup", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowOnkeyup), (intptr_t)setJSDOMWindowOnkeyup THUNK_GENERATOR(0) },    { "onload", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsDOMWindowOnload), (intptr_t)setJSDOMWindowOnload THUNK_GENERATOR(0) },………}

From jsdomwindowtablevalues, we can see attributes such as history, document, and navigator, and events such as onload and onclick.

Each jsdomwindowtablevalues item consists of five parts: "document"-> attribute name; dontdelete | readonly-> flag related to the attribute; (intptr_t) static_cast <propertyslot :: getvaluefunc> (jsdomwindowdocument)-> getter function; (intptr_t) 0-> setter function; thunk_generator (0) is used for JIT. When the execution of the program example document.xxx, the getteraskforexecution of the program example Doc ument will be triggered.
= 123; it will trigger the setter function. Because the setter function of document is null, this JS script will throw an exception.

The implementation of specific setter and getter is related to specific functions. For example, window. Navigator finally calls:

JSValue jsDOMWindowNavigator(ExecState* exec, JSValue slotBase, const Identifier&){    JSDOMWindow* castedThis = static_cast<JSDOMWindow*>(asObject(slotBase));    if (!castedThis->allowsAccessFrom(exec))        return jsUndefined();    UNUSED_PARAM(exec);    DOMWindow* imp = static_cast<DOMWindow*>(castedThis->impl());    JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->navigator()));    return result;}

The imp-> Navigator () indicates that:

Navigator* DOMWindow::navigator() const{    if (!m_navigator)        m_navigator = Navigator::create(m_frame);    return m_navigator.get();}

In addition, many people have a question: when calling related methods or getting related properties, why can't I write windows? For example, the following script can be executed normally:

The answer is that the above script is actually the most direct method, because the thisvalue during JS script execution is jsdomwindowshell, that is, the window object, and jsdomwindow has a property called window, it returns the current jsdomwindowshell, so the window in the JS script. onload is actually thisvalue. window. onload.

In domwindow. IDL, some comments are // Dom level 0, // Dom Level 2 abstractview interface, etc. For relevant explanations, refer to Wiki (http://en.wikipedia.org/wiki/Document_Object_Model#Levels_of_DOM ):

After the release of ecmascript, W3C began work on a standardized Dom. the initial Dom standard, known as "dom Level 1," was recommended by W3C in late 1998. about the same time, Internet Explorer 5.0 shipped with limited support for Dom Level 1. dom level
1 provided a complete model for an entire HTML or XML document, including means to change any portion of the document. Non-conformant
Browsers such as Internet Explorer 4.x and Netscape 4.x were still widely used as late as 2000.

Dom Level 2 was published in late 2000. It introduced the "getelementbyid" function as well as an event
Model and support for XML Namespaces and CSS. Dom Level 3, the current release
Of the DOM specification, published in each l 2004, added support for xpath and keyboard event
Handling, as well as an interface for serializing events as XML.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.