Skip to content

Commit 346fc0a

Browse files
ExE-Bosstargos
authored andcommitted
lib: support returning Safe collections from C++
Co-authored-by: Antoine du Hamel <[email protected]> PR-URL: #36989 Refs: #36652 Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 726ef40 commit 346fc0a

File tree

5 files changed

+59
-0
lines changed

5 files changed

+59
-0
lines changed

src/env.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,29 @@ void Environment::CreateProperties() {
273273
CHECK(primordials->IsObject());
274274
set_primordials(primordials.As<Object>());
275275

276+
Local<String> prototype_string =
277+
FIXED_ONE_BYTE_STRING(isolate(), "prototype");
278+
279+
#define V(EnvPropertyName, PrimordialsPropertyName) \
280+
{ \
281+
Local<Value> ctor = \
282+
primordials.As<Object>() \
283+
->Get(ctx, \
284+
FIXED_ONE_BYTE_STRING(isolate(), PrimordialsPropertyName)) \
285+
.ToLocalChecked(); \
286+
CHECK(ctor->IsObject()); \
287+
Local<Value> prototype = \
288+
ctor.As<Object>()->Get(ctx, prototype_string).ToLocalChecked(); \
289+
CHECK(prototype->IsObject()); \
290+
set_##EnvPropertyName(prototype.As<Object>()); \
291+
}
292+
293+
V(primordials_safe_map_prototype_object, "SafeMap");
294+
V(primordials_safe_set_prototype_object, "SafeSet");
295+
V(primordials_safe_weak_map_prototype_object, "SafeWeakMap");
296+
V(primordials_safe_weak_set_prototype_object, "SafeWeakSet");
297+
#undef V
298+
276299
Local<Object> process_object =
277300
node::CreateProcessObject(this).FromMaybe(Local<Object>());
278301
set_process_object(process_object);

src/env.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,10 @@ constexpr size_t kFsStatsBufferLength =
478478
V(prepare_stack_trace_callback, v8::Function) \
479479
V(process_object, v8::Object) \
480480
V(primordials, v8::Object) \
481+
V(primordials_safe_map_prototype_object, v8::Object) \
482+
V(primordials_safe_set_prototype_object, v8::Object) \
483+
V(primordials_safe_weak_map_prototype_object, v8::Object) \
484+
V(primordials_safe_weak_set_prototype_object, v8::Object) \
481485
V(promise_hook_handler, v8::Function) \
482486
V(promise_reject_callback, v8::Function) \
483487
V(script_data_constructor_function, v8::Function) \

src/node_options.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,12 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
882882
});
883883

884884
Local<Map> options = Map::New(isolate);
885+
if (options
886+
->SetPrototype(context, env->primordials_safe_map_prototype_object())
887+
.IsNothing()) {
888+
return;
889+
}
890+
885891
for (const auto& item : _ppop_instance.options_) {
886892
Local<Value> value;
887893
const auto& option_info = item.second;
@@ -970,6 +976,12 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
970976
Local<Value> aliases;
971977
if (!ToV8Value(context, _ppop_instance.aliases_).ToLocal(&aliases)) return;
972978

979+
if (aliases.As<Object>()
980+
->SetPrototype(context, env->primordials_safe_map_prototype_object())
981+
.IsNothing()) {
982+
return;
983+
}
984+
973985
Local<Object> ret = Object::New(isolate);
974986
if (ret->Set(context, env->options_string(), options).IsNothing() ||
975987
ret->Set(context, env->aliases_string(), aliases).IsNothing()) {

src/uv.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ void GetErrMap(const FunctionCallbackInfo<Value>& args) {
8181
Isolate* isolate = env->isolate();
8282
Local<Context> context = env->context();
8383

84+
// This can't return a SafeMap, because the uv binding can be referenced
85+
// by user code by using `process.binding('uv').getErrorMap()`:
8486
Local<Map> err_map = Map::New(isolate);
8587

8688
size_t errors_len = arraysize(per_process::uv_errors_map);

test/parallel/test-options-binding.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Flags: --expose-internals
2+
'use strict';
3+
4+
const common = require('../common');
5+
const { primordials: { SafeMap } } = require('internal/test/binding');
6+
7+
const { options, aliases, getOptionValue } = require('internal/options');
8+
const assert = require('assert');
9+
10+
assert(options instanceof SafeMap,
11+
"require('internal/options').options is a SafeMap");
12+
13+
assert(aliases instanceof SafeMap,
14+
"require('internal/options').aliases is a SafeMap");
15+
16+
Map.prototype.get =
17+
common.mustNotCall('`getOptionValue` must not call user-mutable method');
18+
assert.strictEqual(getOptionValue('--expose-internals'), true);

0 commit comments

Comments
 (0)