继上文
ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode)这个函数算是正式脱离webcore进入bingding模块了。先看下这个函数,再分析
// Evaluate a script file in the environment of this proxy.ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode){ String sourceURL = sourceCode.url(); const String* savedSourceURL = m_sourceURL; m_sourceURL = &sourceURL; v8::HandleScope handleScope; v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_proxy->frame()); if (v8Context.IsEmpty()) return ScriptValue(); v8::Context::Scope scope(v8Context); RefPtr<Frame> protect(m_frame); v8::Local<v8::Value> object = m_proxy->evaluate(sourceCode, 0); // Evaluating the JavaScript could cause the frame to be deallocated // so we start the keep alive timer here. m_frame->keepAlive(); m_sourceURL = savedSourceURL; if (object.IsEmpty()) return ScriptValue(); return ScriptValue(object);}
这个函数里有很多重要的东西,关于使用V8,,无论是单独编译V8通过官方的测试用例还是在浏览器中使用都是大致相同的使用方法。现在挨着分析重要的部分:
1.先看这句:
v8::HandleScope handleScope;
以后遇到V8::这种,这个来源于V8中的很多源码都是用命名空间控制的,知道就行了:
namespace v8 {namespace internal {//这个是V8里另一个常用的
……
…..
}
}
// Create a handle scope for all local handles.这里创建handleScope对象,该对象销毁后,下面的所有handle就都销毁了。看似下面没有调用这个对象,实质这个对象创建了就已经起作用了。V8中后面还会这样创建handleScope,也是这样使用的。
看下HandleScope的构造函数:
HandleScope::HandleScope() { i::Isolate* isolate = i::Isolate::Current(); API_ENTRY_CHECK(isolate, "HandleScope::HandleScope"); v8::ImplementationUtilities::HandleScopeData* current = isolate->handle_scope_data(); isolate_ = isolate; prev_next_ = current->next; prev_limit_ = current->limit; is_closed_ = false; current->level++;}
取当前的isolate,进入api层的相关检查(主要检查线程锁),这个构造函数里还有一个链表控制的object数据,所以每一样定义一个这样的对象,实质上已经起作用了,即使没有使用这个对象。
2.再看
v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_proxy->frame());
这里是创建当前frame的上下文,,这个mainWorldContext(….)会检测传入的frame的proxy,再调用mainWorldContext()函数,这里面有一个比较重要的函数:
v8::Local<v8::Context> V8Proxy::mainWorldContext(){ windowShell()->initContextIfNeeded(); return v8::Local<v8::Context>::New(windowShell()->context());}
windowShell()->initContextIfNeeded();是一个比较重要的函数,下篇再专门分析下这个函数,根据windowshell初始化上下文。windowshell这个东西比较重要,在jsc中创建上下文也与它有关系,JSC中:
JSDOMWindowShell* shell = windowShell(world);ExecState* exec = shell->window()->globalExec();
V8中:
V8DOMWindowShell* windowShell() const { return m_windowShell.get(); }windowShell()->context()
3.再看
v8::Context::Scope scope(v8Context);
这里就是把创建的上下文放入作用域中,可以看下这个构造函数:
explicit inline Scope(Handle<Context> context):context_(context){
context_->Enter();
}
void Context::Enter() { i::Handle<i::Context> env = Utils::OpenHandle(this); i::Isolate* isolate = env->GetIsolate(); if (IsDeadCheck(isolate, "v8::Context::Enter()")) return; ENTER_V8(isolate); isolate->handle_scope_implementer()->EnterContext(env); isolate->handle_scope_implementer()->SaveContext(isolate->context()); isolate->set_context(*env);}
这里就是获取当前上下文环境,并将于作用域关联。
4.最后
v8::Local<v8::Value> object = m_proxy->evaluate(sourceCode, 0);
这里开始准备进入编译和执行源码了。
PS:这里面有一下数据关键和类的继承关系,下次另起一篇介绍
人只要不失去方向,就不会失去自己