Skip to content

Commit

Permalink
util,src: allow lookup of hidden values
Browse files Browse the repository at this point in the history
This commit adds an internal util method that makes hidden
values in the C++ layer visible in JS.

PR-URL: #3988
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
  • Loading branch information
cjihrig authored and rvagg committed Dec 5, 2015
1 parent a863e8d commit c584c3e
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lib/internal/util.js
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down
19 changes: 19 additions & 0 deletions src/node_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -28,13 +29,31 @@ 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) {
Environment* env = Environment::GetCurrent(context);
env->SetMethod(target, "isMapIterator", IsMapIterator);
env->SetMethod(target, "isSetIterator", IsSetIterator);
env->SetMethod(target, "isPromise", IsPromise);
env->SetMethod(target, "getHiddenValue", GetHiddenValue);
}

} // namespace util
Expand Down
32 changes: 32 additions & 0 deletions test/parallel/test-util-internal.js
Original file line number Diff line number Diff line change
@@ -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));

0 comments on commit c584c3e

Please sign in to comment.