-
Notifications
You must be signed in to change notification settings - Fork 30k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
`napi_instanceof()` is insufficient for reliably establishing the data type to which a pointer stored with `napi_wrap()` or `napi_create_external()` inside a JavaScript object points. Thus, we need a way to "mark" an object with a value that, when later retrieved, can unambiguously tell us whether it is safe to cast the pointer stored inside it to a certain structure. Such a check must survive loading/unloading/multiple instances of an addon, so we use UUIDs chosen *a priori*. Fixes: #28164 Co-authored-by: Anna Henningsen <github@addaleax.net> PR-URL: #28237 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Signed-off-by: Gabriel Schulhof <gabriel.schulhof@intel.com>
- Loading branch information
Showing
14 changed files
with
545 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
'targets': [ | ||
{ | ||
'target_name': 'binding', | ||
'sources': [ '../type-tag/binding.c' ] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
'use strict'; | ||
const common = require('../../common.js'); | ||
|
||
let binding; | ||
try { | ||
binding = require(`./build/${common.buildType}/binding`); | ||
} catch { | ||
console.error(`${__filename}: Binding failed to load`); | ||
process.exit(0); | ||
} | ||
|
||
const bench = common.createBenchmark(main, { | ||
n: [1e5, 1e6, 1e7], | ||
}); | ||
|
||
function main({ n }) { | ||
binding.checkObjectTag(n, bench, bench.start, bench.end); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
#include <assert.h> | ||
#define NAPI_EXPERIMENTAL | ||
#include <node_api.h> | ||
|
||
#define NAPI_CALL(call) \ | ||
do { \ | ||
napi_status status = call; \ | ||
assert(status == napi_ok && #call " failed"); \ | ||
} while (0); | ||
|
||
#define EXPORT_FUNC(env, exports, name, func) \ | ||
do { \ | ||
napi_value js_func; \ | ||
NAPI_CALL(napi_create_function((env), \ | ||
(name), \ | ||
NAPI_AUTO_LENGTH, \ | ||
(func), \ | ||
NULL, \ | ||
&js_func)); \ | ||
NAPI_CALL(napi_set_named_property((env), \ | ||
(exports), \ | ||
(name), \ | ||
js_func)); \ | ||
} while (0); | ||
|
||
static const napi_type_tag tag = { | ||
0xe7ecbcd5954842f6, 0x9e75161c9bf27282 | ||
}; | ||
|
||
static napi_value TagObject(napi_env env, napi_callback_info info) { | ||
size_t argc = 4; | ||
napi_value argv[4]; | ||
uint32_t n; | ||
uint32_t index; | ||
napi_handle_scope scope; | ||
|
||
NAPI_CALL(napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); | ||
NAPI_CALL(napi_get_value_uint32(env, argv[0], &n)); | ||
NAPI_CALL(napi_open_handle_scope(env, &scope)); | ||
napi_value objects[n]; | ||
for (index = 0; index < n; index++) { | ||
NAPI_CALL(napi_create_object(env, &objects[index])); | ||
} | ||
|
||
// Time the object tag creation. | ||
NAPI_CALL(napi_call_function(env, argv[1], argv[2], 0, NULL, NULL)); | ||
for (index = 0; index < n; index++) { | ||
NAPI_CALL(napi_type_tag_object(env, objects[index], &tag)); | ||
} | ||
NAPI_CALL(napi_call_function(env, argv[1], argv[3], 1, &argv[0], NULL)); | ||
|
||
NAPI_CALL(napi_close_handle_scope(env, scope)); | ||
return NULL; | ||
} | ||
|
||
static napi_value CheckObjectTag(napi_env env, napi_callback_info info) { | ||
size_t argc = 4; | ||
napi_value argv[4]; | ||
uint32_t n; | ||
uint32_t index; | ||
bool is_of_type; | ||
|
||
NAPI_CALL(napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); | ||
NAPI_CALL(napi_get_value_uint32(env, argv[0], &n)); | ||
napi_value object; | ||
NAPI_CALL(napi_create_object(env, &object)); | ||
NAPI_CALL(napi_type_tag_object(env, object, &tag)); | ||
|
||
// Time the object tag checking. | ||
NAPI_CALL(napi_call_function(env, argv[1], argv[2], 0, NULL, NULL)); | ||
for (index = 0; index < n; index++) { | ||
NAPI_CALL(napi_check_object_type_tag(env, object, &tag, &is_of_type)); | ||
assert(is_of_type && " type mismatch"); | ||
} | ||
NAPI_CALL(napi_call_function(env, argv[1], argv[3], 1, &argv[0], NULL)); | ||
|
||
return NULL; | ||
} | ||
|
||
NAPI_MODULE_INIT() { | ||
EXPORT_FUNC(env, exports, "tagObject", TagObject); | ||
EXPORT_FUNC(env, exports, "checkObjectTag", CheckObjectTag); | ||
return exports; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
'targets': [ | ||
{ | ||
'target_name': 'binding', | ||
'sources': [ 'binding.c' ] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
'use strict'; | ||
const common = require('../../common.js'); | ||
|
||
let binding; | ||
try { | ||
binding = require(`./build/${common.buildType}/binding`); | ||
} catch { | ||
console.error(`${__filename}: Binding failed to load`); | ||
process.exit(0); | ||
} | ||
|
||
const bench = common.createBenchmark(main, { | ||
n: [1e5, 1e6, 1e7], | ||
}); | ||
|
||
function main({ n }) { | ||
binding.checkObjectTag(n, bench, bench.start, bench.end); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
'use strict'; | ||
const common = require('../../common.js'); | ||
|
||
let binding; | ||
try { | ||
binding = require(`./build/${common.buildType}/binding`); | ||
} catch { | ||
console.error(`${__filename}: Binding failed to load`); | ||
process.exit(0); | ||
} | ||
|
||
const bench = common.createBenchmark(main, { | ||
n: [1e3, 1e4, 1e5], | ||
}); | ||
|
||
function main({ n }) { | ||
binding.tagObject(n, bench, bench.start, bench.end); | ||
} |
Oops, something went wrong.