5

ネイティブ NodeJS (0.11.5) 拡張機能でカスタム例外を作成したいと考えています。ErrorV8 (3.20.11) でビルトイン クラスのサブクラスを作成しようとしています。

基本的に、次の Javascript コードに相当する C++ を探しています。

function MyError(message) {
  Error.apply(this, arguments);
  this.message = message;
}
MyError.prototype = new Error;
MyError.prototype.name = MyError.name;

new MyError("message")

V8 のソースを掘り下げてみたところ、次のようなヘルパー メソッドが見つかりました。

Handle<Object> Factory::NewError(const char* constructor,
                                 Handle<String> message)

残念ながら、それはプライベート API のように見えます。V8 について十分に理解していないため、同様のものを自分で構築する方法を理解できません。ビルトイン インスタンスを作成するのと同様の方法で使用できるメソッドを記述できれば、すばらしいことErrorです。たとえば、次のようになります。

ThrowException(v8::Exception::Error(v8::String::New(msg)))
// becomes...
ThrowException(MyError(v8::String::New(msg)))

組み込みクラスのサブクラスにできるだけ近いソリューションを探していErrorます。おそらく次の条件を満たす必要があります。

var e = new MyError("message");
assert(e instanceof MyError);
assert(e instanceof Error);
assert(e.name === "MyError");
assert(e.message === "message");

どこから始めればよいですか?

4

2 に答える 2

1

私は NodeJS についてあまり知りませんが、1 つの可能性としては、意味のある C++ 例外をスローし、それを拡張機能の境界でキャッチし、標準の V8 呼び出しを使用して適切な JavaScript 例外を構築し、v8::ThrowException(). NodeJS で拡張機能が V8 に直接アクセスできない場合、このアプローチは選択肢にならない可能性があります。

カスタム エラー クラスを設定し、C++ からインスタンス化する方法を示すサンプル プログラムを次に示します。うまくいけば、NodeJS が同様のことを行うのに十分な V8 アクセスを提供します。

#include "v8.h"
#include <iostream>

static void Print(v8::Handle<v8::Value> value)
{
    std::cout << *v8::String::Utf8Value(value) << std::endl;
}

static v8::Local<v8::Value> RunScript(const char* code)
{
    return v8::Script::Compile(v8::String::New(code))->Run();
}

static void RunTest(v8::Isolate* isolate)
{
    // setup
    v8::Locker locker(isolate);
    v8::Isolate::Scope isolateScope(isolate);
    v8::HandleScope handleScope(isolate);
    auto context = v8::Context::New(isolate);
    v8::Context::Scope contextScope(context);

    // create custom error class/function
    auto code =
        "function MyError(message) {"
            "Error.apply(this, arguments);"
            "this.message = message;"
        "}"
        "MyError.prototype = new Error;"
        "MyError.prototype.name = MyError.name;"
        "MyError";
    auto errorFunc = RunScript(code)->ToObject();

    // create custom error instance
    auto message = v8::String::New("message");
    v8::Handle<v8::Value> args[] = { message };
    auto error = errorFunc->CallAsConstructor(1, args);

    // validate custom error instance
    context->Global()->Set(v8::String::New("e"), error);
    Print(RunScript("e instanceof MyError"));
    Print(RunScript("e instanceof Error"));
    Print(RunScript("e.name === 'MyError'"));
    Print(RunScript("e.message === 'message'"));
}

void main(void)
{
    auto isolate = v8::Isolate::New();
    RunTest(isolate);
    isolate->Dispose();
}
于 2013-08-24T21:00:30.403 に答える