简体   繁体   English

如何使对象在Google V8 Javascript引擎中不可变?

[英]How can I make an object immutable in the Google V8 Javascript engine?

Is it possible to make an object immutable in the V8 Javascript Engine? 是否可以使对象在V8 Javascript Engine中不可变? V8 is embedded in a C++ application. V8嵌入在C ++应用程序中。

In my case I've created and populated an Array (code is simplified) 就我而言,我已经创建并填充了一个数组(代码已简化)

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

I'd like to make the resulting object "read-only" (as you might get by calling Object.freeze ) before passing it to a script. 在将结果对象传递给脚本之前,我想使其成为“只读”对象(您可以通过调用Object.freeze获得)。 One of my script authors got themselves in a confusing situation by trying to re-use this object is a convoluted way, and I'd like to make it harder for this to happen by making the object immutable. 我的一位脚本作者试图重新使用该对象使自己陷入混乱的境地,这是一种令人费解的方法,我想通过使该对象成为不可变的对象来使这种情况变得更加困难。

I understand that I can do this in Javascript ( Object.freeze ), but I would like to be able to do it in C++ if possible. 我知道我可以使用Javascript( Object.freeze )来做到这一点,但我希望能够在C ++中做到这一点。

This approach works, although it's a little inelegant. 这种方法行之有效,尽管有点过时。 Essentially, I'm calling "Object.freeze" directly in Javascript, as I couldn't find a way to invoke this functionality from C++. 本质上,我无法在Java中直接调用“ Object.freeze”,因为我找不到从C ++调用此功能的方法。 I'm less than fluent in V8, so my code may be unnecessarily verbose. 我不太熟练使用V8,因此我的代码可能不必要地冗长。

/**
 * 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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM