Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are Node.JS's getHiddenValue and setHiddenValue functions, which wrap V8's GetPrivate and SetPrivate?

For very complicated reasons, I'm researching to better understand the internals of Node.JS, and have discovered two functions of unknown purpose.

These are the functions and how to access them.

process.binding('util').setHiddenValue
process.binding('util').getHiddenValue

From their native code declarations, it's clear they wrap the following V8 functions:

v8::Object::SetPrivate
v8::Object::GetPrivate

I've also made a little snippet that kind-of shows what they can do.

'use strict';

var binding = process.binding('util');

var o = {};

binding.setHiddenValue(o, 7, 'testing123');

console.log(binding.getHiddenValue(o, 7)); // returns 'testing123'

However, I've been unable to find any documentation on what these so-called "hidden values" are for, or otherwise determine why they are needed in Node or in V8.

Can anyone shed some light on their true purpose?

For reference, these appears to be the only valid values you can use to associate the data by (higher than 7 will crash):

alpn_buffer_private_symbol: 0,
arrow_message_private_symbol: 1,
contextify_context_private_symbol: 2,
contextify_global_private_symbol: 3,
decorated_private_symbol: 4,
npn_buffer_private_symbol: 5,
processed_private_symbol: 6,
selected_npn_buffer_private_symbol: 7,
like image 722
Alexander O'Mara Avatar asked Dec 19 '16 18:12

Alexander O'Mara


1 Answers

From https://v8docs.nodesource.com/io.js-3.0/db/d85/classv8_1_1_object.html#a98ad2e2a82b457a733bee13e4c2ba876 :

Access hidden properties on JavaScript objects. These properties are hidden from the executing JavaScript and only accessible through the V8 C++ API. Hidden properties introduced by V8 internally (for example the identity hash) are prefixed with "v8::".

However, they will not be used in v7 and beyond -- https://github.com/nodejs/node/commit/924cc6c6335e58f61b04d2f41d348bd6b8be98a1

To compare with vanilla JS:

const foo = Object.create({}, {
  privBar: {value: 'private'},
  publBar: {value: 'public', enumerable: true}
})

console.log(foo.privBar) // 'private'
console.log(foo.publBar) // 'public'

Notice that we can still access privBar because it isn't really private. But if we JSON.stringify(foo) then only publBar will show up in the serialization. With the v8 functions you get an even more private privBar.

like image 149
James Sumners Avatar answered Oct 05 '22 22:10

James Sumners