From c584c3e08fa557eff7349e286defe625561cdbed Mon Sep 17 00:00:00 2001 From: cjihrig Date: Mon, 23 Nov 2015 14:58:18 -0500 Subject: [PATCH] util,src: allow lookup of hidden values 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 Reviewed-By: Ben Noordhuis --- lib/internal/util.js | 3 +++ src/node_util.cc | 19 +++++++++++++++++ test/parallel/test-util-internal.js | 32 +++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 test/parallel/test-util-internal.js diff --git a/lib/internal/util.js b/lib/internal/util.js index a31f22e6e9f186..5be073f18a2217 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -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) { diff --git a/src/node_util.cc b/src/node_util.cc index 19c3e3240a52af..a520b8d5f354ac 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -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& args) { @@ -28,6 +29,23 @@ static void IsPromise(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(args[0]->IsPromise()); } + +static void GetHiddenValue(const FunctionCallbackInfo& 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 obj = args[0].As(); + Local name = args[1].As(); + + args.GetReturnValue().Set(obj->GetHiddenValue(name)); +} + + void Initialize(Local target, Local unused, Local context) { @@ -35,6 +53,7 @@ void Initialize(Local 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 index 00000000000000..9ab883ec8b6dcd --- /dev/null +++ b/test/parallel/test-util-internal.js @@ -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));