继上文
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:这里面有一下数据关键和类的继承关系,下次另起一篇介绍