Skip to content

Instantly share code, notes, and snippets.

@ranisalt
Last active March 3, 2016 03:46
Show Gist options
  • Save ranisalt/2b22438c35b952169554 to your computer and use it in GitHub Desktop.
Save ranisalt/2b22438c35b952169554 to your computer and use it in GitHub Desktop.
{
"targets": [
{
"target_name": "promises",
"sources": ["promises.cpp"],
"include_dirs": ["<!(node -e \"require('nan')\")"]
}
]
}
{
"name": "nan-promise",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"bindings": "^1.2.1",
"nan": "^2.2.0",
"tap": "^5.7.0"
},
"devDependencies": {},
"scripts": {
"test": "tap spec.js"
},
"author": "",
"license": "Unlicense"
}
#include <nan.h>
#include <node.h>
class PromiseAsyncWorker final: public Nan::AsyncWorker {
public:
PromiseAsyncWorker(bool resolve, int value):
Nan::AsyncWorker{nullptr}, resolve{resolve}, value{value} { }
void Execute() override {
if (not resolve) {
SetErrorMessage("Promise is set to be rejected");
}
}
void HandleOKCallback() override {
Nan::HandleScope scope;
auto promise = GetFromPersistent(1).As<v8::Promise::Resolver>();
promise->Resolve(Nan::GetCurrentContext(), Nan::New(value));
v8::Isolate::GetCurrent()->RunMicrotasks();
}
void HandleErrorCallback() override {
Nan::HandleScope scope;
auto promise = GetFromPersistent(1).As<v8::Promise::Resolver>();
promise->Reject(Nan::GetCurrentContext(), Nan::New(ErrorMessage()).ToLocalChecked());
v8::Isolate::GetCurrent()->RunMicrotasks();
}
private:
bool resolve;
int value;
};
NAN_METHOD(Run) {
auto resolve = Nan::To<bool>(info[0]).FromJust();
auto value = Nan::To<int>(info[1]).FromJust();
auto worker = new PromiseAsyncWorker(resolve, value);
auto resolver = v8::Promise::Resolver::New(Nan::GetCurrentContext()).ToLocalChecked();
worker->SaveToPersistent(1, resolver);
Nan::AsyncQueueWorker(worker);
info.GetReturnValue().Set(resolver->GetPromise());
}
NAN_MODULE_INIT(init) {
Nan::Export(target, "run", Run);
}
NODE_MODULE(promises, init)
const prom = require('bindings')('promises');
const t = require('tap');
t.test('js promise + setInterval', t => {
'use strict';
t.plan(1);
let timer = setInterval(() => t.fail("Interval expired first"), 2e3);
return Promise.resolve(42).then(value => {
clearInterval(timer);
t.pass("Promise resolved first");
});
});
t.test('js promise + setTimeout', t => {
'use strict';
t.plan(1);
let timer = setTimeout(() => t.fail("Timeout expired first"), 2e3);
return Promise.resolve(42).then(value => {
clearTimeout(timer);
t.pass("Promise resolved first");
});
});
t.test('metal promise + setInterval', t => {
'use strict';
t.plan(1);
let timer = setInterval(() => t.fail("Interval expired first"), 2e3);
return prom.run(true, 42).then(value => {
clearInterval(timer);
t.pass("Promise resolved first");
});
});
t.test('metal promise reject + setInterval', t => {
'use strict';
t.plan(1);
let timer = setInterval(() => t.fail("Interval expired first"), 2e3);
return prom.run(false, 42).catch(() => {
clearInterval(timer);
t.pass("Promise resolved first");
});
});
t.test('metal promise + setTimeout', t => {
'use strict';
t.plan(1);
let timer = setTimeout(() => t.fail("Timeout expired first"), 2e3);
return prom.run(true, 42).then(value => {
clearTimeout(timer);
t.pass("Promise resolved first");
});
});
t.test('metal promise reject + setTimeout', t => {
'use strict';
t.plan(1);
let timer = setTimeout(() => t.fail("Timeout expired first"), 2e3);
return prom.run(false, 42).catch(() => {
clearTimeout(timer);
t.pass("Promise resolved first");
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment