util,src: allow lookup of hidden values
authorcjihrig <cjihrig@gmail.com>
Mon, 23 Nov 2015 19:58:18 +0000 (14:58 -0500)
committerMyles Borins <mborins@us.ibm.com>
Tue, 19 Jan 2016 19:52:28 +0000 (11:52 -0800)
This commit adds an internal util method that makes hidden
values in the C++ layer visible in JS.

PR-URL: https://github.com/nodejs/node/pull/3988
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Conflicts:
lib/internal/util.js

lib/internal/util.js
src/node_util.cc
test/parallel/test-util-internal.js [new file with mode: 0644]

index a31f22e..5be073f 100644 (file)
@@ -1,7 +1,10 @@
 'use strict';
 
+const binding = process.binding('util');
 const prefix = '(node) ';
 
+exports.getHiddenValue = binding.getHiddenValue;
+
 // All the internal deprecations have to use this function only, as this will
 // prepend the prefix to the actual message.
 exports.deprecate = function(fn, msg) {
index 19c3e32..a520b8d 100644 (file)
@@ -10,6 +10,7 @@ using v8::Context;
 using v8::FunctionCallbackInfo;
 using v8::Local;
 using v8::Object;
+using v8::String;
 using v8::Value;
 
 static void IsMapIterator(const FunctionCallbackInfo<Value>& args) {
@@ -28,6 +29,23 @@ static void IsPromise(const FunctionCallbackInfo<Value>& args) {
   args.GetReturnValue().Set(args[0]->IsPromise());
 }
 
+
+static void GetHiddenValue(const FunctionCallbackInfo<Value>& args) {
+  Environment* env = Environment::GetCurrent(args);
+
+  if (!args[0]->IsObject())
+    return env->ThrowTypeError("obj must be an object");
+
+  if (!args[1]->IsString())
+    return env->ThrowTypeError("name must be a string");
+
+  Local<Object> obj = args[0].As<Object>();
+  Local<String> name = args[1].As<String>();
+
+  args.GetReturnValue().Set(obj->GetHiddenValue(name));
+}
+
+
 void Initialize(Local<Object> target,
                 Local<Value> unused,
                 Local<Context> context) {
@@ -35,6 +53,7 @@ void Initialize(Local<Object> target,
   env->SetMethod(target, "isMapIterator", IsMapIterator);
   env->SetMethod(target, "isSetIterator", IsSetIterator);
   env->SetMethod(target, "isPromise", IsPromise);
+  env->SetMethod(target, "getHiddenValue", GetHiddenValue);
 }
 
 }  // namespace util
diff --git a/test/parallel/test-util-internal.js b/test/parallel/test-util-internal.js
new file mode 100644 (file)
index 0000000..9ab883e
--- /dev/null
@@ -0,0 +1,32 @@
+'use strict';
+// Flags: --expose_internals
+
+const common = require('../common');
+const assert = require('assert');
+const internalUtil = require('internal/util');
+
+function getHiddenValue(obj, name) {
+  return function() {
+    internalUtil.getHiddenValue(obj, name);
+  };
+}
+
+assert.throws(getHiddenValue(), /obj must be an object/);
+assert.throws(getHiddenValue(null, 'foo'), /obj must be an object/);
+assert.throws(getHiddenValue(undefined, 'foo'), /obj must be an object/);
+assert.throws(getHiddenValue('bar', 'foo'), /obj must be an object/);
+assert.throws(getHiddenValue(85, 'foo'), /obj must be an object/);
+assert.throws(getHiddenValue({}), /name must be a string/);
+assert.throws(getHiddenValue({}, null), /name must be a string/);
+assert.throws(getHiddenValue({}, []), /name must be a string/);
+assert.deepEqual(internalUtil.getHiddenValue({}, 'foo'), undefined);
+
+let arrowMessage;
+
+try {
+  require('../fixtures/syntax/bad_syntax');
+} catch (err) {
+  arrowMessage = internalUtil.getHiddenValue(err, 'arrowMessage');
+}
+
+assert(/bad_syntax\.js:1/.test(arrowMessage));