2016-04-19 12 views
0

Ist es möglich, ein Objekt in der V8 Javascript Engine unveränderlich zu machen? V8 ist in eine C++ - Anwendung eingebettet.Wie kann ich ein Objekt in der Google V8-Javascript-Engine unveränderbar machen?

In meinem Fall habe ich erstellt und ein Array bevölkert (Code ist vereinfacht)

auto arr = v8::Array::New(isolate, 10); 
for (auto i = 0; i < 10; ++i) 
{ 
    arr->Set(context, i, v8::Integer::New(isolate, i)); 
} 

Ich möchte das resultierende Objekt „read-only“ machen (wie man bekommen könnte durch den Aufruf Object.freeze), bevor Sie es an ein Skript übergeben. Einer meiner Scriptautoren hat sich in eine verwirrende Situation gebracht, indem er versucht hat, dieses Objekt in einem verschachtelten Weg wiederzuverwenden, und ich möchte es dadurch erschweren, das Objekt unveränderlich zu machen.

Ich verstehe, dass ich dies in Javascript (Object.freeze) tun kann, aber ich würde gerne in der Lage sein, es in C++ zu tun, wenn möglich.

+0

Sie könnten alle Funktionen außer Kraft setzen, die es ändern, um nichts zu tun, nehme ich an? Keine gute Antwort, ich weiß. – xaxxon

Antwort

1

Dieser Ansatz funktioniert, obwohl es ein wenig unelegant ist. Im Wesentlichen rufe ich "Object.freeze" direkt in Javascript auf, da ich keine Möglichkeit fand, diese Funktionalität von C++ aus aufzurufen. Ich bin nicht so fließend in V8, so dass mein Code möglicherweise unnötig ausführlich ist.

/** 
* Make an object immutable by calling "Object.freeze". 
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze 
**/ 
void ezv8::utility::MakeImmutable(v8::Isolate * isolate, v8::Local<v8::Object> object) 
{ 
    ezv8::Ezv8 ezv8(isolate); 
    auto globalTmpl = v8::ObjectTemplate::New(isolate); 
    auto context = v8::Context::New(isolate, nullptr, globalTmpl); 

    v8::Isolate::Scope scope(isolate); 
    v8::Locker locker(isolate); 
    v8::HandleScope scope(ezv8.getIsolate()); 
    v8::Context::Scope context_scope(context); 

    // Define function "deepFreeze" as listed on the "Object.freeze" documentation page cited above. 
    std::string code(
     "function deepFreeze(obj) {\n" 
     " var propNames = Object.getOwnPropertyNames(obj);\n" 
     " propNames.forEach(function(name) {\n" 
     "  var prop = obj[name];\n" 
     "  if (typeof prop == 'object' && prop !== null)\n" 
     "   deepFreeze(prop);\n" 
     " });\n" 
     " return Object.freeze(obj);\n" 
     "};"); 


    v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, code.c_str()); 

    v8::Local<v8::Script> compiled_script(v8::Script::Compile(source)); 

    // Run the script! 
    v8::Local<v8::Value> result = compiled_script->Run(); 

    v8::Handle<v8::Value> argv[]{ object }; 

    v8::Handle<v8::String> process_name = v8::String::NewFromUtf8(isolate, "deepFreeze"); 
    v8::Handle<v8::Value> process_val = context->Global()->Get(process_name); 


    v8::Handle<v8::Function> process_fun = v8::Handle<v8::Function>::Cast(process_val); 
    v8::Local<v8::Function> process = v8::Local<v8::Function>::New(isolate, process_fun); 

    // Call the script. 
    v8::Local<v8::Value> rv = process->Call(context->Global(), 1, argv); 
}