test: add node::MakeCallback() test coverage
authorBen Noordhuis <info@bnoordhuis.nl>
Wed, 21 Oct 2015 23:30:19 +0000 (01:30 +0200)
committerJames M Snell <jasnell@gmail.com>
Fri, 30 Oct 2015 17:07:47 +0000 (10:07 -0700)
PR-URL: https://github.com/nodejs/node/pull/3478
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
test/addons/make-callback/binding.cc [new file with mode: 0644]
test/addons/make-callback/binding.gyp [new file with mode: 0644]
test/addons/make-callback/test.js [new file with mode: 0644]

diff --git a/test/addons/make-callback/binding.cc b/test/addons/make-callback/binding.cc
new file mode 100644 (file)
index 0000000..3012a39
--- /dev/null
@@ -0,0 +1,40 @@
+#include "node.h"
+#include "v8.h"
+
+#include "../../../src/util.h"
+
+#include <vector>
+
+namespace {
+
+void MakeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  CHECK(args[0]->IsObject());
+  CHECK(args[1]->IsFunction() || args[1]->IsString());
+  auto isolate = args.GetIsolate();
+  auto recv = args[0].As<v8::Object>();
+  std::vector<v8::Local<v8::Value>> argv;
+  for (size_t n = 2; n < static_cast<size_t>(args.Length()); n += 1) {
+    argv.push_back(args[n]);
+  }
+  v8::Local<v8::Value> result;
+  if (args[1]->IsFunction()) {
+    auto method = args[1].As<v8::Function>();
+    result =
+        node::MakeCallback(isolate, recv, method, argv.size(), argv.data());
+  } else if (args[1]->IsString()) {
+    auto method = args[1].As<v8::String>();
+    result =
+        node::MakeCallback(isolate, recv, method, argv.size(), argv.data());
+  } else {
+    UNREACHABLE();
+  }
+  args.GetReturnValue().Set(result);
+}
+
+void Initialize(v8::Local<v8::Object> target) {
+  NODE_SET_METHOD(target, "makeCallback", MakeCallback);
+}
+
+}  // namespace anonymous
+
+NODE_MODULE(binding, Initialize)
diff --git a/test/addons/make-callback/binding.gyp b/test/addons/make-callback/binding.gyp
new file mode 100644 (file)
index 0000000..3bfb844
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  'targets': [
+    {
+      'target_name': 'binding',
+      'sources': [ 'binding.cc' ]
+    }
+  ]
+}
diff --git a/test/addons/make-callback/test.js b/test/addons/make-callback/test.js
new file mode 100644 (file)
index 0000000..80ea0db
--- /dev/null
@@ -0,0 +1,61 @@
+'use strict';
+
+const common = require('../../common');
+const assert = require('assert');
+const vm = require('vm');
+const binding = require('./build/Release/binding');
+const makeCallback = binding.makeCallback;
+
+assert.strictEqual(42, makeCallback(process, common.mustCall(function() {
+  assert.strictEqual(0, arguments.length);
+  assert.strictEqual(this, process);
+  return 42;
+})));
+
+assert.strictEqual(42, makeCallback(process, common.mustCall(function(x) {
+  assert.strictEqual(1, arguments.length);
+  assert.strictEqual(this, process);
+  assert.strictEqual(x, 1337);
+  return 42;
+}), 1337));
+
+const recv = {
+  one: common.mustCall(function() {
+    assert.strictEqual(0, arguments.length);
+    assert.strictEqual(this, recv);
+    return 42;
+  }),
+  two: common.mustCall(function(x) {
+    assert.strictEqual(1, arguments.length);
+    assert.strictEqual(this, recv);
+    assert.strictEqual(x, 1337);
+    return 42;
+  }),
+};
+
+assert.strictEqual(42, makeCallback(recv, 'one'));
+assert.strictEqual(42, makeCallback(recv, 'two', 1337));
+
+// Check that the callback is made in the context of the receiver.
+const target = vm.runInNewContext(`
+    (function($Object) {
+      if (Object === $Object)
+        throw Error('bad');
+      return Object;
+    })
+`);
+assert.notStrictEqual(Object, makeCallback(process, target, Object));
+
+// Runs in inner context.
+const forward = vm.runInNewContext(`
+    (function(forward) {
+      return forward(Object);
+    })
+`);
+// Runs in outer context.
+const endpoint = function($Object) {
+  if (Object === $Object)
+    throw Error('bad');
+  return Object;
+};
+assert.strictEqual(Object, makeCallback(process, forward, endpoint));