summaryrefslogtreecommitdiff
path: root/deps/v8/test/cctest/test-api.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/cctest/test-api.cc')
-rw-r--r--deps/v8/test/cctest/test-api.cc319
1 files changed, 251 insertions, 68 deletions
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index 5eafa420bc..13a9704279 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -34,7 +34,7 @@
#include <string>
#if V8_OS_POSIX
-#include <unistd.h> // NOLINT
+#include <unistd.h>
#endif
#include "include/v8-fast-api-calls.h"
@@ -1453,6 +1453,9 @@ static void TestExternalPointerWrapping() {
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
+ int* ptr = new int;
+ expected_ptr = ptr;
+
v8::Local<v8::Value> data = v8::External::New(isolate, expected_ptr);
v8::Local<v8::Object> obj = v8::Object::New(isolate);
@@ -1468,6 +1471,8 @@ static void TestExternalPointerWrapping() {
"}\n"
"foo(), true")
->BooleanValue(isolate));
+
+ delete ptr;
}
@@ -2672,24 +2677,28 @@ void SimpleAccessorSetter(Local<String> name, Local<Value> value,
void SymbolAccessorGetter(Local<Name> name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
CHECK(name->IsSymbol());
+ v8::Isolate* isolate = info.GetIsolate();
Local<Symbol> sym = name.As<Symbol>();
- if (sym->Description()->IsUndefined()) return;
- SimpleAccessorGetter(Local<String>::Cast(sym->Description()), info);
+ if (sym->Description(isolate)->IsUndefined()) return;
+ SimpleAccessorGetter(Local<String>::Cast(sym->Description(isolate)), info);
}
void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
const v8::PropertyCallbackInfo<void>& info) {
CHECK(name->IsSymbol());
+ v8::Isolate* isolate = info.GetIsolate();
Local<Symbol> sym = name.As<Symbol>();
- if (sym->Description()->IsUndefined()) return;
- SimpleAccessorSetter(Local<String>::Cast(sym->Description()), value, info);
+ if (sym->Description(isolate)->IsUndefined()) return;
+ SimpleAccessorSetter(Local<String>::Cast(sym->Description(isolate)), value,
+ info);
}
void SymbolAccessorGetterReturnsDefault(
Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
CHECK(name->IsSymbol());
+ v8::Isolate* isolate = info.GetIsolate();
Local<Symbol> sym = name.As<Symbol>();
- if (sym->Description()->IsUndefined()) return;
+ if (sym->Description(isolate)->IsUndefined()) return;
info.GetReturnValue().Set(info.Data());
}
@@ -3045,7 +3054,9 @@ THREADED_TEST(InternalFieldsAlignedPointers) {
int stack_allocated[100];
CheckAlignedPointerInInternalField(obj, stack_allocated);
- void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
+ // The aligned pointer must have the top bits be zero on 64-bit machines (at
+ // least if the heap sandbox is enabled).
+ void* huge = reinterpret_cast<void*>(0x0000fffffffffffe);
CheckAlignedPointerInInternalField(obj, huge);
v8::Global<v8::Object> persistent(isolate, obj);
@@ -3121,7 +3132,9 @@ THREADED_TEST(EmbedderDataAlignedPointers) {
CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
CHECK_EQ(3, (*env)->GetNumberOfEmbedderDataFields());
- void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
+ // The aligned pointer must have the top bits be zero on 64-bit machines (at
+ // least if the heap sandbox is enabled).
+ void* huge = reinterpret_cast<void*>(0x0000fffffffffffe);
CheckAlignedPointerInEmbedderData(&env, 3, huge);
CHECK_EQ(4, (*env)->GetNumberOfEmbedderDataFields());
@@ -3319,8 +3332,9 @@ THREADED_TEST(SymbolProperties) {
CHECK(!sym1->StrictEquals(sym2));
CHECK(!sym2->StrictEquals(sym1));
- CHECK(
- sym2->Description()->Equals(env.local(), v8_str("my-symbol")).FromJust());
+ CHECK(sym2->Description(isolate)
+ ->Equals(env.local(), v8_str("my-symbol"))
+ .FromJust());
v8::Local<v8::Value> sym_val = sym2;
CHECK(sym_val->IsSymbol());
@@ -8529,12 +8543,8 @@ THREADED_TEST(StringWrite) {
CHECK_EQ(0, str->Write(isolate, nullptr, 0, 0, String::NO_NULL_TERMINATION));
}
-
-static void Utf16Helper(
- LocalContext& context, // NOLINT
- const char* name,
- const char* lengths_name,
- int len) {
+static void Utf16Helper(LocalContext& context, const char* name,
+ const char* lengths_name, int len) {
Local<v8::Array> a = Local<v8::Array>::Cast(
context->Global()->Get(context.local(), v8_str(name)).ToLocalChecked());
Local<v8::Array> alens =
@@ -14191,8 +14201,8 @@ void CheckIsSymbolAt(v8::Isolate* isolate, v8::Local<v8::Array> properties,
properties->Get(context, v8::Integer::New(isolate, index))
.ToLocalChecked();
CHECK(value->IsSymbol());
- v8::String::Utf8Value symbol_name(isolate,
- Local<Symbol>::Cast(value)->Description());
+ v8::String::Utf8Value symbol_name(
+ isolate, Local<Symbol>::Cast(value)->Description(isolate));
if (strcmp(name, *symbol_name) != 0) {
FATAL("properties[%u] was Symbol('%s') instead of Symbol('%s').", index,
name, *symbol_name);
@@ -16753,7 +16763,10 @@ THREADED_TEST(GetHeapStatistics) {
CHECK_EQ(0u, heap_statistics.used_heap_size());
c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
- CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
+ if (!v8::internal::FLAG_enable_third_party_heap) {
+ // TODO(wenyuzhao): Get used size from third_party_heap interface
+ CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
+ }
}
TEST(GetHeapSpaceStatistics) {
@@ -20784,6 +20797,50 @@ THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
CheckInstanceCheckedAccessors(true);
}
+THREADED_TEST(CheckIsLeafTemplateForApiObject) {
+ LocalContext context;
+ v8::HandleScope scope(context->GetIsolate());
+
+ Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
+ CHECK(context->Global()
+ ->Set(context.local(), v8_str("f"),
+ templ->GetFunction(context.local()).ToLocalChecked())
+ .FromJust());
+
+ printf("Testing positive ...\n");
+ CompileRun("var obj = new f();");
+ CHECK(templ->IsLeafTemplateForApiObject(
+ context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
+
+ printf("Testing negative ...\n");
+ CompileRun(
+ "var obj = {};"
+ "obj.__proto__ = new f();");
+ CHECK(!templ->IsLeafTemplateForApiObject(
+ context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
+
+ printf("Testing positive with modified prototype chain ...\n");
+ CompileRun(
+ "var obj = new f();"
+ "var pro = {};"
+ "pro.__proto__ = obj.__proto__;"
+ "obj.__proto__ = pro;");
+ CHECK(templ->IsLeafTemplateForApiObject(
+ context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
+
+ Local<FunctionTemplate> child_templ =
+ FunctionTemplate::New(context->GetIsolate());
+ child_templ->Inherit(templ);
+ Local<Object> instance = child_templ->GetFunction(context.local())
+ .ToLocalChecked()
+ ->NewInstance(context.local())
+ .ToLocalChecked();
+
+ printf("Testing positive for child ...\n");
+ CHECK(child_templ->IsLeafTemplateForApiObject(instance));
+ printf("Testing negative for parent ...\n");
+ CHECK(!templ->IsLeafTemplateForApiObject(instance));
+}
TEST(TryFinallyMessage) {
LocalContext context;
@@ -21974,7 +22031,7 @@ THREADED_TEST(FunctionNew) {
->shared()
.get_api_func_data()
.serial_number();
- CHECK_EQ(i::FunctionTemplateInfo::kInvalidSerialNumber, serial_number);
+ CHECK_EQ(i::TemplateInfo::kDoNotCache, serial_number);
// Verify that each Function::New creates a new function instance
Local<Object> data2 = v8::Object::New(isolate);
@@ -26169,8 +26226,9 @@ TEST(DynamicImport) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::Handle<i::Script> referrer = i_isolate->factory()->NewScript(source);
referrer->set_name(*url);
- referrer->set_host_defined_options(*i_isolate->factory()->NewFixedArray(
- kCustomHostDefinedOptionsLengthForTesting));
+ i::Handle<i::FixedArray> options = i_isolate->factory()->NewFixedArray(
+ kCustomHostDefinedOptionsLengthForTesting);
+ referrer->set_host_defined_options(*options);
i::MaybeHandle<i::JSPromise> maybe_promise =
i_isolate->RunHostImportModuleDynamicallyCallback(
referrer, specifier, i::MaybeHandle<i::Object>());
@@ -26255,8 +26313,9 @@ TEST(DynamicImportWithAssertions) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::Handle<i::Script> referrer = i_isolate->factory()->NewScript(source);
referrer->set_name(*url);
- referrer->set_host_defined_options(*i_isolate->factory()->NewFixedArray(
- kCustomHostDefinedOptionsLengthForTesting));
+ i::Handle<i::FixedArray> options = i_isolate->factory()->NewFixedArray(
+ kCustomHostDefinedOptionsLengthForTesting);
+ referrer->set_host_defined_options(*options);
i::MaybeHandle<i::JSPromise> maybe_promise =
i_isolate->RunHostImportModuleDynamicallyCallback(referrer, specifier,
i_import_assertions);
@@ -27621,14 +27680,16 @@ namespace {
template <typename Value, typename Impl, typename Ret>
struct BasicApiChecker {
- static Ret FastCallback(v8::ApiObject receiver, Value argument,
+ static Ret FastCallback(v8::Local<v8::Object> receiver, Value argument,
v8::FastApiCallbackOptions& options) {
- const v8::Value* data = reinterpret_cast<const v8::Value*>(&options.data);
+ // TODO(mslekova): Refactor the data checking.
+ v8::Value* data = &(options.data);
CHECK(data->IsNumber());
- CHECK_EQ(reinterpret_cast<const v8::Number*>(data)->Value(), 42.0);
+ CHECK_EQ(v8::Number::Cast(data)->Value(), 42.0);
return Impl::FastCallback(receiver, argument, options);
}
- static Ret FastCallbackNoFallback(v8::ApiObject receiver, Value argument) {
+ static Ret FastCallbackNoFallback(v8::Local<v8::Object> receiver,
+ Value argument) {
v8::FastApiCallbackOptions options = {false, {0}};
return Impl::FastCallback(receiver, argument, options);
}
@@ -27639,6 +27700,12 @@ struct BasicApiChecker {
bool DidCallFast() const { return (result_ & ApiCheckerResult::kFastCalled); }
bool DidCallSlow() const { return (result_ & ApiCheckerResult::kSlowCalled); }
+ void SetCallFast() { result_ |= ApiCheckerResult::kFastCalled; }
+ void SetCallSlow() { result_ |= ApiCheckerResult::kSlowCalled; }
+
+ void Reset() { result_ = ApiCheckerResult::kNotCalled; }
+
+ private:
ApiCheckerResultFlags result_ = ApiCheckerResult::kNotCalled;
};
@@ -27663,17 +27730,16 @@ struct ApiNumberChecker : BasicApiChecker<T, ApiNumberChecker<T>, void> {
write_to_fallback_(write_to_fallback),
args_count_(args_count) {}
- static void FastCallback(v8::ApiObject receiver, T argument,
+ static void FastCallback(v8::Local<v8::Object> receiver, T argument,
v8::FastApiCallbackOptions& options) {
- v8::Object* receiver_obj = reinterpret_cast<v8::Object*>(&receiver);
+ v8::Object* receiver_obj = *receiver;
if (!IsValidUnwrapObject(receiver_obj)) {
options.fallback = 1;
return;
}
ApiNumberChecker<T>* receiver_ptr =
- GetInternalField<ApiNumberChecker<T>, kV8WrapperObjectIndex>(
- receiver_obj);
- receiver_ptr->result_ |= ApiCheckerResult::kFastCalled;
+ GetInternalField<ApiNumberChecker<T>>(receiver_obj);
+ receiver_ptr->SetCallFast();
receiver_ptr->fast_value_ = argument;
if (receiver_ptr->write_to_fallback_ == FallbackPolicy::kRequestFallback) {
// Anything != 0 has the same effect here, but we're writing 1 to match
@@ -27692,10 +27758,10 @@ struct ApiNumberChecker : BasicApiChecker<T, ApiNumberChecker<T>, void> {
return;
}
ApiNumberChecker<T>* checker =
- GetInternalField<ApiNumberChecker<T>, kV8WrapperObjectIndex>(receiver);
+ GetInternalField<ApiNumberChecker<T>>(receiver);
CHECK_EQ(info.Length(), checker->args_count_);
- checker->result_ |= ApiCheckerResult::kSlowCalled;
+ checker->SetCallSlow();
LocalContext env;
checker->slow_value_ = ConvertJSValue<T>::Get(info[0], env.local());
@@ -27714,17 +27780,15 @@ struct ApiNumberChecker : BasicApiChecker<T, ApiNumberChecker<T>, void> {
};
struct UnexpectedObjectChecker
- : BasicApiChecker<v8::ApiObject, UnexpectedObjectChecker, void> {
- static void FastCallback(v8::ApiObject receiver, v8::ApiObject argument,
+ : BasicApiChecker<v8::Local<v8::Value>, UnexpectedObjectChecker, void> {
+ static void FastCallback(v8::Local<v8::Object> receiver,
+ v8::Local<v8::Value> argument,
v8::FastApiCallbackOptions& options) {
- v8::Object* receiver_obj = reinterpret_cast<v8::Object*>(&receiver);
UnexpectedObjectChecker* receiver_ptr =
- GetInternalField<UnexpectedObjectChecker, kV8WrapperObjectIndex>(
- receiver_obj);
- receiver_ptr->result_ |= ApiCheckerResult::kFastCalled;
- v8::Value* argument_value = reinterpret_cast<v8::Value*>(&argument);
- if (argument_value->IsObject()) {
- v8::Object* argument_obj = reinterpret_cast<v8::Object*>(&argument);
+ GetInternalField<UnexpectedObjectChecker>(*receiver);
+ receiver_ptr->SetCallFast();
+ if (argument->IsObject()) {
+ v8::Object* argument_obj = v8::Object::Cast(*argument);
CHECK(!IsValidUnwrapObject(argument_obj));
}
}
@@ -27732,9 +27796,8 @@ struct UnexpectedObjectChecker
static void SlowCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Object* receiver_obj = v8::Object::Cast(*info.Holder());
UnexpectedObjectChecker* receiver_ptr =
- GetInternalField<UnexpectedObjectChecker, kV8WrapperObjectIndex>(
- receiver_obj);
- receiver_ptr->result_ |= ApiCheckerResult::kSlowCalled;
+ GetInternalField<UnexpectedObjectChecker>(receiver_obj);
+ receiver_ptr->SetCallSlow();
if (info[0]->IsObject()) {
v8::Object* argument_obj = v8::Object::Cast(*info[0]);
CHECK(!IsValidUnwrapObject(argument_obj));
@@ -27742,6 +27805,44 @@ struct UnexpectedObjectChecker
}
};
+struct EmbedderType {
+ int data;
+};
+
+struct ApiObjectChecker
+ : BasicApiChecker<v8::Local<v8::Value>, ApiObjectChecker, void> {
+ ApiObjectChecker(v8::FunctionTemplate* ctor, int data)
+ : ctor_(ctor), initial_data_(data) {}
+
+ static void FastCallback(v8::Local<v8::Object> receiver,
+ v8::Local<v8::Value> argument,
+ v8::FastApiCallbackOptions& options) {
+ ApiObjectChecker* receiver_ptr =
+ GetInternalField<ApiObjectChecker>(*receiver);
+ receiver_ptr->SetCallFast();
+
+ v8::Object* argument_obj = v8::Object::Cast(*argument);
+ EmbedderType* argument_ptr = GetInternalField<EmbedderType>(argument_obj);
+ CHECK(receiver_ptr->ctor_->IsLeafTemplateForApiObject(argument));
+
+ argument_ptr->data = receiver_ptr->initial_data_;
+ }
+ static void SlowCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ v8::Object* receiver_obj = v8::Object::Cast(*info.Holder());
+ ApiObjectChecker* receiver_ptr =
+ GetInternalField<ApiObjectChecker>(receiver_obj);
+ receiver_ptr->SetCallSlow();
+
+ CHECK(info[0]->IsObject());
+ v8::Local<v8::Object> argument_obj = info[0].As<v8::Object>();
+ CHECK(receiver_ptr->ctor_->IsLeafTemplateForApiObject(argument_obj));
+ }
+
+ v8::FunctionTemplate* ctor_;
+ int fast_value_ = 0;
+ int initial_data_;
+};
+
template <typename Value, typename Impl, typename Ret>
bool SetupTest(v8::Local<v8::Value> initial_value, LocalContext* env,
BasicApiChecker<Value, Impl, Ret>* checker,
@@ -27833,7 +27934,7 @@ void CallAndCheck(
"function func(arg) { return receiver.api_func(arg); }"
"%PrepareFunctionForOptimization(func);"
"func(value);");
- checker.result_ = ApiCheckerResult::kNotCalled;
+ checker.Reset();
v8::Isolate* isolate = CcTest::isolate();
v8::TryCatch try_catch(isolate);
@@ -27862,24 +27963,57 @@ void CallAndCheck(
}
}
+void CheckApiObjectArg() {
+ LocalContext env;
+ v8::Isolate* isolate = CcTest::isolate();
+ Local<v8::FunctionTemplate> api_obj_ctor = v8::FunctionTemplate::New(isolate);
+ v8::Local<v8::ObjectTemplate> api_obj_template =
+ api_obj_ctor->InstanceTemplate();
+ api_obj_template->SetInternalFieldCount(kV8WrapperObjectIndex + 1);
+
+ EmbedderType embedder_obj;
+ v8::Local<v8::Object> api_obj =
+ api_obj_template->NewInstance(env.local()).ToLocalChecked();
+ api_obj->SetAlignedPointerInInternalField(
+ kV8WrapperObjectIndex, reinterpret_cast<void*>(&embedder_obj));
+ CHECK(env->Global()
+ ->Set(env.local(), v8_str("api_object"), api_obj)
+ .FromJust());
+
+ const int data = 42;
+ ApiObjectChecker checker(*api_obj_ctor, data);
+ bool has_caught =
+ SetupTest(v8_num(data), &env, &checker,
+ "function func() { return receiver.api_func(api_object); }"
+ "%PrepareFunctionForOptimization(func);"
+ "func();");
+ checker.Reset();
+ CHECK(!has_caught);
+
+ CompileRun(
+ "%OptimizeFunctionOnNextCall(func);"
+ "func();");
+
+ CHECK(checker.DidCallFast());
+ CHECK_EQ(embedder_obj.data, data);
+ CHECK(!checker.DidCallSlow());
+}
+
template <typename T>
struct ReturnValueChecker : BasicApiChecker<T, ReturnValueChecker<T>, T> {
- static T FastCallback(v8::ApiObject receiver, T arg,
+ static T FastCallback(v8::Local<v8::Object> receiver, T arg,
v8::FastApiCallbackOptions& options) {
- v8::Object* receiver_obj = reinterpret_cast<v8::Object*>(&receiver);
ReturnValueChecker<T>* receiver_ptr =
- GetInternalField<ReturnValueChecker<T>, kV8WrapperObjectIndex>(
- receiver_obj);
- receiver_ptr->result_ |= ApiCheckerResult::kFastCalled;
+ GetInternalField<ReturnValueChecker<T>>(*receiver);
+ receiver_ptr->SetCallFast();
return arg;
}
static void SlowCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Object* receiver_obj = v8::Object::Cast(*info.Holder());
ReturnValueChecker<T>* receiver_ptr =
- GetInternalField<ReturnValueChecker<T>, kV8WrapperObjectIndex>(
- receiver_obj);
- receiver_ptr->result_ |= ApiCheckerResult::kSlowCalled;
+ GetInternalField<ReturnValueChecker<T>>(receiver_obj);
+ receiver_ptr->SetCallSlow();
info.GetReturnValue().Set(info[0]);
}
};
@@ -27896,7 +28030,7 @@ void CheckFastReturnValue(v8::Local<v8::Value> expected_value,
"%PrepareFunctionForOptimization(func);"
"func(value);");
CHECK(!has_caught);
- checker.result_ = ApiCheckerResult::kNotCalled;
+ checker.Reset();
v8::Isolate* isolate = CcTest::isolate();
v8::TryCatch try_catch(isolate);
@@ -28064,12 +28198,12 @@ TEST(FastApiStackSlot) {
#ifndef V8_LITE_MODE
if (i::FLAG_jitless) return;
- FLAG_SCOPE_EXTERNAL(opt);
- FLAG_SCOPE_EXTERNAL(turbo_fast_api_calls);
- FLAG_SCOPE_EXTERNAL(allow_natives_syntax);
+ v8::internal::FLAG_opt = true;
+ v8::internal::FLAG_turbo_fast_api_calls = true;
+ v8::internal::FLAG_allow_natives_syntax = true;
// Disable --always_opt, otherwise we haven't generated the necessary
// feedback to go down the "best optimization" path for the fast call.
- UNFLAG_SCOPE_EXTERNAL(always_opt);
+ v8::internal::FLAG_always_opt = false;
v8::Isolate* isolate = CcTest::isolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
@@ -28095,7 +28229,7 @@ TEST(FastApiStackSlot) {
" };"
" return foo;"
"};");
- checker.result_ = ApiCheckerResult::kNotCalled;
+ checker.Reset();
v8::TryCatch try_catch(isolate);
v8::Local<v8::Value> foo =
@@ -28115,12 +28249,12 @@ TEST(FastApiCalls) {
#ifndef V8_LITE_MODE
if (i::FLAG_jitless) return;
- FLAG_SCOPE_EXTERNAL(opt);
- FLAG_SCOPE_EXTERNAL(turbo_fast_api_calls);
- FLAG_SCOPE_EXTERNAL(allow_natives_syntax);
+ v8::internal::FLAG_opt = true;
+ v8::internal::FLAG_turbo_fast_api_calls = true;
+ v8::internal::FLAG_allow_natives_syntax = true;
// Disable --always_opt, otherwise we haven't generated the necessary
// feedback to go down the "best optimization" path for the fast call.
- UNFLAG_SCOPE_EXTERNAL(always_opt);
+ v8::internal::FLAG_always_opt = false;
v8::Isolate* isolate = CcTest::isolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
@@ -28571,8 +28705,8 @@ TEST(FastApiCalls) {
CallWithUnexpectedObjectType(v8_str("str"));
CallWithUnexpectedObjectType(CompileRun("new Proxy({}, {});"));
- // TODO(mslekova): Add corner cases for 64-bit values.
- // TODO(mslekova): Add main cases for float and double.
+ CheckApiObjectArg();
+
// TODO(mslekova): Restructure the tests so that the fast optimized calls
// are compared against the slow optimized calls.
// TODO(mslekova): Add tests for FTI that requires access check.
@@ -28943,3 +29077,52 @@ THREADED_TEST(MicrotaskQueueOfContext) {
microtask_queue.get());
CHECK_EQ(context->GetMicrotaskQueue(), microtask_queue.get());
}
+
+namespace {
+
+bool sab_constructor_enabled_value = false;
+
+bool MockSabConstructorEnabledCallback(v8::Local<v8::Context>) {
+ return sab_constructor_enabled_value;
+}
+
+} // namespace
+
+TEST(TestSetSabConstructorEnabledCallback) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ v8::HandleScope scope(isolate);
+ v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
+ i::Handle<i::Context> i_context = v8::Utils::OpenHandle(*context);
+
+ // {Isolate::IsSharedArrayBufferConstructorEnabled} calls the callback set by
+ // the embedder if such a callback exists. Otherwise it returns
+ // {FLAG_harmony_sharedarraybuffer}. First we test that the flag is returned
+ // correctly if no callback is set. Then we test that the flag is ignored if
+ // the callback is set.
+
+ i::FLAG_harmony_sharedarraybuffer = false;
+ i::FLAG_enable_sharedarraybuffer_per_context = false;
+ CHECK(!i_isolate->IsSharedArrayBufferConstructorEnabled(i_context));
+
+ i::FLAG_harmony_sharedarraybuffer = false;
+ i::FLAG_enable_sharedarraybuffer_per_context = false;
+ CHECK(!i_isolate->IsSharedArrayBufferConstructorEnabled(i_context));
+
+ i::FLAG_harmony_sharedarraybuffer = true;
+ i::FLAG_enable_sharedarraybuffer_per_context = false;
+ CHECK(i_isolate->IsSharedArrayBufferConstructorEnabled(i_context));
+
+ i::FLAG_harmony_sharedarraybuffer = true;
+ i::FLAG_enable_sharedarraybuffer_per_context = true;
+ CHECK(!i_isolate->IsSharedArrayBufferConstructorEnabled(i_context));
+
+ isolate->SetSharedArrayBufferConstructorEnabledCallback(
+ MockSabConstructorEnabledCallback);
+ sab_constructor_enabled_value = false;
+ CHECK(!i_isolate->IsSharedArrayBufferConstructorEnabled(i_context));
+
+ sab_constructor_enabled_value = true;
+ CHECK(i_isolate->IsSharedArrayBufferConstructorEnabled(i_context));
+}