Skip to content

Instantly share code, notes, and snippets.

@trevnorris trevnorris/main.cc
Last active Sep 6, 2017

Embed
What would you like to do?
#include <v8.h>
#include <node.h>
#define NEW_FROM_ONEBYTE(iso, name) \
v8::String::NewFromOneByte( \
iso, \
reinterpret_cast<const uint8_t*>(name), \
NewStringType::kInternalized).ToLocalChecked()
#define RUNTIME_TESTS(V) \
V(kTryCatch) \
V(kVerbose) \
V(kDomain) \
V(kDisposedDomain)
namespace bmod {
using namespace v8;
enum TestFlags {
#define V(RUNTIME_TEST) \
RUNTIME_TEST = (1 << __COUNTER__ ),
RUNTIME_TESTS(V)
#undef V
};
static void RunMakeCallback(const FunctionCallbackInfo<Value>& args) {
assert(args[0]->IsUint32());
assert(args[1]->IsUint32());
assert(args[2]->IsFunction());
assert(args[3]->IsObject());
auto isolate = args.GetIsolate();
uint32_t flags = args[0]->Uint32Value();
double async_id = args[1]->NumberValue();
auto fn = args[2].As<Function>();
auto obj = args[3].As<Object>();
fprintf(stderr, ">>> about to run MakeCallback %g\n", async_id);
if (!(flags & TestFlags::kTryCatch)) {
auto ret =
node::MakeCallback(isolate, obj, fn, 0, nullptr, { async_id, 1 });
args.GetReturnValue().Set(ret.FromMaybe(Undefined(isolate).As<Value>()));
fprintf(stderr,
"--- MakeCallback return value %s empty\n",
ret.IsEmpty() ? "IS" : "is NOT");
fprintf(stderr,
"<<< finished MakeCallback %g without TryCatch\n", async_id);
return;
}
TryCatch try_catch(isolate);
if (flags & TestFlags::kVerbose)
try_catch.SetVerbose(true);
auto ret = node::MakeCallback(isolate, obj, fn, 0, nullptr, { async_id, 1 });
fprintf(stderr,
"--- MakeCallback return value %s empty\n",
ret.IsEmpty() ? "IS" : "is NOT");
args.GetReturnValue().Set(ret.FromMaybe(Undefined(isolate).As<Value>()));
fprintf(stderr,
"--- MakeCallback %s throw\n",
try_catch.HasCaught() ? "DID" : "did NOT");
fprintf(stderr,
"<<< finished MakeCallback %g with TryCatch with verbose %s\n",
async_id,
(flags & TestFlags::kVerbose) ? "on" : "off");
}
void Init(Local<Object> exports) {
auto isolate = Isolate::GetCurrent();
auto ctx = isolate->GetCurrentContext();
NODE_SET_METHOD(exports, "runMakeCallback", RunMakeCallback);
auto constants = Object::New(isolate);
#define SET_CONSTS(obj, str, num) \
do { \
obj->Set(ctx, \
NEW_FROM_ONEBYTE(isolate, #str), \
Number::New(isolate, num)).ToChecked(); \
} while (0)
#define V(RUNTIME_TEST) \
SET_CONSTS(constants, RUNTIME_TEST, TestFlags::RUNTIME_TEST);
RUNTIME_TESTS(V)
#undef V
#undef SET_CONSTS
exports->Set(ctx,
NEW_FROM_ONEBYTE(isolate, "constants"),
constants).ToChecked();
}
} // namespace bmod
NODE_MODULE(addon, bmod::Init)
'use strict';
const release_type = process.config.target_defaults.default_configuration;
/* Signature:
* runMakeCallback(flags, async_id, callback, object)
*/
const { runMakeCallback, constants } = require(`./build/${release_type}/addon`);
const { kTryCatch, kVerbose } = constants;
const print = process._rawDebug;
const fnNames = ['fn', 'fnThrow', 'fnThrowCaught', 'nestDomain'];
let async_id_cntr = 100;
const wTryCatch = process.argv.includes('--try-catch');
const wVerbose = process.argv.includes('--verbose');
const wNested = process.argv.includes('--nested');
const wNestedTryCatch = process.argv.includes('--nested-try-catch');
const wNestedVerbose = process.argv.includes('--nested-verbose');
const wDomain = process.argv.includes('--domain');
const wDisposedDomain = process.argv.includes('--disposed-domain');
const fnSelect =
(process.argv.find(e => e.indexOf('--fn=') === 0) || '').split('=')[1];
if (!fnNames.includes(fnSelect))
throw new Error('Incorrect fn name specified: ' + fnSelect);
const domain = wDomain && require('domain');
let flags = 0;
if (wTryCatch) flags |= kTryCatch;
if (wVerbose) flags |= kVerbose;
let nested_flags = 0;
if (wNestedTryCatch) nested_flags |= kTryCatch;
if (wNestedVerbose) nested_flags |= kVerbose;
let call_string =
`try-catch=${wTryCatch} verbose=${wVerbose} nested=${wNested} ` +
`nested-try-catch=${wNestedTryCatch} nested-verbose=${wNestedVerbose} ` +
`fn=${fnSelect}`;
print(call_string);
function getAsyncId() { return async_id_cntr++; }
function setUncaught() {
process.on('uncaughtException', er => print('caught error ' + er.message));
}
function fn() { return 42; }
function fnThrow() { throw new Error('fnThrow'); }
function fnThrowCaught() {
setUncaught();
throw new Error('fnThrowCaught');
}
function fnNested(call, flags) {
return function wrappedNested() {
return runMakeCallback(flags, getAsyncId(), getCallback(call), {});
}
}
function domainDisposedThrows(d) {
return function wrappedDisposedThrows() {
d.dispose();
throw new Error('domainDisposedThrows');
}
}
function nestDomain(flags) {
return function wrapped() {
const d = domain.create();
d.on('error', e => print('domain caught error: ' + e.message));
return d.run(() => {
return runMakeCallback(flags, getAsyncId(), domainDisposedThrows(d), {});
});
}
}
if (wNested) {
print(runMakeCallback(
flags, getAsyncId(), fnNested(fnSelect, nested_flags), {}));
return;
}
if (wDomain || fnSelect === 'nestDomain') {
print(runMakeCallback(0, getAsyncId(), nestDomain(flags), {}));
return;
}
print(runMakeCallback(flags, getAsyncId(), getCallback(fnSelect), {}));
function getCallback(call) {
return (() => {
if (call === 'fn')
return fn;
if (call === 'fnThrow')
return fnThrow;
if (call === 'fnThrowCaught')
return fnThrowCaught;
print('invalid call in fnNested: ' + call);
process.abort();
})();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.