From e5c872ffdbda16e058a706c4c55232eeb2ab17b7 Mon Sep 17 00:00:00 2001 From: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> Date: Mon, 18 Jan 2021 00:30:00 +0100 Subject: [PATCH] =?UTF-8?q?lib:=20support=C2=A0returning=20Safe=C2=A0colle?= =?UTF-8?q?ctions=20from=C2=A0C++?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/env.cc | 23 +++++++++++++++++++++++ src/env.h | 4 ++++ src/node_options.cc | 6 ++++++ src/uv.cc | 2 ++ test/parallel/test-options-binding.js | 16 ++++++++++++++++ 5 files changed, 51 insertions(+) create mode 100644 test/parallel/test-options-binding.js diff --git a/src/env.cc b/src/env.cc index 7e89c2828f2003..433807ccb0e926 100644 --- a/src/env.cc +++ b/src/env.cc @@ -273,6 +273,29 @@ void Environment::CreateProperties() { CHECK(primordials->IsObject()); set_primordials(primordials.As()); + Local prototype_string = + FIXED_ONE_BYTE_STRING(isolate(), "prototype"); + +#define V(EnvPropertyName, PrimordialsPropertyName) \ + { \ + Local ctor = \ + primordials \ + ->Get(ctx, \ + FIXED_ONE_BYTE_STRING(isolate(), PrimordialsPropertyName)) \ + .ToLocalChecked(); \ + CHECK(ctor->IsObject()); \ + Local prototype = \ + ctor.As()->Get(ctx, prototype_string).ToLocalChecked(); \ + CHECK(prototype->IsObject()); \ + set_##EnvPropertyName(prototype.As()); \ + } + + V(primordials_safe_map_prototype_object, "SafeMap"); + V(primordials_safe_set_prototype_object, "SafeSet"); + V(primordials_safe_weak_map_prototype_object, "SafeWeakMap"); + V(primordials_safe_weak_set_prototype_object, "SafeWeakSet"); +#undef V + Local process_object = node::CreateProcessObject(this).FromMaybe(Local()); set_process_object(process_object); diff --git a/src/env.h b/src/env.h index 6d554f3fcfc04b..514a3871b4ee05 100644 --- a/src/env.h +++ b/src/env.h @@ -550,6 +550,10 @@ constexpr size_t kFsStatsBufferLength = V(prepare_stack_trace_callback, v8::Function) \ V(process_object, v8::Object) \ V(primordials, v8::Object) \ + V(primordials_safe_map_prototype_object, v8::Object) \ + V(primordials_safe_set_prototype_object, v8::Object) \ + V(primordials_safe_weak_map_prototype_object, v8::Object) \ + V(primordials_safe_weak_set_prototype_object, v8::Object) \ V(promise_hook_handler, v8::Function) \ V(promise_reject_callback, v8::Function) \ V(script_data_constructor_function, v8::Function) \ diff --git a/src/node_options.cc b/src/node_options.cc index 9f59e7ee4f8aa8..a59efc66d82fac 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -917,6 +917,12 @@ void GetOptions(const FunctionCallbackInfo& args) { }); Local options = Map::New(isolate); + if (options + ->SetPrototype(context, env->primordials_safe_map_prototype_object()) + .IsNothing()) { + return; + } + for (const auto& item : _ppop_instance.options_) { Local value; const auto& option_info = item.second; diff --git a/src/uv.cc b/src/uv.cc index e4b428f339b578..7347826cab0fc8 100644 --- a/src/uv.cc +++ b/src/uv.cc @@ -81,6 +81,8 @@ void GetErrMap(const FunctionCallbackInfo& args) { Isolate* isolate = env->isolate(); Local context = env->context(); + // This can't return a SafeMap, because the uv binding can be referenced + // by user code by using `process.binding('uv').getErrorMap()`: Local err_map = Map::New(isolate); size_t errors_len = arraysize(per_process::uv_errors_map); diff --git a/test/parallel/test-options-binding.js b/test/parallel/test-options-binding.js new file mode 100644 index 00000000000000..de9aafd7f43bb8 --- /dev/null +++ b/test/parallel/test-options-binding.js @@ -0,0 +1,16 @@ +// Flags: --expose-internals +'use strict'; + +require('../common'); +const { internalBinding, primordials } = require('internal/test/binding'); +const { + SafeMap, +} = primordials; + +const options = internalBinding('options'); +const assert = require('assert'); + +assert( + options.getOptions() instanceof SafeMap, + "internalBinding('options').getOptions() returns SafeMap", +);