Commit b3b9e198 authored by Erik Luo's avatar Erik Luo Committed by Commit Bot

[bindings] remove constructor blacklist and only allow wrappers

This CL dismantles the side effect constructor blacklist, so Blink constructors
(default, named, custom) all throw when evaluating with throwOnSideEffect.
[Affects=Everything] is no longer a valid extended attribute.

Constructors can still be invoked without side effects in one case: creating a
DOM wrapper for the V8 object. Any whitelisted attribute/operation that returns
an HTMLDivElement, for example, can call the constructor with
ConstructorMode::kWrapExistingObject the first time it returns.

Bug: 829571
Change-Id: I3ed2166da80d38a7835dc57a1ccaec23e22734e9
Reviewed-on: https://chromium-review.googlesource.com/1043655Reviewed-by: default avatarYuki Shiino <yukishiino@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Erik Luo <luoe@chromium.org>
Cr-Commit-Position: refs/heads/master@{#558134}
parent bac2a356
Tests that invoking embedder constructors is side-effect-free. Should not crash.
Checking functions on 'window'
Function "Worker" failed side-effect check
Function "SharedWorker" failed side-effect check
Tests that embedder constructors throw on side effect. Should not crash.
PASS: Constructor "Worker"
has side effect: true
PASS: Constructor "SharedWorker"
has side effect: true
PASS: Constructor "Audio"
has side effect: true
PASS: Constructor "Image"
has side effect: true
PASS: Constructor "Option"
has side effect: true
PASS: Constructor "ReadableStream"
has side effect: true
PASS: Constructor "WritableStream"
has side effect: true
PASS: Constructor "TransformStream"
has side effect: true
(async function(testRunner) {
var {page, session, dp} = await testRunner.startBlank(
`Tests that invoking embedder constructors is side-effect-free. Should not crash.`);
var constructorNames = await session.evaluate(`
var windowProps = Object.keys(Object.getOwnPropertyDescriptors(window));
var constructorNames = windowProps.filter(prop => {
var value = window[prop];
return typeof value === 'function' &&
value.toString().endsWith('{ [native code] }');
});
var nativeConstructors = constructorNames.map(name => window[name]);
constructorNames;
`Tests that embedder constructors throw on side effect. Should not crash.`);
var badConstructorNames = await session.evaluate(`
var global_badConstructors = [
// Worker, SharedWorker constructors are known to be able to run in
// parallel, fetch URLs, and modify the global worker set.
// See spec section 10.2.6.3, step 9.
// https://html.spec.whatwg.org/#dedicated-workers-and-the-worker-interface
'Worker',
// See spec section 10.2.6.4, step 11.
// https://html.spec.whatwg.org/#shared-workers-and-the-sharedworker-interface
'SharedWorker',
// Check named constructors.
'Audio',
'Image',
'Option',
// Check constructors with JS source.
'ReadableStream',
'WritableStream',
'TransformStream'
];
global_badConstructors;
`);
// These functions are for testing-only, should not be tested.
var TestFrameworkBuiltins = new Set(['gc']);
// These functions are V8 builtins that have not yet been whitelisted.
// Do not check for test.
var V8BuiltinsWithoutSideEffect = new Set(['Function', 'Promise', 'RegExp', 'Proxy']);
// These functions are actually side-effect-free, but fail the V8
// side-effect check. Methods and attributes marked with [Affects=Nothing]
// that invoke these as constructors MUST properly handle exceptions.
var EmbedderCallbacksWithoutSideEffect = new Set(['ReadableStream', 'WritableStream', 'TransformStream']);
// These constructor callbacks are blacklisted with `[Affects=Everything]`,
// and should throwOnSideEffect.
var EmbedderConstructorBlacklist = new Set([
// The Worker constructor may run a worker in parallel, fetch URLs, and
// modify the global worker set. See spec section 10.2.6.3, step 9.
// https://html.spec.whatwg.org/#dedicated-workers-and-the-worker-interface
'Worker',
// The SharedWorker constructor may run a worker in parallel, fetch URLs,
// and modify the global worker set. See spec section 10.2.6.4, step 11.
// https://html.spec.whatwg.org/#shared-workers-and-the-sharedworker-interface
'SharedWorker'
]);
testRunner.log(`Checking functions on 'window'`);
for (var i = 0; i < constructorNames.length; i++) {
var name = constructorNames[i];
if (TestFrameworkBuiltins.has(name) || V8BuiltinsWithoutSideEffect.has(name))
continue;
var response = await dp.Runtime.evaluate({expression: `new nativeConstructors[${i}]`, throwOnSideEffect: true});
for (var i = 0; i < badConstructorNames.length; i++) {
var name = badConstructorNames[i];
var response = await dp.Runtime.evaluate({expression: `new window[global_badConstructors[${i}]]`, throwOnSideEffect: true});
var exception = response.result.exceptionDetails;
var failedSideEffectCheck = exception && exception.exception.description.startsWith('EvalError: Possible side-effect in debug-evaluate');
var expectedToThrow = EmbedderConstructorBlacklist.has(name);
if (failedSideEffectCheck && !EmbedderCallbacksWithoutSideEffect.has(name))
testRunner.log(`${expectedToThrow ? '' : 'FAIL: '}Function "${name}" failed side-effect check`);
var hasSideEffect = false;
var exceptionDetails = response.result.exceptionDetails;
if (exceptionDetails &&
exceptionDetails.exception.description.startsWith('EvalError: Possible side-effect in debug-evaluate'))
hasSideEffect = true;
testRunner.log(`${hasSideEffect ? 'PASS: ' : 'FAIL: '}Constructor "${name}"\nhas side effect: ${hasSideEffect}`);
}
testRunner.completeTest();
......
......@@ -1548,23 +1548,16 @@ V8PrivateProperty::getHTMLFooBarCachedAccessor().set(context, object, newValue);
```
### [Affects] _(i, m, a)_
### [Affects] _(m, a)_
Summary: `[Affects=Nothing]` indicates that a function must not produce JS-observable side effects, and functions without this attribute are never invoked by V8 with throwOnSideEffect. `[Affects=Everything]` indicates that a constructor will throwOnSideEffect.
Summary: `[Affects=Nothing]` indicates that a function must not produce JS-observable side effects. Functions without this attribute are never invoked by V8 with throwOnSideEffect.
Marked functions are allowed to be nondeterministic, throw exceptions, force layout, and recalculate style, but must not set values, cache objects, or schedule execution that will be observable after the function completes. If a marked function calls into V8, it must properly handle cases when the V8 call returns an MaybeHandle.
All DOM constructors are assumed to have no JS-observable side effects, unless blacklisted with `[Affects=Everything]`.
All DOM constructors are assumed to have side effects. However, an exception can be explicitly indicated when calling constructors using the V8 API method Function::NewInstanceWithSideEffectType().
There is not yet support for marking SymbolKeyedMethodConfigurations as side-effect free. This requires additional support in V8 to whitelist Intrinsics.
Usage for interfaces: `[Affects=Everything]` can be specified on an interface to indicate that its constructor callback does have side effects.
```webidl
[Affects=Everything]
interface HTMLFoo {};
```
Usage for attributes and operations: `[Affects=Nothing]` can be specified on an operation, or on an attribute to indicate that its getter callback is side effect free:
```webidl
......
......@@ -32,7 +32,7 @@
#
ActiveScriptWrappable
Affects=Everything|Nothing
Affects=Nothing
AllowShared
CEReactions
CachedAccessor
......
......@@ -809,9 +809,7 @@ v8::Local<v8::FunctionTemplate> V8DOMConfiguration::DomClassTemplate(
// We assume all constructors have no JS-observable side effect.
interface_template = v8::FunctionTemplate::New(
isolate, V8ObjectConstructor::IsValidConstructorMode,
v8::Local<v8::Value>(), v8::Local<v8::Signature>(), 0,
v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasNoSideEffect);
isolate, V8ObjectConstructor::IsValidConstructorMode);
configure_dom_class_template(isolate, world, interface_template);
data->SetInterfaceTemplate(world, wrapper_type_info, interface_template);
return interface_template;
......
......@@ -377,7 +377,6 @@ def interface_context(interface, interfaces):
context.update({
'constructors': constructors,
'constructor_has_side_effect': has_extended_attribute_value(interface, 'Affects', 'Everything'),
'has_custom_constructor': bool(custom_constructors),
'has_html_constructor': has_html_constructor,
'interface_length':
......
......@@ -745,7 +745,7 @@ v8::Local<v8::FunctionTemplate> {{v8_class}}Constructor::domTemplate(v8::Isolate
if (!result.IsEmpty())
return result;
result = v8::FunctionTemplate::New(isolate, {{v8_class}}ConstructorCallback, v8::Local<v8::Value>(), v8::Local<v8::Signature>(), 0, v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasNoSideEffect);
result = v8::FunctionTemplate::New(isolate, {{v8_class}}ConstructorCallback);
v8::Local<v8::ObjectTemplate> instanceTemplate = result->InstanceTemplate();
instanceTemplate->SetInternalFieldCount({{v8_class}}::internalFieldCount);
result->SetClassName(V8AtomicString(isolate, "{{named_constructor.name}}"));
......
......@@ -452,7 +452,7 @@ static void install{{v8_class}}Template(
'v8::Local<v8::FunctionTemplate>()' %}
V8DOMConfiguration::InitializeDOMInterfaceTemplate(isolate, interfaceTemplate, {{v8_class}}::wrapperTypeInfo.interface_name, {{parent_interface_template}}, {{v8_class}}::internalFieldCount);
{% if constructors or has_custom_constructor or has_html_constructor %}
interfaceTemplate->SetCallHandler({{v8_class}}::constructorCallback, v8::Local<v8::Value>(), v8::SideEffectType::{% if constructor_has_side_effect %}kHasSideEffect{% else %}kHasNoSideEffect{% endif %});
interfaceTemplate->SetCallHandler({{v8_class}}::constructorCallback);
interfaceTemplate->SetLength({{interface_length}});
{% endif %}
{% endif %}{# is_partial #}
......
......@@ -693,7 +693,7 @@ void V8TestInterface2::installV8TestInterface2Template(
v8::Local<v8::FunctionTemplate> interfaceTemplate) {
// Initialize the interface object's template.
V8DOMConfiguration::InitializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterface2::wrapperTypeInfo.interface_name, v8::Local<v8::FunctionTemplate>(), V8TestInterface2::internalFieldCount);
interfaceTemplate->SetCallHandler(V8TestInterface2::constructorCallback, v8::Local<v8::Value>(), v8::SideEffectType::kHasNoSideEffect);
interfaceTemplate->SetCallHandler(V8TestInterface2::constructorCallback);
interfaceTemplate->SetLength(0);
v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
......
......@@ -431,7 +431,7 @@ v8::Local<v8::FunctionTemplate> V8TestInterfaceConstructorConstructor::domTempla
if (!result.IsEmpty())
return result;
result = v8::FunctionTemplate::New(isolate, V8TestInterfaceConstructorConstructorCallback, v8::Local<v8::Value>(), v8::Local<v8::Signature>(), 0, v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasNoSideEffect);
result = v8::FunctionTemplate::New(isolate, V8TestInterfaceConstructorConstructorCallback);
v8::Local<v8::ObjectTemplate> instanceTemplate = result->InstanceTemplate();
instanceTemplate->SetInternalFieldCount(V8TestInterfaceConstructor::internalFieldCount);
result->SetClassName(V8AtomicString(isolate, "Audio"));
......@@ -492,7 +492,7 @@ static void installV8TestInterfaceConstructorTemplate(
v8::Local<v8::FunctionTemplate> interfaceTemplate) {
// Initialize the interface object's template.
V8DOMConfiguration::InitializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceConstructor::wrapperTypeInfo.interface_name, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceConstructor::internalFieldCount);
interfaceTemplate->SetCallHandler(V8TestInterfaceConstructor::constructorCallback, v8::Local<v8::Value>(), v8::SideEffectType::kHasNoSideEffect);
interfaceTemplate->SetCallHandler(V8TestInterfaceConstructor::constructorCallback);
interfaceTemplate->SetLength(0);
v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
......
......@@ -255,7 +255,7 @@ static void installV8TestInterfaceConstructor2Template(
v8::Local<v8::FunctionTemplate> interfaceTemplate) {
// Initialize the interface object's template.
V8DOMConfiguration::InitializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceConstructor2::wrapperTypeInfo.interface_name, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceConstructor2::internalFieldCount);
interfaceTemplate->SetCallHandler(V8TestInterfaceConstructor2::constructorCallback, v8::Local<v8::Value>(), v8::SideEffectType::kHasNoSideEffect);
interfaceTemplate->SetCallHandler(V8TestInterfaceConstructor2::constructorCallback);
interfaceTemplate->SetLength(1);
v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
......
......@@ -105,7 +105,7 @@ static void installV8TestInterfaceConstructor3Template(
v8::Local<v8::FunctionTemplate> interfaceTemplate) {
// Initialize the interface object's template.
V8DOMConfiguration::InitializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceConstructor3::wrapperTypeInfo.interface_name, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceConstructor3::internalFieldCount);
interfaceTemplate->SetCallHandler(V8TestInterfaceConstructor3::constructorCallback, v8::Local<v8::Value>(), v8::SideEffectType::kHasNoSideEffect);
interfaceTemplate->SetCallHandler(V8TestInterfaceConstructor3::constructorCallback);
interfaceTemplate->SetLength(1);
v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
......
......@@ -139,7 +139,7 @@ static void installV8TestInterfaceConstructor4Template(
v8::Local<v8::FunctionTemplate> interfaceTemplate) {
// Initialize the interface object's template.
V8DOMConfiguration::InitializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceConstructor4::wrapperTypeInfo.interface_name, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceConstructor4::internalFieldCount);
interfaceTemplate->SetCallHandler(V8TestInterfaceConstructor4::constructorCallback, v8::Local<v8::Value>(), v8::SideEffectType::kHasNoSideEffect);
interfaceTemplate->SetCallHandler(V8TestInterfaceConstructor4::constructorCallback);
interfaceTemplate->SetLength(1);
v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
......
......@@ -84,7 +84,7 @@ static void installV8TestInterfaceCustomConstructorTemplate(
v8::Local<v8::FunctionTemplate> interfaceTemplate) {
// Initialize the interface object's template.
V8DOMConfiguration::InitializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceCustomConstructor::wrapperTypeInfo.interface_name, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceCustomConstructor::internalFieldCount);
interfaceTemplate->SetCallHandler(V8TestInterfaceCustomConstructor::constructorCallback, v8::Local<v8::Value>(), v8::SideEffectType::kHasNoSideEffect);
interfaceTemplate->SetCallHandler(V8TestInterfaceCustomConstructor::constructorCallback);
interfaceTemplate->SetLength(0);
v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
......
......@@ -151,7 +151,7 @@ static void installV8TestInterfaceEventInitConstructorTemplate(
v8::Local<v8::FunctionTemplate> interfaceTemplate) {
// Initialize the interface object's template.
V8DOMConfiguration::InitializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceEventInitConstructor::wrapperTypeInfo.interface_name, V8Event::domTemplate(isolate, world), V8TestInterfaceEventInitConstructor::internalFieldCount);
interfaceTemplate->SetCallHandler(V8TestInterfaceEventInitConstructor::constructorCallback, v8::Local<v8::Value>(), v8::SideEffectType::kHasNoSideEffect);
interfaceTemplate->SetCallHandler(V8TestInterfaceEventInitConstructor::constructorCallback);
interfaceTemplate->SetLength(2);
v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
......
......@@ -112,7 +112,7 @@ v8::Local<v8::FunctionTemplate> V8TestInterfaceEventTargetConstructor::domTempla
if (!result.IsEmpty())
return result;
result = v8::FunctionTemplate::New(isolate, V8TestInterfaceEventTargetConstructorCallback, v8::Local<v8::Value>(), v8::Local<v8::Signature>(), 0, v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasNoSideEffect);
result = v8::FunctionTemplate::New(isolate, V8TestInterfaceEventTargetConstructorCallback);
v8::Local<v8::ObjectTemplate> instanceTemplate = result->InstanceTemplate();
instanceTemplate->SetInternalFieldCount(V8TestInterfaceEventTarget::internalFieldCount);
result->SetClassName(V8AtomicString(isolate, "Name"));
......
......@@ -413,7 +413,7 @@ static void installV8TestInterfaceGarbageCollectedTemplate(
v8::Local<v8::FunctionTemplate> interfaceTemplate) {
// Initialize the interface object's template.
V8DOMConfiguration::InitializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceGarbageCollected::wrapperTypeInfo.interface_name, V8EventTarget::domTemplate(isolate, world), V8TestInterfaceGarbageCollected::internalFieldCount);
interfaceTemplate->SetCallHandler(V8TestInterfaceGarbageCollected::constructorCallback, v8::Local<v8::Value>(), v8::SideEffectType::kHasNoSideEffect);
interfaceTemplate->SetCallHandler(V8TestInterfaceGarbageCollected::constructorCallback);
interfaceTemplate->SetLength(1);
v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
......
......@@ -195,7 +195,7 @@ v8::Local<v8::FunctionTemplate> V8TestInterfaceNamedConstructorConstructor::domT
if (!result.IsEmpty())
return result;
result = v8::FunctionTemplate::New(isolate, V8TestInterfaceNamedConstructorConstructorCallback, v8::Local<v8::Value>(), v8::Local<v8::Signature>(), 0, v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasNoSideEffect);
result = v8::FunctionTemplate::New(isolate, V8TestInterfaceNamedConstructorConstructorCallback);
v8::Local<v8::ObjectTemplate> instanceTemplate = result->InstanceTemplate();
instanceTemplate->SetInternalFieldCount(V8TestInterfaceNamedConstructor::internalFieldCount);
result->SetClassName(V8AtomicString(isolate, "Audio"));
......
......@@ -121,7 +121,7 @@ v8::Local<v8::FunctionTemplate> V8TestInterfaceNamedConstructor2Constructor::dom
if (!result.IsEmpty())
return result;
result = v8::FunctionTemplate::New(isolate, V8TestInterfaceNamedConstructor2ConstructorCallback, v8::Local<v8::Value>(), v8::Local<v8::Signature>(), 0, v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasNoSideEffect);
result = v8::FunctionTemplate::New(isolate, V8TestInterfaceNamedConstructor2ConstructorCallback);
v8::Local<v8::ObjectTemplate> instanceTemplate = result->InstanceTemplate();
instanceTemplate->SetInternalFieldCount(V8TestInterfaceNamedConstructor2::internalFieldCount);
result->SetClassName(V8AtomicString(isolate, "Audio"));
......
......@@ -265,7 +265,7 @@ static void installV8TestNodeTemplate(
v8::Local<v8::FunctionTemplate> interfaceTemplate) {
// Initialize the interface object's template.
V8DOMConfiguration::InitializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestNode::wrapperTypeInfo.interface_name, V8Node::domTemplate(isolate, world), V8TestNode::internalFieldCount);
interfaceTemplate->SetCallHandler(V8TestNode::constructorCallback, v8::Local<v8::Value>(), v8::SideEffectType::kHasNoSideEffect);
interfaceTemplate->SetCallHandler(V8TestNode::constructorCallback);
interfaceTemplate->SetLength(0);
v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
......
......@@ -577,7 +577,7 @@ static void installV8TestTypedefsTemplate(
v8::Local<v8::FunctionTemplate> interfaceTemplate) {
// Initialize the interface object's template.
V8DOMConfiguration::InitializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestTypedefs::wrapperTypeInfo.interface_name, v8::Local<v8::FunctionTemplate>(), V8TestTypedefs::internalFieldCount);
interfaceTemplate->SetCallHandler(V8TestTypedefs::constructorCallback, v8::Local<v8::Value>(), v8::SideEffectType::kHasNoSideEffect);
interfaceTemplate->SetCallHandler(V8TestTypedefs::constructorCallback);
interfaceTemplate->SetLength(1);
v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
......
......@@ -102,7 +102,7 @@ static void installV8TestVariadicConstructorArgumentsTemplate(
v8::Local<v8::FunctionTemplate> interfaceTemplate) {
// Initialize the interface object's template.
V8DOMConfiguration::InitializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestVariadicConstructorArguments::wrapperTypeInfo.interface_name, v8::Local<v8::FunctionTemplate>(), V8TestVariadicConstructorArguments::internalFieldCount);
interfaceTemplate->SetCallHandler(V8TestVariadicConstructorArguments::constructorCallback, v8::Local<v8::Value>(), v8::SideEffectType::kHasNoSideEffect);
interfaceTemplate->SetCallHandler(V8TestVariadicConstructorArguments::constructorCallback);
interfaceTemplate->SetLength(0);
v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
......
......@@ -33,10 +33,6 @@
[
ActiveScriptWrappable,
// The SharedWorker constructor may run a worker in parallel, fetch URLs,
// and modify the global worker set. See spec section 10.2.6.4, step 11.
// https://html.spec.whatwg.org/#shared-workers-and-the-sharedworker-interface
Affects=Everything,
// TODO(foolip): The name argument should not have a default null value.
Constructor(DOMString scriptURL, optional DOMString name = null),
ConstructorCallWith=ExecutionContext,
......
......@@ -29,10 +29,6 @@
[
ActiveScriptWrappable,
// The Worker constructor may run a worker in parallel, fetch URLs, and
// modify the global worker set. See spec section 10.2.6.3, step 9.
// https://html.spec.whatwg.org/#dedicated-workers-and-the-worker-interface
Affects=Everything,
Constructor(DOMString scriptURL, optional WorkerOptions options),
ConstructorCallWith=ExecutionContext,
// TODO(foolip): Exposed=(Window,Worker),
......
......@@ -44,8 +44,12 @@ v8::MaybeLocal<v8::Object> V8ObjectConstructor::NewInstance(
ConstructorMode constructor_mode(isolate);
v8::MicrotasksScope microtasks_scope(
isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
v8::MaybeLocal<v8::Object> result =
function->NewInstance(isolate->GetCurrentContext(), argc, argv);
// Construct without side effect only in ConstructorMode::kWrapExistingObject
// cases. This allows whitelisted methods to correctly set return values
// without invoking Blink's internal constructors.
v8::MaybeLocal<v8::Object> result = function->NewInstanceWithSideEffectType(
isolate->GetCurrentContext(), argc, argv,
v8::SideEffectType::kHasNoSideEffect);
CHECK(!isolate->IsDead());
return result;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment