2011
Oct
25

Javascript是一个脚本程式语言,而 Google 写了一个JS engine ,可以分析javascript的程式码并实作出来,这是一个用C语言写出来的程式,就跟PHP类似,我们也可以对node.js写extension,不过在学如何制作extension时,我们就得先学学 Google V8 Engine。

what is Context

你可以把 context 当成一个 Instance,里面有包含原始的 object , properties 等,简单的说, context 预设就像是 Javasceipt 的 window , 当 JS 直接对外部变数修改,而没有宣告 local variable ,这时 context 的内容就会被更改,每个 Context 都要有一个 context scope ,就是为了 Garbage 管理 ,在之后的 v8 engine 语法中,常会见到 scope 这个名称,几乎所有的 v8 engine object ,都必需存放在scope中。

Example
  1. //initial context
  2. Persistent<Context> context;
  3. context = Context::New();

V8 Handle

Handle是各种物件的reference,有自动的 GC (Garbage Collector) 处理,在 Google V8 Engine中,几乎所有的变数都会宣告在 Handle里,统一由Handle来管理。

  • Handle 又分两种类型, Local 与 Persistent ,这两个其实也不难, Local Handle 的生命周期是由 HandleScope来控制,当变数不再被使用的时候,就会自动被GC给处理掉,Persistent Handle则是由工程师可自已控制,当不需要使用时,要手动 delete memory allocate 。
Example
  1. void run(){
  2. HandleScope handle_scope;
  3. Persistent<String> PerName(String::New("Persistent var"));
  4. Local<String> LocalName(String::New("local var"));
  5. namePer.Dispose();//手动清除 memory
  6. //function 结束后, LocalName 因 handle_scope destruct 而跟著自动被清除
  7. }

V8 HandleScope

HandleScope 就是代表著 Handle 存在的区域,也可以说是 Handle的家,你必需先建立 HandleScope ,接著才能建立 Handle,不然 Handle可是会找不到家的喔。

HandleScope 会自动管理 Handle的生命周期,当HandleScope结束掉,家里所有的 Handle 也会被清空。

  • 同时宣告两个以上的 HandleScope , 后面的HandleScope取代第一个HandleScope的所有功能,等於 Handle 有了两个家,这时只要有一个 HandleScope存在, Handle就不会被清除。

V8 基本变数使用

V8 支援将多种变数转成字串,这里实际测试了变数型态有 Number,Integer, Boolean。

  • 将变数以 UTF-8字串编码输出,String::Utf8Value utf_str(text);
  • 将变数以 BIG5 字串编码输出,String::AsciiValue big_str(text);
  • Integer为32位元,最大整数值 = 2147483647,最小整数值 = -2147483648
Example
  1. #include <iostream>
  2. #include <v8-debug.h>
  3. #include <v8.h>
  4. using namespace std;
  5. using namespace v8;
  6.  
  7. //void NeanderArray::set(int index, i::Object* value)
  8.  
  9. int main(int argc, char* argv[]){
  10. HandleScope handle_scope;
  11. Persistent<Context> context = Context::New();
  12. Context::Scope context_scope(context);
  13. Handle<Number> Num= Number::New(100.5); //double
  14. Handle<Integer> inte= Integer::New(10); //32位元
  15. Handle<Integer> inte2= Integer::New(-10);
  16. Handle<Integer> int_max= Integer::New(2147483647);
  17. Handle<Integer> int_min= Integer::New(-2147483648);
  18. Handle<String> str= String::New("just string");
  19. Handle<Boolean> boolean= Boolean::New(1);
  20. Handle<Boolean> boolean2= Boolean::New(0);
  21. Handle<Boolean> boolean3= Boolean::New(2);
  22. Handle<Boolean> boolean4= Boolean::New(3);
  23. //String::AsciiValue b(inte); //ascii big5
  24. cout <<"Num = " << *String::Utf8Value(Num) << endl;
  25. cout <<"inte = " << *String::Utf8Value(inte) << endl;
  26. cout <<"inte2 = " << *String::Utf8Value(inte2) << endl;
  27. cout <<"int_max = " << *String::Utf8Value(int_max) << endl;
  28. cout <<"int_min = " << *String::Utf8Value(int_min) << endl;
  29. cout <<"str = " << *String::Utf8Value(str) << endl;
  30. cout <<"boolean = " << *String::Utf8Value(boolean) << endl;
  31. cout <<"boolean2 = " << *String::Utf8Value(boolean2) << endl;
  32. cout <<"boolean3 = " << *String::Utf8Value(boolean3) << endl;
  33. cout <<"boolean4 = " << *String::Utf8Value(boolean4) << endl;
  34. context.Dispose();
  35. return 0;
  36. }
执行结果
Example
  1. [puritys]V8$ ./exe/basic.o
  2. Num = 100.5
  3. inte = 10
  4. inte2 = -10
  5. int_max = 2147483647
  6. int_min = -2147483648
  7. str = just string
  8. boolean = true
  9. boolean2 = false
  10. boolean3 = true
  11. boolean4 = true

V8 Array

V8 的 Array 就像 JS , PHP 一样,想塞什么值就塞什么值,在 Array 中塞 Array 也没问题啦。

Example
  1. #include <iostream>
  2. #include <v8-debug.h>
  3. #include <v8.h>
  4. using namespace std;
  5. using namespace v8;
  6.  
  7. //void NeanderArray::set(int index, i::Object* value)
  8. int main(int argc, char* argv[]){
  9. HandleScope handle_scope;
  10. Persistent<Context> context = Context::New();
  11. Context::Scope context_scope(context);
  12. Handle<Array> array= Array::New(4);
  13. array->Set(0, Integer::New(1));
  14. array->Set(1, String::New("string test"));
  15. array->Set(2, String::New("中文"));
  16. Handle<Array> array2= Array::New(2);
  17. array2->Set(0, Integer::New(2));
  18. array2->Set(1, Integer::New(2));
  19. //将array2 塞到 array1
  20. array->Set(3, array2);
  21. cout << "Length = " << array->Length() << endl;
  22. String::Utf8Value b(array); //utf8 编码
  23. //String::AsciiValue b(array); //ascii big5
  24. cout << *b;
  25. context.Dispose();
  26. return 0;
  27. }
执行结果
Example
  1. [puritys]V8$ ./exe/array.o
  2. Length = 4
  3. 1,string test,中文,2,2

问题与解法

建立一个 Handle array = Array::New(3); ,执行时却出现 segmentation fault

当你想建立一个Array物件时,V8的会试著去建立 JSArray ,JSArray 就是Google 实作 Javascript 的 Array,如果你在宣告 context 之前,就先定义 array ,这样 JS 会找不到 this ,而无法存取这个变数,因此你必需先宣告一个 Context ,这样程式才能够正常执行。
file: objects.h
Example
  1. class JSArray: public JSObject

Reference


回應 (Leave a comment)