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)