[api] Implement v8::Context::HasTemplateLiteralObject
V8-side implementation for trusted types fromLiteral. Create a separate JSArray root map for template literal objects to clearly identify untampered template literals belonging to a given context. Given that template literals are frozen arrays with a 'raw' property, we don't expect additional polymorphism. Drive-by-fix: Avoid ValidateElements call in NewJSArrayWithElements. Bug: chromium:1271149 Change-Id: I327b0fd99a2db3b57d35efa9293ddf2f14e555ea Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3572044 Reviewed-by: Shu-yu Guo <syg@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Auto-Submit: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/main@{#83383}
This commit is contained in:
parent
e2b7092f52
commit
4e23f53cdf
@ -290,6 +290,7 @@ class V8_EXPORT Context : public Data {
|
||||
Local<Function> after_hook,
|
||||
Local<Function> resolve_hook);
|
||||
|
||||
bool HasTemplateLiteralObject(Local<Value> object);
|
||||
/**
|
||||
* Stack-allocated class which sets the execution context for all
|
||||
* operations executed within a local scope.
|
||||
|
@ -6715,6 +6715,14 @@ void v8::Context::SetPromiseHooks(Local<Function> init_hook,
|
||||
#endif // V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
|
||||
}
|
||||
|
||||
bool Context::HasTemplateLiteralObject(Local<Value> object) {
|
||||
i::DisallowGarbageCollection no_gc;
|
||||
i::Object i_object = *Utils::OpenHandle(*object);
|
||||
if (!i_object.IsJSArray()) return false;
|
||||
return Utils::OpenHandle(this)->native_context().HasTemplateLiteralObject(
|
||||
i::JSArray::cast(i_object));
|
||||
}
|
||||
|
||||
MaybeLocal<Context> metrics::Recorder::GetContext(
|
||||
Isolate* v8_isolate, metrics::Recorder::ContextId id) {
|
||||
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
|
@ -2730,6 +2730,10 @@ Handle<JSObject> Factory::NewJSObjectFromMap(
|
||||
InitializeJSObjectFromMap(js_obj, *empty_fixed_array(), *map);
|
||||
|
||||
DCHECK(js_obj.HasFastElements() ||
|
||||
(isolate()->bootstrapper()->IsActive() ||
|
||||
*map == isolate()
|
||||
->raw_native_context()
|
||||
.js_array_template_literal_object_map()) ||
|
||||
js_obj.HasTypedArrayOrRabGsabTypedArrayElements() ||
|
||||
js_obj.HasFastStringWrapperElements() ||
|
||||
js_obj.HasFastArgumentsElements() || js_obj.HasDictionaryElements() ||
|
||||
@ -2802,7 +2806,9 @@ Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArrayBase> elements,
|
||||
AllocationType allocation) {
|
||||
Handle<JSArray> array = NewJSArrayWithUnverifiedElements(
|
||||
elements, elements_kind, length, allocation);
|
||||
#ifdef ENABLE_SLOW_DCHECKS
|
||||
JSObject::ValidateElements(*array);
|
||||
#endif
|
||||
return array;
|
||||
}
|
||||
|
||||
@ -2816,8 +2822,14 @@ Handle<JSArray> Factory::NewJSArrayWithUnverifiedElements(
|
||||
JSFunction array_function = native_context.array_function();
|
||||
map = array_function.initial_map();
|
||||
}
|
||||
Handle<JSArray> array = Handle<JSArray>::cast(
|
||||
NewJSObjectFromMap(handle(map, isolate()), allocation));
|
||||
return NewJSArrayWithUnverifiedElements(handle(map, isolate()), elements,
|
||||
length, allocation);
|
||||
}
|
||||
|
||||
Handle<JSArray> Factory::NewJSArrayWithUnverifiedElements(
|
||||
Handle<Map> map, Handle<FixedArrayBase> elements, int length,
|
||||
AllocationType allocation) {
|
||||
auto array = Handle<JSArray>::cast(NewJSObjectFromMap(map, allocation));
|
||||
DisallowGarbageCollection no_gc;
|
||||
JSArray raw = *array;
|
||||
raw.set_elements(*elements);
|
||||
@ -2825,6 +2837,23 @@ Handle<JSArray> Factory::NewJSArrayWithUnverifiedElements(
|
||||
return array;
|
||||
}
|
||||
|
||||
Handle<JSArray> Factory::NewJSArrayForTemplateLiteralArray(
|
||||
Handle<FixedArray> cooked_strings, Handle<FixedArray> raw_strings) {
|
||||
Handle<JSArray> raw_object =
|
||||
NewJSArrayWithElements(raw_strings, PACKED_ELEMENTS,
|
||||
raw_strings->length(), AllocationType::kOld);
|
||||
JSObject::SetIntegrityLevel(raw_object, FROZEN, kThrowOnError).ToChecked();
|
||||
|
||||
Handle<NativeContext> native_context = isolate()->native_context();
|
||||
Handle<JSArray> template_object = NewJSArrayWithUnverifiedElements(
|
||||
handle(native_context->js_array_template_literal_object_map(), isolate()),
|
||||
cooked_strings, cooked_strings->length(), AllocationType::kOld);
|
||||
TemplateLiteralObject::SetRaw(template_object, raw_object);
|
||||
DCHECK_EQ(template_object->map(),
|
||||
native_context->js_array_template_literal_object_map());
|
||||
return template_object;
|
||||
}
|
||||
|
||||
void Factory::NewJSArrayStorage(Handle<JSArray> array, int length, int capacity,
|
||||
ArrayStorageAllocationMode mode) {
|
||||
DCHECK(capacity >= length);
|
||||
|
@ -606,6 +606,9 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
|
||||
ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND,
|
||||
AllocationType allocation = AllocationType::kYoung);
|
||||
|
||||
Handle<JSArray> NewJSArrayForTemplateLiteralArray(
|
||||
Handle<FixedArray> cooked_strings, Handle<FixedArray> raw_strings);
|
||||
|
||||
void NewJSArrayStorage(
|
||||
Handle<JSArray> array, int length, int capacity,
|
||||
ArrayStorageAllocationMode mode = DONT_INITIALIZE_ARRAY_ELEMENTS);
|
||||
@ -1141,6 +1144,9 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
|
||||
Handle<JSArray> NewJSArrayWithUnverifiedElements(
|
||||
Handle<FixedArrayBase> elements, ElementsKind elements_kind, int length,
|
||||
AllocationType allocation = AllocationType::kYoung);
|
||||
Handle<JSArray> NewJSArrayWithUnverifiedElements(
|
||||
Handle<Map> map, Handle<FixedArrayBase> elements, int length,
|
||||
AllocationType allocation = AllocationType::kYoung);
|
||||
|
||||
// Creates the backing storage for a JSArray. This handle must be discarded
|
||||
// before returning the JSArray reference to code outside Factory, which might
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include "src/objects/js-weak-refs.h"
|
||||
#include "src/objects/ordered-hash-table.h"
|
||||
#include "src/objects/property-cell.h"
|
||||
#include "src/objects/property-descriptor.h"
|
||||
#include "src/objects/slots-inl.h"
|
||||
#include "src/objects/swiss-name-dictionary-inl.h"
|
||||
#include "src/objects/templates.h"
|
||||
@ -1774,9 +1775,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
native_context()->set_initial_array_prototype(*proto);
|
||||
|
||||
InitializeJSArrayMaps(isolate_, native_context(),
|
||||
|
||||
handle(array_function->initial_map(), isolate_));
|
||||
|
||||
SimpleInstallFunction(isolate_, array_function, "isArray",
|
||||
Builtin::kArrayIsArray, 1, true);
|
||||
SimpleInstallFunction(isolate_, array_function, "from", Builtin::kArrayFrom,
|
||||
@ -5794,6 +5793,58 @@ bool Genesis::InstallABunchOfRandomThings() {
|
||||
native_context()->set_data_property_descriptor_map(*map);
|
||||
}
|
||||
|
||||
{
|
||||
// -- TemplateLiteral JSArray Map
|
||||
Handle<JSFunction> array_function(native_context()->array_function(),
|
||||
isolate());
|
||||
Handle<Map> template_map(array_function->initial_map(), isolate_);
|
||||
template_map = Map::CopyAsElementsKind(isolate_, template_map,
|
||||
PACKED_ELEMENTS, OMIT_TRANSITION);
|
||||
template_map->set_instance_size(template_map->instance_size() +
|
||||
kTaggedSize);
|
||||
// Temporarily instantiate full template_literal_object to get the final
|
||||
// map.
|
||||
auto template_object =
|
||||
Handle<JSArray>::cast(factory()->NewJSObjectFromMap(template_map));
|
||||
{
|
||||
DisallowGarbageCollection no_gc;
|
||||
JSArray raw = *template_object;
|
||||
raw.set_elements(ReadOnlyRoots(isolate()).empty_fixed_array());
|
||||
raw.set_length(Smi::FromInt(0));
|
||||
}
|
||||
|
||||
// Install a "raw" data property for {raw_object} on {template_object}.
|
||||
// See ES#sec-gettemplateobject.
|
||||
PropertyDescriptor raw_desc;
|
||||
// Use arbrirary object {template_object} as ".raw" value.
|
||||
raw_desc.set_value(template_object);
|
||||
raw_desc.set_configurable(false);
|
||||
raw_desc.set_enumerable(false);
|
||||
raw_desc.set_writable(false);
|
||||
JSArray::DefineOwnProperty(isolate(), template_object,
|
||||
factory()->raw_string(), &raw_desc,
|
||||
Just(kThrowOnError))
|
||||
.ToChecked();
|
||||
|
||||
// Freeze the {template_object} as well.
|
||||
JSObject::SetIntegrityLevel(template_object, FROZEN, kThrowOnError)
|
||||
.ToChecked();
|
||||
{
|
||||
DisallowGarbageCollection no_gc;
|
||||
// Verify TemplateLiteralObject::kRawFieldOffset
|
||||
DescriptorArray desc = template_object->map().instance_descriptors();
|
||||
InternalIndex descriptor_index =
|
||||
desc.Search(*factory()->raw_string(), desc.number_of_descriptors());
|
||||
FieldIndex index =
|
||||
FieldIndex::ForDescriptor(template_object->map(), descriptor_index);
|
||||
CHECK(index.is_inobject());
|
||||
CHECK_EQ(index.offset(), TemplateLiteralObject::kRawFieldOffset);
|
||||
}
|
||||
|
||||
native_context()->set_js_array_template_literal_object_map(
|
||||
template_object->map());
|
||||
}
|
||||
|
||||
// Create a constructor for RegExp results (a variant of Array that
|
||||
// predefines the properties index, input, and groups).
|
||||
{
|
||||
|
@ -426,6 +426,10 @@ Handle<Object> Context::Lookup(Handle<Context> context, Handle<String> name,
|
||||
return Handle<Object>::null();
|
||||
}
|
||||
|
||||
bool NativeContext::HasTemplateLiteralObject(JSArray array) {
|
||||
return array.map() == js_array_template_literal_object_map();
|
||||
}
|
||||
|
||||
void NativeContext::AddOptimizedCode(CodeT code) {
|
||||
DCHECK(CodeKindCanDeoptimize(code.kind()));
|
||||
DCHECK(code.next_code_link().IsUndefined());
|
||||
|
@ -178,6 +178,8 @@ enum ContextLookupFlags {
|
||||
js_array_packed_double_elements_map) \
|
||||
V(JS_ARRAY_HOLEY_DOUBLE_ELEMENTS_MAP_INDEX, Map, \
|
||||
js_array_holey_double_elements_map) \
|
||||
V(JS_ARRAY_TEMPLATE_LITERAL_OBJECT_MAP, Map, \
|
||||
js_array_template_literal_object_map) \
|
||||
V(JS_ATOMICS_CONDITION_MAP, Map, js_atomics_condition_map) \
|
||||
V(JS_ATOMICS_MUTEX_MAP, Map, js_atomics_mutex_map) \
|
||||
V(JS_MAP_FUN_INDEX, JSFunction, js_map_fun) \
|
||||
@ -746,6 +748,8 @@ class NativeContext : public Context {
|
||||
inline Map TypedArrayElementsKindToRabGsabCtorMap(
|
||||
ElementsKind element_kind) const;
|
||||
|
||||
bool HasTemplateLiteralObject(JSArray array);
|
||||
|
||||
// Dispatched behavior.
|
||||
DECL_PRINTER(NativeContext)
|
||||
DECL_VERIFIER(NativeContext)
|
||||
|
@ -73,6 +73,14 @@ void JSArrayIterator::set_kind(IterationKind kind) {
|
||||
set_raw_kind(static_cast<int>(kind));
|
||||
}
|
||||
|
||||
// static
|
||||
void TemplateLiteralObject::SetRaw(Handle<JSArray> template_object,
|
||||
Handle<JSArray> raw_object) {
|
||||
TaggedField<Object, kRawFieldOffset>::store(*template_object, *raw_object);
|
||||
CONDITIONAL_WRITE_BARRIER(*template_object, kRawFieldOffset, *raw_object,
|
||||
UPDATE_WRITE_BARRIER);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -159,6 +159,14 @@ class JSArrayIterator
|
||||
TQ_OBJECT_CONSTRUCTORS(JSArrayIterator)
|
||||
};
|
||||
|
||||
// Helper class for JSArrays that are template literal objects
|
||||
class TemplateLiteralObject {
|
||||
public:
|
||||
static const int kRawFieldOffset = JSArray::kLengthOffset + kTaggedSize;
|
||||
static inline void SetRaw(Handle<JSArray> template_object,
|
||||
Handle<JSArray> raw_object);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -75,33 +75,10 @@ Handle<JSArray> TemplateObjectDescription::GetTemplateObject(
|
||||
|
||||
// Create the raw object from the {raw_strings}.
|
||||
Handle<FixedArray> raw_strings(description->raw_strings(), isolate);
|
||||
Handle<JSArray> raw_object = isolate->factory()->NewJSArrayWithElements(
|
||||
raw_strings, PACKED_ELEMENTS, raw_strings->length(),
|
||||
AllocationType::kOld);
|
||||
|
||||
// Create the template object from the {cooked_strings}.
|
||||
Handle<FixedArray> cooked_strings(description->cooked_strings(), isolate);
|
||||
Handle<JSArray> template_object = isolate->factory()->NewJSArrayWithElements(
|
||||
cooked_strings, PACKED_ELEMENTS, cooked_strings->length(),
|
||||
AllocationType::kOld);
|
||||
|
||||
// Freeze the {raw_object}.
|
||||
JSObject::SetIntegrityLevel(raw_object, FROZEN, kThrowOnError).ToChecked();
|
||||
|
||||
// Install a "raw" data property for {raw_object} on {template_object}.
|
||||
PropertyDescriptor raw_desc;
|
||||
raw_desc.set_value(raw_object);
|
||||
raw_desc.set_configurable(false);
|
||||
raw_desc.set_enumerable(false);
|
||||
raw_desc.set_writable(false);
|
||||
JSArray::DefineOwnProperty(isolate, template_object,
|
||||
isolate->factory()->raw_string(), &raw_desc,
|
||||
Just(kThrowOnError))
|
||||
.ToChecked();
|
||||
|
||||
// Freeze the {template_object} as well.
|
||||
JSObject::SetIntegrityLevel(template_object, FROZEN, kThrowOnError)
|
||||
.ToChecked();
|
||||
Handle<JSArray> template_object =
|
||||
isolate->factory()->NewJSArrayForTemplateLiteralArray(cooked_strings,
|
||||
raw_strings);
|
||||
|
||||
// Insert the template object into the template weakmap.
|
||||
Handle<CachedTemplateObject> cached_template;
|
||||
|
@ -238,6 +238,7 @@ v8_source_set("unittests_sources") {
|
||||
"api/access-check-unittest.cc",
|
||||
"api/accessor-unittest.cc",
|
||||
"api/api-icu-unittest.cc",
|
||||
"api/context-unittest.cc",
|
||||
"api/deserialize-unittest.cc",
|
||||
"api/exception-unittest.cc",
|
||||
"api/gc-callbacks-unittest.cc",
|
||||
|
96
test/unittests/api/context-unittest.cc
Normal file
96
test/unittests/api/context-unittest.cc
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "include/libplatform/libplatform.h"
|
||||
#include "include/v8-context.h"
|
||||
#include "include/v8-data.h"
|
||||
#include "include/v8-isolate.h"
|
||||
#include "include/v8-local-handle.h"
|
||||
#include "include/v8-value.h"
|
||||
#include "test/unittests/test-utils.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
using ContextTest = v8::TestWithIsolate;
|
||||
|
||||
TEST_F(ContextTest, HasTemplateLiteralObjectBasic) {
|
||||
v8::Local<v8::Context> context = v8::Context::New(isolate());
|
||||
v8::Context::Scope scope(context);
|
||||
ASSERT_FALSE(
|
||||
context->HasTemplateLiteralObject(v8::Number::New(isolate(), 1)));
|
||||
ASSERT_FALSE(context->HasTemplateLiteralObject(v8::String::Empty(isolate())));
|
||||
ASSERT_FALSE(
|
||||
context->HasTemplateLiteralObject(v8::Array::New(isolate(), 10)));
|
||||
}
|
||||
|
||||
TEST_F(ContextTest, HasTemplateLiteralObject) {
|
||||
const char* source = R"(
|
||||
function ret(literal) {
|
||||
return literal;
|
||||
};
|
||||
ret`one_${'two'}_three`;
|
||||
)";
|
||||
const char* otherObject1Source = R"(
|
||||
Object.freeze(
|
||||
Object.defineProperty(['one_', '_three'], 'raw', {
|
||||
value: ['asdf'],
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
})
|
||||
);
|
||||
)";
|
||||
const char* otherObject2Source = R"(
|
||||
Object.freeze(
|
||||
Object.defineProperty(['one_', '_three'], 'raw', {
|
||||
get() { return ['asdf']; },
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
})
|
||||
);
|
||||
)";
|
||||
|
||||
v8::Local<v8::Context> context1 = v8::Context::New(isolate());
|
||||
v8::Local<v8::Value> templateLiteral1;
|
||||
v8::Local<v8::Value> templateLiteral1_2;
|
||||
v8::Local<v8::Value> otherObject1_ctx1;
|
||||
v8::Local<v8::Value> otherObject2_ctx1;
|
||||
{
|
||||
v8::Context::Scope scope(context1);
|
||||
auto script =
|
||||
v8::Script::Compile(context1, NewString(source)).ToLocalChecked();
|
||||
templateLiteral1 = script->Run(context1).ToLocalChecked();
|
||||
templateLiteral1_2 = script->Run(context1).ToLocalChecked();
|
||||
otherObject1_ctx1 = RunJS(context1, otherObject1Source);
|
||||
otherObject2_ctx1 = RunJS(context1, otherObject2Source);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> templateLiteral2;
|
||||
v8::Local<v8::Context> context2 = v8::Context::New(isolate());
|
||||
v8::Local<v8::Value> otherObject1_ctx2;
|
||||
v8::Local<v8::Value> otherObject2_ctx2;
|
||||
{
|
||||
v8::Context::Scope scope(context2);
|
||||
templateLiteral2 = RunJS(context2, source);
|
||||
otherObject1_ctx2 = RunJS(context2, otherObject1Source);
|
||||
otherObject2_ctx2 = RunJS(context1, otherObject2Source);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(context1->HasTemplateLiteralObject(templateLiteral1));
|
||||
ASSERT_TRUE(context1->HasTemplateLiteralObject(templateLiteral1_2));
|
||||
ASSERT_FALSE(context1->HasTemplateLiteralObject(templateLiteral2));
|
||||
|
||||
ASSERT_FALSE(context2->HasTemplateLiteralObject(templateLiteral1));
|
||||
ASSERT_FALSE(context2->HasTemplateLiteralObject(templateLiteral1_2));
|
||||
ASSERT_TRUE(context2->HasTemplateLiteralObject(templateLiteral2));
|
||||
|
||||
// Neither otherObject is a template object
|
||||
ASSERT_FALSE(context1->HasTemplateLiteralObject(otherObject1_ctx1));
|
||||
ASSERT_FALSE(context1->HasTemplateLiteralObject(otherObject2_ctx1));
|
||||
ASSERT_FALSE(context1->HasTemplateLiteralObject(otherObject1_ctx2));
|
||||
ASSERT_FALSE(context1->HasTemplateLiteralObject(otherObject1_ctx1));
|
||||
ASSERT_FALSE(context2->HasTemplateLiteralObject(otherObject2_ctx1));
|
||||
ASSERT_FALSE(context2->HasTemplateLiteralObject(otherObject1_ctx2));
|
||||
ASSERT_FALSE(context2->HasTemplateLiteralObject(otherObject2_ctx2));
|
||||
ASSERT_FALSE(context2->HasTemplateLiteralObject(otherObject2_ctx2));
|
||||
}
|
@ -13,6 +13,7 @@
|
||||
#include "include/v8-context.h"
|
||||
#include "include/v8-extension.h"
|
||||
#include "include/v8-local-handle.h"
|
||||
#include "include/v8-object.h"
|
||||
#include "include/v8-primitive.h"
|
||||
#include "include/v8-template.h"
|
||||
#include "src/api/api-inl.h"
|
||||
@ -100,6 +101,18 @@ class WithIsolateMixin : public TMixin {
|
||||
|
||||
v8::Isolate* v8_isolate() const { return isolate_wrapper_.isolate(); }
|
||||
|
||||
Local<Value> RunJS(const char* source, Local<Context> context) {
|
||||
return RunJS(
|
||||
v8::String::NewFromUtf8(this->v8_isolate(), source).ToLocalChecked(),
|
||||
context);
|
||||
}
|
||||
|
||||
Local<Value> RunJS(Local<String> source, Local<Context> context) {
|
||||
Local<Script> script =
|
||||
v8::Script::Compile(context, source).ToLocalChecked();
|
||||
return script->Run(context).ToLocalChecked();
|
||||
}
|
||||
|
||||
private:
|
||||
v8::IsolateWrapper isolate_wrapper_;
|
||||
};
|
||||
@ -134,6 +147,12 @@ class WithIsolateScopeMixin : public TMixin {
|
||||
v8::String::NewFromUtf8(this->v8_isolate(), source).ToLocalChecked());
|
||||
}
|
||||
|
||||
Local<Value> RunJS(Local<Context> context, const char* source) {
|
||||
return RunJS(
|
||||
context,
|
||||
v8::String::NewFromUtf8(this->v8_isolate(), source).ToLocalChecked());
|
||||
}
|
||||
|
||||
MaybeLocal<Value> TryRunJS(const char* source) {
|
||||
return TryRunJS(
|
||||
v8::String::NewFromUtf8(this->v8_isolate(), source).ToLocalChecked());
|
||||
@ -141,6 +160,11 @@ class WithIsolateScopeMixin : public TMixin {
|
||||
|
||||
static MaybeLocal<Value> TryRunJS(Isolate* isolate, Local<String> source) {
|
||||
auto context = isolate->GetCurrentContext();
|
||||
return TryRunJS(context, source);
|
||||
}
|
||||
|
||||
static MaybeLocal<Value> TryRunJS(Local<Context> context,
|
||||
Local<String> source) {
|
||||
v8::Local<v8::Value> result;
|
||||
Local<Script> script =
|
||||
v8::Script::Compile(context, source).ToLocalChecked();
|
||||
@ -210,6 +234,10 @@ class WithIsolateScopeMixin : public TMixin {
|
||||
return TryRunJS(source).ToLocalChecked();
|
||||
}
|
||||
|
||||
Local<Value> RunJS(Local<Context> context, Local<String> source) {
|
||||
return TryRunJS(context, source).ToLocalChecked();
|
||||
}
|
||||
|
||||
MaybeLocal<Value> TryRunJS(Local<String> source) {
|
||||
return TryRunJS(this->v8_isolate(), source);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user