diff options
Diffstat (limited to 'src/api.cc')
-rw-r--r-- | src/api.cc | 1215 |
1 files changed, 843 insertions, 372 deletions
@@ -29,11 +29,13 @@ #include "src/bootstrapper.h" #include "src/char-predicates-inl.h" #include "src/code-stubs.h" +#include "src/compiler-dispatcher/compiler-dispatcher.h" #include "src/compiler.h" #include "src/context-measure.h" #include "src/contexts.h" #include "src/conversions-inl.h" #include "src/counters.h" +#include "src/debug/debug-coverage.h" #include "src/debug/debug.h" #include "src/deoptimizer.h" #include "src/execution.h" @@ -46,6 +48,7 @@ #include "src/json-parser.h" #include "src/json-stringifier.h" #include "src/messages.h" +#include "src/objects-inl.h" #include "src/parsing/parser.h" #include "src/parsing/scanner-character-streams.h" #include "src/pending-compilation-error-handler.h" @@ -97,6 +100,15 @@ namespace v8 { ENTER_V8(isolate); \ bool has_pending_exception = false +#define PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, T) \ + if (IsExecutionTerminatingCheck(isolate)) { \ + return MaybeLocal<T>(); \ + } \ + InternalEscapableScope handle_scope(isolate); \ + CallDepthScope<false> call_depth_scope(isolate, v8::Local<v8::Context>()); \ + ENTER_V8(isolate); \ + bool has_pending_exception = false + #define PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \ bailout_value, HandleScopeClass, \ do_callback) \ @@ -141,6 +153,23 @@ namespace v8 { PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \ false, i::HandleScope, false) +#ifdef DEBUG +#define ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate) \ + i::VMState<v8::OTHER> __state__((isolate)); \ + i::DisallowJavascriptExecutionDebugOnly __no_script__((isolate)); \ + i::DisallowExceptions __no_exceptions__((isolate)) + +#define ENTER_V8_FOR_NEW_CONTEXT(isolate) \ + i::VMState<v8::OTHER> __state__((isolate)); \ + i::DisallowExceptions __no_exceptions__((isolate)) +#else +#define ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate) \ + i::VMState<v8::OTHER> __state__((isolate)); + +#define ENTER_V8_FOR_NEW_CONTEXT(isolate) \ + i::VMState<v8::OTHER> __state__((isolate)); +#endif // DEBUG + #define EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, value) \ do { \ if (has_pending_exception) { \ @@ -243,7 +272,7 @@ class CallDepthScope { static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate, i::Handle<i::Script> script) { - i::Handle<i::Object> scriptName(i::Script::GetNameOrSourceURL(script)); + i::Handle<i::Object> scriptName(script->GetNameOrSourceURL(), isolate); i::Handle<i::Object> source_map_url(script->source_mapping_url(), isolate); v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(script->GetIsolate()); @@ -254,9 +283,10 @@ static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate, v8::Integer::New(v8_isolate, script->column_offset()), v8::Boolean::New(v8_isolate, options.IsSharedCrossOrigin()), v8::Integer::New(v8_isolate, script->id()), - v8::Boolean::New(v8_isolate, options.IsEmbedderDebugScript()), Utils::ToLocal(source_map_url), - v8::Boolean::New(v8_isolate, options.IsOpaque())); + v8::Boolean::New(v8_isolate, options.IsOpaque()), + v8::Boolean::New(v8_isolate, script->type() == i::Script::TYPE_WASM), + v8::Boolean::New(v8_isolate, options.IsModule())); return origin; } @@ -452,6 +482,7 @@ bool RunExtraCode(Isolate* isolate, Local<Context> context, struct SnapshotCreatorData { explicit SnapshotCreatorData(Isolate* isolate) : isolate_(isolate), + default_context_(), contexts_(isolate), templates_(isolate), created_(false) {} @@ -462,8 +493,10 @@ struct SnapshotCreatorData { ArrayBufferAllocator allocator_; Isolate* isolate_; + Persistent<Context> default_context_; PersistentValueVector<Context> contexts_; PersistentValueVector<Template> templates_; + std::vector<SerializeInternalFieldsCallback> internal_fields_serializers_; bool created_; }; @@ -500,7 +533,18 @@ Isolate* SnapshotCreator::GetIsolate() { return SnapshotCreatorData::cast(data_)->isolate_; } -size_t SnapshotCreator::AddContext(Local<Context> context) { +void SnapshotCreator::SetDefaultContext(Local<Context> context) { + DCHECK(!context.IsEmpty()); + SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); + DCHECK(!data->created_); + DCHECK(data->default_context_.IsEmpty()); + Isolate* isolate = data->isolate_; + CHECK_EQ(isolate, context->GetIsolate()); + data->default_context_.Reset(isolate, context); +} + +size_t SnapshotCreator::AddContext(Local<Context> context, + SerializeInternalFieldsCallback callback) { DCHECK(!context.IsEmpty()); SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); DCHECK(!data->created_); @@ -508,6 +552,7 @@ size_t SnapshotCreator::AddContext(Local<Context> context) { CHECK_EQ(isolate, context->GetIsolate()); size_t index = static_cast<int>(data->contexts_.Size()); data->contexts_.Append(context); + data->internal_fields_serializers_.push_back(callback); return index; } @@ -523,11 +568,13 @@ size_t SnapshotCreator::AddTemplate(Local<Template> template_obj) { } StartupData SnapshotCreator::CreateBlob( - SnapshotCreator::FunctionCodeHandling function_code_handling, - SerializeInternalFieldsCallback callback) { + SnapshotCreator::FunctionCodeHandling function_code_handling) { SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_); DCHECK(!data->created_); + DCHECK(!data->default_context_.IsEmpty()); + + int num_additional_contexts = static_cast<int>(data->contexts_.Size()); { int num_templates = static_cast<int>(data->templates_.Size()); @@ -539,6 +586,18 @@ StartupData SnapshotCreator::CreateBlob( } isolate->heap()->SetSerializedTemplates(*templates); data->templates_.Clear(); + + // We need to store the global proxy size upfront in case we need the + // bootstrapper to create a global proxy before we deserialize the context. + i::Handle<i::FixedArray> global_proxy_sizes = + isolate->factory()->NewFixedArray(num_additional_contexts, i::TENURED); + for (int i = 0; i < num_additional_contexts; i++) { + i::Handle<i::Context> context = + v8::Utils::OpenHandle(*data->contexts_.Get(i)); + global_proxy_sizes->set(i, + i::Smi::FromInt(context->global_proxy()->Size())); + } + isolate->heap()->SetSerializedGlobalProxySizes(*global_proxy_sizes); } // If we don't do this then we end up with a stray root pointing at the @@ -549,15 +608,20 @@ StartupData SnapshotCreator::CreateBlob( i::DisallowHeapAllocation no_gc_from_here_on; - int num_contexts = static_cast<int>(data->contexts_.Size()); - i::List<i::Object*> contexts(num_contexts); - for (int i = 0; i < num_contexts; i++) { + i::List<i::Object*> contexts(num_additional_contexts); + i::Object* default_context; + { i::HandleScope scope(isolate); - i::Handle<i::Context> context = - v8::Utils::OpenHandle(*data->contexts_.Get(i)); - contexts.Add(*context); + default_context = + *v8::Utils::OpenHandle(*data->default_context_.Get(data->isolate_)); + data->default_context_.Reset(); + for (int i = 0; i < num_additional_contexts; i++) { + i::Handle<i::Context> context = + v8::Utils::OpenHandle(*data->contexts_.Get(i)); + contexts.Add(*context); + } + data->contexts_.Clear(); } - data->contexts_.Clear(); #ifdef DEBUG i::ExternalReferenceTable::instance(isolate)->ResetCount(); @@ -567,11 +631,20 @@ StartupData SnapshotCreator::CreateBlob( startup_serializer.SerializeStrongReferences(); // Serialize each context with a new partial serializer. - i::List<i::SnapshotData*> context_snapshots(num_contexts); - for (int i = 0; i < num_contexts; i++) { - i::PartialSerializer partial_serializer(isolate, &startup_serializer, - callback); - partial_serializer.Serialize(&contexts[i]); + i::List<i::SnapshotData*> context_snapshots(num_additional_contexts + 1); + + { + // The default snapshot does not support internal fields. + i::PartialSerializer partial_serializer( + isolate, &startup_serializer, v8::SerializeInternalFieldsCallback()); + partial_serializer.Serialize(&default_context, false); + context_snapshots.Add(new i::SnapshotData(&partial_serializer)); + } + + for (int i = 0; i < num_additional_contexts; i++) { + i::PartialSerializer partial_serializer( + isolate, &startup_serializer, data->internal_fields_serializers_[i]); + partial_serializer.Serialize(&contexts[i], true); context_snapshots.Add(new i::SnapshotData(&partial_serializer)); } @@ -611,7 +684,7 @@ StartupData V8::CreateSnapshotDataBlob(const char* embedded_source) { !RunExtraCode(isolate, context, embedded_source, "<embedded>")) { return result; } - snapshot_creator.AddContext(context); + snapshot_creator.SetDefaultContext(context); } result = snapshot_creator.CreateBlob( SnapshotCreator::FunctionCodeHandling::kClear); @@ -652,7 +725,7 @@ StartupData V8::WarmUpSnapshotDataBlob(StartupData cold_snapshot_blob, HandleScope handle_scope(isolate); isolate->ContextDisposedNotification(false); Local<Context> context = Context::New(isolate); - snapshot_creator.AddContext(context); + snapshot_creator.SetDefaultContext(context); } result = snapshot_creator.CreateBlob( SnapshotCreator::FunctionCodeHandling::kKeep); @@ -929,6 +1002,12 @@ HandleScope::~HandleScope() { i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_); } +V8_NORETURN void* HandleScope::operator new(size_t) { + base::OS::Abort(); + abort(); +} + +void HandleScope::operator delete(void*, size_t) { base::OS::Abort(); } int HandleScope::NumberOfHandles(Isolate* isolate) { return i::HandleScope::NumberOfHandles( @@ -967,6 +1046,13 @@ i::Object** EscapableHandleScope::Escape(i::Object** escape_value) { return escape_slot_; } +V8_NORETURN void* EscapableHandleScope::operator new(size_t) { + base::OS::Abort(); + abort(); +} + +void EscapableHandleScope::operator delete(void*, size_t) { base::OS::Abort(); } + SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(reinterpret_cast<i::Isolate*>(isolate)) { i::HandleScopeData* current = isolate_->handle_scope_data(); @@ -985,11 +1071,17 @@ SealHandleScope::~SealHandleScope() { current->sealed_level = prev_sealed_level_; } +V8_NORETURN void* SealHandleScope::operator new(size_t) { + base::OS::Abort(); + abort(); +} + +void SealHandleScope::operator delete(void*, size_t) { base::OS::Abort(); } void Context::Enter() { i::Handle<i::Context> env = Utils::OpenHandle(this); i::Isolate* isolate = env->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); impl->EnterContext(env); impl->SaveContext(isolate->context()); @@ -1000,7 +1092,7 @@ void Context::Enter() { void Context::Exit() { i::Handle<i::Context> env = Utils::OpenHandle(this); i::Isolate* isolate = env->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); if (!Utils::ApiCheck(impl->LastEnteredContextWas(env), "v8::Context::Exit()", @@ -1099,7 +1191,7 @@ void Template::Set(v8::Local<Name> name, v8::Local<Data> value, v8::PropertyAttribute attribute) { auto templ = Utils::OpenHandle(this); i::Isolate* isolate = templ->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); auto value_obj = Utils::OpenHandle(*value); CHECK(!value_obj->IsJSReceiver() || value_obj->IsTemplateInfo()); @@ -1130,7 +1222,7 @@ void Template::SetAccessorProperty( DCHECK_EQ(v8::DEFAULT, access_control); auto templ = Utils::OpenHandle(this); auto isolate = templ->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); DCHECK(!name.IsEmpty()); DCHECK(!getter.IsEmpty() || !setter.IsEmpty()); i::HandleScope scope(isolate); @@ -1154,7 +1246,7 @@ static Local<ObjectTemplate> ObjectTemplateNew( Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() { i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate(); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template(), i_isolate); if (result->IsUndefined(i_isolate)) { @@ -1166,6 +1258,16 @@ Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() { return ToApiHandle<ObjectTemplate>(result); } +void FunctionTemplate::SetPrototypeProviderTemplate( + Local<FunctionTemplate> prototype_provider) { + i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate(); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); + i::Handle<i::Object> result = Utils::OpenHandle(*prototype_provider); + auto info = Utils::OpenHandle(this); + CHECK(info->prototype_template()->IsUndefined(i_isolate)); + CHECK(info->parent_template()->IsUndefined(i_isolate)); + info->set_prototype_provider_template(*result); +} static void EnsureNotInstantiated(i::Handle<i::FunctionTemplateInfo> info, const char* func) { @@ -1177,8 +1279,9 @@ static void EnsureNotInstantiated(i::Handle<i::FunctionTemplateInfo> info, void FunctionTemplate::Inherit(v8::Local<FunctionTemplate> value) { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::Inherit"); - i::Isolate* isolate = info->GetIsolate(); - ENTER_V8(isolate); + i::Isolate* i_isolate = info->GetIsolate(); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); + CHECK(info->prototype_provider_template()->IsUndefined(i_isolate)); info->set_parent_template(*Utils::OpenHandle(*value)); } @@ -1193,7 +1296,7 @@ static Local<FunctionTemplate> FunctionTemplateNew( i::Handle<i::FunctionTemplateInfo>::cast(struct_obj); InitializeFunctionTemplate(obj); obj->set_do_not_cache(do_not_cache); - int next_serial_number = 0; + int next_serial_number = i::FunctionTemplateInfo::kInvalidSerialNumber; if (!do_not_cache) { next_serial_number = isolate->heap()->GetNextTemplateSerialNumber(); } @@ -1224,7 +1327,7 @@ Local<FunctionTemplate> FunctionTemplate::New( // Changes to the environment cannot be captured in the snapshot. Expect no // function templates when the isolate is created for serialization. LOG_API(i_isolate, FunctionTemplate, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); auto templ = FunctionTemplateNew(i_isolate, callback, nullptr, data, signature, length, false); if (behavior == ConstructorBehavior::kThrow) templ->RemovePrototype(); @@ -1252,7 +1355,7 @@ Local<FunctionTemplate> FunctionTemplate::NewWithFastHandler( v8::Local<Signature> signature, int length) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, FunctionTemplate, NewWithFastHandler); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); return FunctionTemplateNew(i_isolate, callback, fast_handler, data, signature, length, false); } @@ -1261,8 +1364,8 @@ Local<FunctionTemplate> FunctionTemplate::NewWithCache( Isolate* isolate, FunctionCallback callback, Local<Private> cache_property, Local<Value> data, Local<Signature> signature, int length) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); - LOG_API(i_isolate, FunctionTemplate, NewWithFastHandler); - ENTER_V8(i_isolate); + LOG_API(i_isolate, FunctionTemplate, NewWithCache); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); return FunctionTemplateNew(i_isolate, callback, nullptr, data, signature, length, false, cache_property); } @@ -1291,7 +1394,7 @@ void FunctionTemplate::SetCallHandler( auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::SetCallHandler"); i::Isolate* isolate = info->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); i::Handle<i::Struct> struct_obj = isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE); @@ -1363,7 +1466,7 @@ Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() { return Local<ObjectTemplate>(); } i::Isolate* isolate = handle->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); if (handle->instance_template()->IsUndefined(isolate)) { Local<ObjectTemplate> templ = ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle)); @@ -1379,7 +1482,7 @@ void FunctionTemplate::SetLength(int length) { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::SetLength"); auto isolate = info->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); info->set_length(length); } @@ -1388,7 +1491,7 @@ void FunctionTemplate::SetClassName(Local<String> name) { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::SetClassName"); auto isolate = info->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); info->set_class_name(*Utils::OpenHandle(*name)); } @@ -1397,7 +1500,7 @@ void FunctionTemplate::SetAcceptAnyReceiver(bool value) { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::SetAcceptAnyReceiver"); auto isolate = info->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); info->set_accept_any_receiver(value); } @@ -1406,7 +1509,7 @@ void FunctionTemplate::SetHiddenPrototype(bool value) { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::SetHiddenPrototype"); auto isolate = info->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); info->set_hidden_prototype(value); } @@ -1415,7 +1518,7 @@ void FunctionTemplate::ReadOnlyPrototype() { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::ReadOnlyPrototype"); auto isolate = info->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); info->set_read_only_prototype(true); } @@ -1424,7 +1527,7 @@ void FunctionTemplate::RemovePrototype() { auto info = Utils::OpenHandle(this); EnsureNotInstantiated(info, "v8::FunctionTemplate::RemovePrototype"); auto isolate = info->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); info->set_remove_prototype(true); } @@ -1446,7 +1549,7 @@ static Local<ObjectTemplate> ObjectTemplateNew( i::Isolate* isolate, v8::Local<FunctionTemplate> constructor, bool do_not_cache) { LOG_API(isolate, ObjectTemplate, New); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::Handle<i::Struct> struct_obj = isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE); i::Handle<i::ObjectTemplateInfo> obj = @@ -1511,7 +1614,7 @@ static bool TemplateSetAccessor(Template* template_obj, v8::Local<Name> name, bool replace_on_access) { auto info = Utils::OpenHandle(template_obj); auto isolate = info->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); auto obj = MakeAccessorInfo(name, getter, setter, data, settings, attribute, @@ -1558,7 +1661,7 @@ void Template::SetIntrinsicDataProperty(Local<Name> name, Intrinsic intrinsic, PropertyAttribute attribute) { auto templ = Utils::OpenHandle(this); i::Isolate* isolate = templ->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name), intrinsic, @@ -1631,7 +1734,7 @@ static void ObjectTemplateSetNamedPropertyHandler( Descriptor descriptor, Deleter remover, Enumerator enumerator, Definer definer, Local<Value> data, PropertyHandlerFlags flags) { i::Isolate* isolate = Utils::OpenHandle(templ)->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); auto cons = EnsureConstructor(isolate, templ); EnsureNotInstantiated(cons, "ObjectTemplateSetNamedPropertyHandler"); @@ -1660,7 +1763,7 @@ void ObjectTemplate::SetHandler( void ObjectTemplate::MarkAsUndetectable() { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); auto cons = EnsureConstructor(isolate, this); EnsureNotInstantiated(cons, "v8::ObjectTemplate::MarkAsUndetectable"); @@ -1671,7 +1774,7 @@ void ObjectTemplate::MarkAsUndetectable() { void ObjectTemplate::SetAccessCheckCallback(AccessCheckCallback callback, Local<Value> data) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); auto cons = EnsureConstructor(isolate, this); EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetAccessCheckCallback"); @@ -1700,7 +1803,7 @@ void ObjectTemplate::SetAccessCheckCallbackAndHandler( const IndexedPropertyHandlerConfiguration& indexed_handler, Local<Value> data) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); auto cons = EnsureConstructor(isolate, this); EnsureNotInstantiated( @@ -1736,7 +1839,7 @@ void ObjectTemplate::SetAccessCheckCallbackAndHandler( void ObjectTemplate::SetHandler( const IndexedPropertyHandlerConfiguration& config) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); auto cons = EnsureConstructor(isolate, this); EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetHandler"); @@ -1751,7 +1854,7 @@ void ObjectTemplate::SetHandler( void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback, Local<Value> data) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); auto cons = EnsureConstructor(isolate, this); EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetCallAsFunctionHandler"); @@ -1780,7 +1883,7 @@ void ObjectTemplate::SetInternalFieldCount(int value) { "Invalid internal field count")) { return; } - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); if (value > 0) { // The internal field count is set by the constructor function's // construct code, so we ensure that there is a constructor @@ -1796,7 +1899,7 @@ bool ObjectTemplate::IsImmutableProto() { void ObjectTemplate::SetImmutableProto() { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); Utils::OpenHandle(this)->set_immutable_proto(true); } @@ -2003,8 +2106,7 @@ MaybeLocal<Value> Module::Evaluate(Local<Context> context) { } MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundInternal( - Isolate* v8_isolate, Source* source, CompileOptions options, - bool is_module) { + Isolate* v8_isolate, Source* source, CompileOptions options) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); PREPARE_FOR_EXECUTION_WITH_ISOLATE(isolate, ScriptCompiler, CompileUnbound, UnboundScript); @@ -2049,7 +2151,7 @@ MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundInternal( result = i::Compiler::GetSharedFunctionInfoForScript( str, name_obj, line_offset, column_offset, source->resource_options, source_map_url, isolate->native_context(), NULL, &script_data, options, - i::NOT_NATIVES_CODE, is_module); + i::NOT_NATIVES_CODE); has_pending_exception = result.is_null(); if (has_pending_exception && script_data != NULL) { // This case won't happen during normal operation; we have compiled @@ -2078,24 +2180,34 @@ MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundInternal( MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundScript( Isolate* v8_isolate, Source* source, CompileOptions options) { - return CompileUnboundInternal(v8_isolate, source, options, false); + Utils::ApiCheck( + !source->GetResourceOptions().IsModule(), + "v8::ScriptCompiler::CompileUnboundScript", + "v8::ScriptCompiler::CompileModule must be used to compile modules"); + return CompileUnboundInternal(v8_isolate, source, options); } Local<UnboundScript> ScriptCompiler::CompileUnbound(Isolate* v8_isolate, Source* source, CompileOptions options) { - RETURN_TO_LOCAL_UNCHECKED( - CompileUnboundInternal(v8_isolate, source, options, false), - UnboundScript); + Utils::ApiCheck( + !source->GetResourceOptions().IsModule(), + "v8::ScriptCompiler::CompileUnbound", + "v8::ScriptCompiler::CompileModule must be used to compile modules"); + RETURN_TO_LOCAL_UNCHECKED(CompileUnboundInternal(v8_isolate, source, options), + UnboundScript); } MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context, Source* source, CompileOptions options) { + Utils::ApiCheck( + !source->GetResourceOptions().IsModule(), "v8::ScriptCompiler::Compile", + "v8::ScriptCompiler::CompileModule must be used to compile modules"); auto isolate = context->GetIsolate(); - auto maybe = CompileUnboundInternal(isolate, source, options, false); + auto maybe = CompileUnboundInternal(isolate, source, options); Local<UnboundScript> result; if (!maybe.ToLocal(&result)) return MaybeLocal<Script>(); v8::Context::Scope scope(context); @@ -2115,7 +2227,10 @@ MaybeLocal<Module> ScriptCompiler::CompileModule(Isolate* isolate, Source* source) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); - auto maybe = CompileUnboundInternal(isolate, source, kNoCompileOptions, true); + Utils::ApiCheck(source->GetResourceOptions().IsModule(), + "v8::ScriptCompiler::CompileModule", + "Invalid ScriptOrigin: is_module must be true"); + auto maybe = CompileUnboundInternal(isolate, source, kNoCompileOptions); Local<UnboundScript> unbound; if (!maybe.ToLocal(&unbound)) return MaybeLocal<Module>(); @@ -2171,9 +2286,14 @@ MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext( Function); TRACE_EVENT0("v8", "V8.ScriptCompiler"); i::Handle<i::String> source_string; + int parameters_end_pos = i::kNoSourcePosition; auto factory = isolate->factory(); if (arguments_count) { - source_string = factory->NewStringFromStaticChars("(function("); + if (i::FLAG_harmony_function_tostring) { + source_string = factory->NewStringFromStaticChars("(function anonymous("); + } else { + source_string = factory->NewStringFromStaticChars("(function("); + } for (size_t i = 0; i < arguments_count; ++i) { IsIdentifierHelper helper; if (!helper.Check(*Utils::OpenHandle(*arguments[i]))) { @@ -2191,12 +2311,24 @@ MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext( ',')).ToHandle(&source_string); RETURN_ON_FAILED_EXECUTION(Function); } - auto brackets = factory->NewStringFromStaticChars("){"); + i::Handle<i::String> brackets; + if (i::FLAG_harmony_function_tostring) { + brackets = factory->NewStringFromStaticChars("\n) {"); + parameters_end_pos = source_string->length() - 3; + } else { + brackets = factory->NewStringFromStaticChars("){"); + } has_pending_exception = !factory->NewConsString(source_string, brackets) .ToHandle(&source_string); RETURN_ON_FAILED_EXECUTION(Function); } else { - source_string = factory->NewStringFromStaticChars("(function(){"); + if (i::FLAG_harmony_function_tostring) { + source_string = + factory->NewStringFromStaticChars("(function anonymous(\n) {"); + parameters_end_pos = source_string->length() - 3; + } else { + source_string = factory->NewStringFromStaticChars("(function(){"); + } } int scope_position = source_string->length(); @@ -2246,9 +2378,9 @@ MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext( has_pending_exception = !i::Compiler::GetFunctionFromEval( source_string, outer_info, context, i::SLOPPY, - i::ONLY_SINGLE_FUNCTION_LITERAL, eval_scope_position, eval_position, - line_offset, column_offset - scope_position, name_obj, - source->resource_options) + i::ONLY_SINGLE_FUNCTION_LITERAL, parameters_end_pos, + eval_scope_position, eval_position, line_offset, + column_offset - scope_position, name_obj, source->resource_options) .ToHandle(&fun); if (has_pending_exception) { isolate->ReportPendingMessages(); @@ -2315,12 +2447,19 @@ MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context, } source->info->set_script(script); + if (source->info->literal() == nullptr) { + source->parser->ReportErrors(isolate, script); + } + source->parser->UpdateStatistics(isolate, script); - // Do the parsing tasks which need to be done on the main thread. This will - // also handle parse errors. - source->parser->Internalize(isolate, script, - source->info->literal() == nullptr); - source->parser->HandleSourceURLComments(isolate, script); + i::DeferredHandleScope deferred_handle_scope(isolate); + { + // Internalize AST values on the main thread. + source->info->ReopenHandlesInNewHandleScope(); + source->info->ast_value_factory()->Internalize(isolate); + source->parser->HandleSourceURLComments(isolate, script); + } + source->info->set_deferred_handles(deferred_handle_scope.Detach()); i::Handle<i::SharedFunctionInfo> result; if (source->info->literal() != nullptr) { @@ -2454,6 +2593,12 @@ v8::TryCatch::~TryCatch() { } } +V8_NORETURN void* v8::TryCatch::operator new(size_t) { + base::OS::Abort(); + abort(); +} + +void v8::TryCatch::operator delete(void*, size_t) { base::OS::Abort(); } bool v8::TryCatch::HasCaught() const { return !reinterpret_cast<i::Object*>(exception_)->IsTheHole(isolate_); @@ -2620,6 +2765,10 @@ int Message::GetEndPosition() const { return self->end_position(); } +int Message::ErrorLevel() const { + auto self = Utils::OpenHandle(this); + return self->error_level(); +} Maybe<int> Message::GetStartColumn(Local<Context> context) const { auto self = Utils::OpenHandle(this); @@ -2821,7 +2970,7 @@ bool StackFrame::IsConstructor() const { Local<NativeWeakMap> NativeWeakMap::New(Isolate* v8_isolate) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::Handle<i::JSWeakMap> weakmap = isolate->factory()->NewJSWeakMap(); i::JSWeakCollection::Initialize(weakmap, isolate); return Utils::NativeWeakMapToLocal(weakmap); @@ -2875,7 +3024,7 @@ Local<Value> NativeWeakMap::Get(Local<Value> v8_key) { bool NativeWeakMap::Has(Local<Value> v8_key) { i::Handle<i::JSWeakMap> weak_collection = Utils::OpenHandle(this); i::Isolate* isolate = weak_collection->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); i::Handle<i::Object> key = Utils::OpenHandle(*v8_key); if (!key->IsJSReceiver() && !key->IsSymbol()) { @@ -2896,7 +3045,7 @@ bool NativeWeakMap::Has(Local<Value> v8_key) { bool NativeWeakMap::Delete(Local<Value> v8_key) { i::Handle<i::JSWeakMap> weak_collection = Utils::OpenHandle(this); i::Isolate* isolate = weak_collection->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); i::Handle<i::Object> key = Utils::OpenHandle(*v8_key); if (!key->IsJSReceiver() && !key->IsSymbol()) { @@ -2982,6 +3131,15 @@ Maybe<bool> ValueSerializer::Delegate::WriteHostObject(Isolate* v8_isolate, return Nothing<bool>(); } +Maybe<uint32_t> ValueSerializer::Delegate::GetSharedArrayBufferId( + Isolate* v8_isolate, Local<SharedArrayBuffer> shared_array_buffer) { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); + isolate->ScheduleThrow(*isolate->factory()->NewError( + isolate->error_function(), i::MessageTemplate::kDataCloneError, + Utils::OpenHandle(*shared_array_buffer))); + return Nothing<uint32_t>(); +} + void* ValueSerializer::Delegate::ReallocateBufferMemory(void* old_buffer, size_t size, size_t* actual_size) { @@ -3011,6 +3169,10 @@ ValueSerializer::~ValueSerializer() { delete private_; } void ValueSerializer::WriteHeader() { private_->serializer.WriteHeader(); } +void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(bool mode) { + private_->serializer.SetTreatArrayBufferViewsAsHostObjects(mode); +} + Maybe<bool> ValueSerializer::WriteValue(Local<Context> context, Local<Value> value) { PREPARE_FOR_EXECUTION_PRIMITIVE(context, ValueSerializer, WriteValue, bool); @@ -3940,7 +4102,7 @@ bool Value::SameValue(Local<Value> that) const { Local<String> Value::TypeOf(v8::Isolate* external_isolate) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); LOG_API(isolate, Value, TypeOf); return Utils::ToLocal(i::Object::TypeOf(isolate, Utils::OpenHandle(this))); } @@ -4343,12 +4505,11 @@ bool v8::Object::SetPrototype(Local<Value> value) { return SetPrototype(context, value).FromMaybe(false); } - Local<Object> v8::Object::FindInstanceInPrototypeChain( v8::Local<FunctionTemplate> tmpl) { - auto isolate = Utils::OpenHandle(this)->GetIsolate(); - i::PrototypeIterator iter(isolate, *Utils::OpenHandle(this), - i::kStartAtReceiver); + auto self = Utils::OpenHandle(this); + auto isolate = self->GetIsolate(); + i::PrototypeIterator iter(isolate, *self, i::kStartAtReceiver); auto tmpl_info = *Utils::OpenHandle(*tmpl); while (!tmpl_info->IsTemplateFor(iter.GetCurrent<i::JSObject>())) { iter.Advance(); @@ -4411,12 +4572,14 @@ MaybeLocal<Array> v8::Object::GetOwnPropertyNames(Local<Context> context, MaybeLocal<String> v8::Object::ObjectProtoToString(Local<Context> context) { PREPARE_FOR_EXECUTION(context, Object, ObjectProtoToString, String); - auto obj = Utils::OpenHandle(this); - Local<String> result; + auto self = Utils::OpenHandle(this); + Local<Value> result; has_pending_exception = - !ToLocal<String>(i::JSObject::ObjectProtoToString(isolate, obj), &result); + !ToLocal<Value>(i::Execution::Call(isolate, isolate->object_to_string(), + self, 0, nullptr), + &result); RETURN_ON_FAILED_EXECUTION(String); - RETURN_ESCAPED(result); + RETURN_ESCAPED(Local<String>::Cast(result)); } @@ -4554,7 +4717,7 @@ static Maybe<bool> ObjectSetAccessor(Local<Context> context, Object* self, has_pending_exception = !i::JSObject::SetAccessor(obj, info).ToHandle(&result); RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); - if (result->IsUndefined(obj->GetIsolate())) return Nothing<bool>(); + if (result->IsUndefined(obj->GetIsolate())) return Just(false); if (fast) { i::JSObject::MigrateSlowToFast(obj, 0, "APISetAccessor"); } @@ -4826,7 +4989,7 @@ Maybe<PropertyAttribute> v8::Object::GetRealNamedPropertyAttributes( Local<v8::Object> v8::Object::Clone() { auto self = i::Handle<i::JSObject>::cast(Utils::OpenHandle(this)); auto isolate = self->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); auto result = isolate->factory()->CopyJSObject(self); CHECK(!result.is_null()); return Utils::ToLocal(result); @@ -4835,8 +4998,7 @@ Local<v8::Object> v8::Object::Clone() { Local<v8::Context> v8::Object::CreationContext() { auto self = Utils::OpenHandle(this); - auto context = handle(self->GetCreationContext()); - return Utils::ToLocal(context); + return Utils::ToLocal(self->GetCreationContext()); } @@ -4915,7 +5077,7 @@ MaybeLocal<Function> Function::New(Local<Context> context, int length, ConstructorBehavior behavior) { i::Isolate* isolate = Utils::OpenHandle(*context)->GetIsolate(); LOG_API(isolate, Function, New); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); auto templ = FunctionTemplateNew(isolate, callback, nullptr, data, Local<Signature>(), length, true); if (behavior == ConstructorBehavior::kThrow) templ->RemovePrototype(); @@ -5109,7 +5271,7 @@ bool Function::IsBuiltin() const { return false; } auto func = i::Handle<i::JSFunction>::cast(self); - return func->shared()->IsBuiltin(); + return !func->shared()->IsUserJavaScript(); } @@ -5680,7 +5842,7 @@ int String::WriteUtf8(char* buffer, i::Handle<i::String> str = Utils::OpenHandle(this); i::Isolate* isolate = str->GetIsolate(); LOG_API(isolate, String, WriteUtf8); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); if (options & HINT_MANY_WRITES_EXPECTED) { str = i::String::Flatten(str); // Flatten the string for efficiency. } @@ -5732,7 +5894,7 @@ static inline int WriteHelper(const String* string, int options) { i::Isolate* isolate = Utils::OpenHandle(string)->GetIsolate(); LOG_API(isolate, String, Write); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); DCHECK(start >= 0 && length >= -1); i::Handle<i::String> str = Utils::OpenHandle(string); if (options & String::HINT_MANY_WRITES_EXPECTED) { @@ -6069,10 +6231,11 @@ struct InvokeBootstrapper<i::Context> { i::Handle<i::Context> Invoke( i::Isolate* isolate, i::MaybeHandle<i::JSGlobalProxy> maybe_global_proxy, v8::Local<v8::ObjectTemplate> global_object_template, - v8::ExtensionConfiguration* extensions, size_t context_snapshot_index) { + v8::ExtensionConfiguration* extensions, size_t context_snapshot_index, + v8::DeserializeInternalFieldsCallback internal_fields_deserializer) { return isolate->bootstrapper()->CreateEnvironment( maybe_global_proxy, global_object_template, extensions, - context_snapshot_index); + context_snapshot_index, internal_fields_deserializer); } }; @@ -6081,7 +6244,8 @@ struct InvokeBootstrapper<i::JSGlobalProxy> { i::Handle<i::JSGlobalProxy> Invoke( i::Isolate* isolate, i::MaybeHandle<i::JSGlobalProxy> maybe_global_proxy, v8::Local<v8::ObjectTemplate> global_object_template, - v8::ExtensionConfiguration* extensions, size_t context_snapshot_index) { + v8::ExtensionConfiguration* extensions, size_t context_snapshot_index, + v8::DeserializeInternalFieldsCallback internal_fields_deserializer) { USE(extensions); USE(context_snapshot_index); return isolate->bootstrapper()->NewRemoteContext(maybe_global_proxy, @@ -6093,15 +6257,19 @@ template <typename ObjectType> static i::Handle<ObjectType> CreateEnvironment( i::Isolate* isolate, v8::ExtensionConfiguration* extensions, v8::MaybeLocal<ObjectTemplate> maybe_global_template, - v8::MaybeLocal<Value> maybe_global_proxy, size_t context_snapshot_index) { + v8::MaybeLocal<Value> maybe_global_proxy, size_t context_snapshot_index, + v8::DeserializeInternalFieldsCallback internal_fields_deserializer) { i::Handle<ObjectType> result; - // Enter V8 via an ENTER_V8 scope. { - ENTER_V8(isolate); + ENTER_V8_FOR_NEW_CONTEXT(isolate); v8::Local<ObjectTemplate> proxy_template; i::Handle<i::FunctionTemplateInfo> proxy_constructor; i::Handle<i::FunctionTemplateInfo> global_constructor; + i::Handle<i::Object> named_interceptor( + isolate->factory()->undefined_value()); + i::Handle<i::Object> indexed_interceptor( + isolate->factory()->undefined_value()); if (!maybe_global_template.IsEmpty()) { v8::Local<v8::ObjectTemplate> global_template = @@ -6134,6 +6302,24 @@ static i::Handle<ObjectType> CreateEnvironment( global_constructor->set_access_check_info( isolate->heap()->undefined_value()); } + + // Same for other interceptors. If the global constructor has + // interceptors, we need to replace them temporarily with noop + // interceptors, so the map is correctly marked as having interceptors, + // but we don't invoke any. + if (!global_constructor->named_property_handler()->IsUndefined(isolate)) { + named_interceptor = + handle(global_constructor->named_property_handler(), isolate); + global_constructor->set_named_property_handler( + isolate->heap()->noop_interceptor_info()); + } + if (!global_constructor->indexed_property_handler()->IsUndefined( + isolate)) { + indexed_interceptor = + handle(global_constructor->indexed_property_handler(), isolate); + global_constructor->set_indexed_property_handler( + isolate->heap()->noop_interceptor_info()); + } } i::MaybeHandle<i::JSGlobalProxy> maybe_proxy; @@ -6143,10 +6329,11 @@ static i::Handle<ObjectType> CreateEnvironment( } // Create the environment. InvokeBootstrapper<ObjectType> invoke; - result = invoke.Invoke(isolate, maybe_proxy, proxy_template, extensions, - context_snapshot_index); + result = + invoke.Invoke(isolate, maybe_proxy, proxy_template, extensions, + context_snapshot_index, internal_fields_deserializer); - // Restore the access check info on the global template. + // Restore the access check info and interceptors on the global template. if (!maybe_global_template.IsEmpty()) { DCHECK(!global_constructor.is_null()); DCHECK(!proxy_constructor.is_null()); @@ -6154,6 +6341,8 @@ static i::Handle<ObjectType> CreateEnvironment( proxy_constructor->access_check_info()); global_constructor->set_needs_access_check( proxy_constructor->needs_access_check()); + global_constructor->set_named_property_handler(*named_interceptor); + global_constructor->set_indexed_property_handler(*indexed_interceptor); } } // Leave V8. @@ -6161,20 +6350,20 @@ static i::Handle<ObjectType> CreateEnvironment( return result; } -Local<Context> NewContext(v8::Isolate* external_isolate, - v8::ExtensionConfiguration* extensions, - v8::MaybeLocal<ObjectTemplate> global_template, - v8::MaybeLocal<Value> global_object, - size_t context_snapshot_index) { +Local<Context> NewContext( + v8::Isolate* external_isolate, v8::ExtensionConfiguration* extensions, + v8::MaybeLocal<ObjectTemplate> global_template, + v8::MaybeLocal<Value> global_object, size_t context_snapshot_index, + v8::DeserializeInternalFieldsCallback internal_fields_deserializer) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate); TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.NewContext"); LOG_API(isolate, Context, New); i::HandleScope scope(isolate); ExtensionConfiguration no_extensions; if (extensions == NULL) extensions = &no_extensions; - i::Handle<i::Context> env = - CreateEnvironment<i::Context>(isolate, extensions, global_template, - global_object, context_snapshot_index); + i::Handle<i::Context> env = CreateEnvironment<i::Context>( + isolate, extensions, global_template, global_object, + context_snapshot_index, internal_fields_deserializer); if (env.is_null()) { if (isolate->has_pending_exception()) { isolate->OptionalRescheduleException(true); @@ -6189,21 +6378,22 @@ Local<Context> v8::Context::New(v8::Isolate* external_isolate, v8::MaybeLocal<ObjectTemplate> global_template, v8::MaybeLocal<Value> global_object) { return NewContext(external_isolate, extensions, global_template, - global_object, 0); + global_object, 0, DeserializeInternalFieldsCallback()); } MaybeLocal<Context> v8::Context::FromSnapshot( v8::Isolate* external_isolate, size_t context_snapshot_index, - v8::ExtensionConfiguration* extensions, - v8::MaybeLocal<ObjectTemplate> global_template, - v8::MaybeLocal<Value> global_object) { + v8::DeserializeInternalFieldsCallback internal_fields_deserializer, + v8::ExtensionConfiguration* extensions, MaybeLocal<Value> global_object) { + size_t index_including_default_context = context_snapshot_index + 1; if (!i::Snapshot::HasContextSnapshot( reinterpret_cast<i::Isolate*>(external_isolate), - context_snapshot_index)) { + index_including_default_context)) { return MaybeLocal<Context>(); } - return NewContext(external_isolate, extensions, global_template, - global_object, context_snapshot_index); + return NewContext(external_isolate, extensions, MaybeLocal<ObjectTemplate>(), + global_object, index_including_default_context, + internal_fields_deserializer); } MaybeLocal<Object> v8::Context::NewRemoteContext( @@ -6225,7 +6415,8 @@ MaybeLocal<Object> v8::Context::NewRemoteContext( "Global template needs to have access check handlers."); i::Handle<i::JSGlobalProxy> global_proxy = CreateEnvironment<i::JSGlobalProxy>(isolate, nullptr, global_template, - global_object, 0); + global_object, 0, + DeserializeInternalFieldsCallback()); if (global_proxy.is_null()) { if (isolate->has_pending_exception()) { isolate->OptionalRescheduleException(true); @@ -6263,7 +6454,6 @@ v8::Isolate* Context::GetIsolate() { return reinterpret_cast<Isolate*>(env->GetIsolate()); } - v8::Local<v8::Object> Context::Global() { i::Handle<i::Context> context = Utils::OpenHandle(this); i::Isolate* isolate = context->GetIsolate(); @@ -6281,7 +6471,7 @@ v8::Local<v8::Object> Context::Global() { void Context::DetachGlobal() { i::Handle<i::Context> context = Utils::OpenHandle(this); i::Isolate* isolate = context->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); isolate->bootstrapper()->DetachGlobal(context); } @@ -6297,7 +6487,7 @@ Local<v8::Object> Context::GetExtrasBindingObject() { void Context::AllowCodeGenerationFromStrings(bool allow) { i::Handle<i::Context> context = Utils::OpenHandle(this); i::Isolate* isolate = context->GetIsolate(); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); context->set_allow_code_gen_from_strings( allow ? isolate->heap()->true_value() : isolate->heap()->false_value()); } @@ -6390,10 +6580,13 @@ bool FunctionTemplate::HasInstance(v8::Local<v8::Value> value) { return true; } if (obj->IsJSGlobalProxy()) { - // If it's a global proxy object, then test with the global object. + // If it's a global proxy, then test with the global object. Note that the + // inner global object may not necessarily be a JSGlobalObject. i::PrototypeIterator iter(i::JSObject::cast(*obj)->map()); - if (iter.IsAtEnd()) return false; - return self->IsTemplateFor(iter.GetCurrent<i::JSGlobalObject>()); + // The global proxy should always have a prototype, as it is a bug to call + // this on a detached JSGlobalProxy. + DCHECK(!iter.IsAtEnd()); + return self->IsTemplateFor(iter.GetCurrent<i::JSObject>()); } return false; } @@ -6403,7 +6596,7 @@ Local<External> v8::External::New(Isolate* isolate, void* value) { STATIC_ASSERT(sizeof(value) == sizeof(i::Address)); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, External, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::JSObject> external = i_isolate->factory()->NewExternal(value); return Utils::ExternalToLocal(external); } @@ -6482,7 +6675,7 @@ STATIC_ASSERT(v8::String::kMaxLength == i::String::kMaxLength); result = MaybeLocal<String>(); \ } else { \ i::Isolate* i_isolate = reinterpret_cast<internal::Isolate*>(isolate); \ - ENTER_V8(i_isolate); \ + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); \ LOG_API(i_isolate, class_name, function_name); \ if (length < 0) length = StringLength(data); \ i::Handle<i::String> handle_result = \ @@ -6569,13 +6762,19 @@ MaybeLocal<String> v8::String::NewExternalTwoByte( return MaybeLocal<String>(); } i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); LOG_API(i_isolate, String, NewExternalTwoByte); - i::Handle<i::String> string = i_isolate->factory() - ->NewExternalStringFromTwoByte(resource) - .ToHandleChecked(); - i_isolate->heap()->RegisterExternalString(*string); - return Utils::ToLocal(string); + if (resource->length() > 0) { + i::Handle<i::String> string = i_isolate->factory() + ->NewExternalStringFromTwoByte(resource) + .ToHandleChecked(); + i_isolate->heap()->RegisterExternalString(*string); + return Utils::ToLocal(string); + } else { + // The resource isn't going to be used, free it immediately. + resource->Dispose(); + return Utils::ToLocal(i_isolate->factory()->empty_string()); + } } @@ -6593,13 +6792,19 @@ MaybeLocal<String> v8::String::NewExternalOneByte( return MaybeLocal<String>(); } i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); LOG_API(i_isolate, String, NewExternalOneByte); - i::Handle<i::String> string = i_isolate->factory() - ->NewExternalStringFromOneByte(resource) - .ToHandleChecked(); - i_isolate->heap()->RegisterExternalString(*string); - return Utils::ToLocal(string); + if (resource->length() > 0) { + i::Handle<i::String> string = i_isolate->factory() + ->NewExternalStringFromOneByte(resource) + .ToHandleChecked(); + i_isolate->heap()->RegisterExternalString(*string); + return Utils::ToLocal(string); + } else { + // The resource isn't going to be used, free it immediately. + resource->Dispose(); + return Utils::ToLocal(i_isolate->factory()->empty_string()); + } } @@ -6615,7 +6820,7 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { if (i::StringShape(*obj).IsExternal()) { return false; // Already an external string. } - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); if (isolate->heap()->IsInGCPostProcessing()) { return false; } @@ -6639,7 +6844,7 @@ bool v8::String::MakeExternal( if (i::StringShape(*obj).IsExternal()) { return false; // Already an external string. } - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); if (isolate->heap()->IsInGCPostProcessing()) { return false; } @@ -6675,7 +6880,7 @@ Isolate* v8::Object::GetIsolate() { Local<v8::Object> v8::Object::New(Isolate* isolate) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, Object, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::JSObject> obj = i_isolate->factory()->NewJSObject(i_isolate->object_function()); return Utils::ToLocal(obj); @@ -6685,7 +6890,7 @@ Local<v8::Object> v8::Object::New(Isolate* isolate) { Local<v8::Value> v8::NumberObject::New(Isolate* isolate, double value) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, NumberObject, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::Object> number = i_isolate->factory()->NewNumber(value); i::Handle<i::Object> obj = i::Object::ToObject(i_isolate, number).ToHandleChecked(); @@ -6705,7 +6910,7 @@ double v8::NumberObject::ValueOf() const { Local<v8::Value> v8::BooleanObject::New(Isolate* isolate, bool value) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, BooleanObject, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::Object> boolean(value ? i_isolate->heap()->true_value() : i_isolate->heap()->false_value(), i_isolate); @@ -6733,7 +6938,7 @@ Local<v8::Value> v8::StringObject::New(Local<String> value) { i::Handle<i::String> string = Utils::OpenHandle(*value); i::Isolate* isolate = string->GetIsolate(); LOG_API(isolate, StringObject, New); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::Handle<i::Object> obj = i::Object::ToObject(isolate, string).ToHandleChecked(); return Utils::ToLocal(obj); @@ -6753,7 +6958,7 @@ Local<v8::String> v8::StringObject::ValueOf() const { Local<v8::Value> v8::SymbolObject::New(Isolate* isolate, Local<Symbol> value) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, SymbolObject, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::Object> obj = i::Object::ToObject( i_isolate, Utils::OpenHandle(*value)).ToHandleChecked(); return Utils::ToLocal(obj); @@ -6803,7 +7008,7 @@ double v8::Date::ValueOf() const { void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, Date, DateTimeConfigurationChangeNotification); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i_isolate->date_cache()->ResetDateCache(); if (!i_isolate->eternal_handles()->Exists( i::EternalHandles::DATE_CACHE_VERSION)) { @@ -6868,7 +7073,7 @@ v8::RegExp::Flags v8::RegExp::GetFlags() const { Local<v8::Array> v8::Array::New(Isolate* isolate, int length) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, Array, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); int real_length = length > 0 ? length : 0; i::Handle<i::JSArray> obj = i_isolate->factory()->NewJSArray(real_length); i::Handle<i::Object> length_obj = @@ -6913,7 +7118,7 @@ Local<Object> Array::CloneElementAt(uint32_t index) { return Local<Object>(); } Local<v8::Map> v8::Map::New(Isolate* isolate) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, Map, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::JSMap> obj = i_isolate->factory()->NewJSMap(); return Utils::ToLocal(obj); } @@ -6929,7 +7134,7 @@ void Map::Clear() { auto self = Utils::OpenHandle(this); i::Isolate* isolate = self->GetIsolate(); LOG_API(isolate, Map, Clear); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::JSMap::Clear(self); } @@ -6988,15 +7193,14 @@ Maybe<bool> Map::Delete(Local<Context> context, Local<Value> key) { return Just(result->IsTrue(isolate)); } - -Local<Array> Map::AsArray() const { - i::Handle<i::JSMap> obj = Utils::OpenHandle(this); - i::Isolate* isolate = obj->GetIsolate(); +namespace { +i::Handle<i::JSArray> MapAsArray(i::Isolate* isolate, i::Object* table_obj, + int offset, int kind) { i::Factory* factory = isolate->factory(); - LOG_API(isolate, Map, AsArray); - ENTER_V8(isolate); - i::Handle<i::OrderedHashMap> table(i::OrderedHashMap::cast(obj->table())); - int length = table->NumberOfElements() * 2; + i::Handle<i::OrderedHashMap> table(i::OrderedHashMap::cast(table_obj)); + if (offset >= table->NumberOfElements()) return factory->NewJSArray(0); + int length = (table->NumberOfElements() - offset) * + (kind == i::JSMapIterator::kKindEntries ? 2 : 1); i::Handle<i::FixedArray> result = factory->NewFixedArray(length); int result_index = 0; { @@ -7006,22 +7210,37 @@ Local<Array> Map::AsArray() const { for (int i = 0; i < capacity; ++i) { i::Object* key = table->KeyAt(i); if (key == the_hole) continue; - result->set(result_index++, key); - result->set(result_index++, table->ValueAt(i)); + if (offset-- > 0) continue; + if (kind == i::JSMapIterator::kKindEntries || + kind == i::JSMapIterator::kKindKeys) { + result->set(result_index++, key); + } + if (kind == i::JSMapIterator::kKindEntries || + kind == i::JSMapIterator::kKindValues) { + result->set(result_index++, table->ValueAt(i)); + } } } DCHECK_EQ(result_index, result->length()); DCHECK_EQ(result_index, length); - i::Handle<i::JSArray> result_array = - factory->NewJSArrayWithElements(result, i::FAST_ELEMENTS, length); - return Utils::ToLocal(result_array); + return factory->NewJSArrayWithElements(result, i::FAST_ELEMENTS, length); +} +} // namespace + +Local<Array> Map::AsArray() const { + i::Handle<i::JSMap> obj = Utils::OpenHandle(this); + i::Isolate* isolate = obj->GetIsolate(); + LOG_API(isolate, Map, AsArray); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); + return Utils::ToLocal( + MapAsArray(isolate, obj->table(), 0, i::JSMapIterator::kKindEntries)); } Local<v8::Set> v8::Set::New(Isolate* isolate) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, Set, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::JSSet> obj = i_isolate->factory()->NewJSSet(); return Utils::ToLocal(obj); } @@ -7037,7 +7256,7 @@ void Set::Clear() { auto self = Utils::OpenHandle(this); i::Isolate* isolate = self->GetIsolate(); LOG_API(isolate, Set, Clear); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::JSSet::Clear(self); } @@ -7080,15 +7299,13 @@ Maybe<bool> Set::Delete(Local<Context> context, Local<Value> key) { return Just(result->IsTrue(isolate)); } - -Local<Array> Set::AsArray() const { - i::Handle<i::JSSet> obj = Utils::OpenHandle(this); - i::Isolate* isolate = obj->GetIsolate(); +namespace { +i::Handle<i::JSArray> SetAsArray(i::Isolate* isolate, i::Object* table_obj, + int offset) { i::Factory* factory = isolate->factory(); - LOG_API(isolate, Set, AsArray); - ENTER_V8(isolate); - i::Handle<i::OrderedHashSet> table(i::OrderedHashSet::cast(obj->table())); - int length = table->NumberOfElements(); + i::Handle<i::OrderedHashSet> table(i::OrderedHashSet::cast(table_obj)); + int length = table->NumberOfElements() - offset; + if (length <= 0) return factory->NewJSArray(0); i::Handle<i::FixedArray> result = factory->NewFixedArray(length); int result_index = 0; { @@ -7098,14 +7315,22 @@ Local<Array> Set::AsArray() const { for (int i = 0; i < capacity; ++i) { i::Object* key = table->KeyAt(i); if (key == the_hole) continue; + if (offset-- > 0) continue; result->set(result_index++, key); } } DCHECK_EQ(result_index, result->length()); DCHECK_EQ(result_index, length); - i::Handle<i::JSArray> result_array = - factory->NewJSArrayWithElements(result, i::FAST_ELEMENTS, length); - return Utils::ToLocal(result_array); + return factory->NewJSArrayWithElements(result, i::FAST_ELEMENTS, length); +} +} // namespace + +Local<Array> Set::AsArray() const { + i::Handle<i::JSSet> obj = Utils::OpenHandle(this); + i::Isolate* isolate = obj->GetIsolate(); + LOG_API(isolate, Set, AsArray); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); + return Utils::ToLocal(SetAsArray(isolate, obj->table(), 0)); } @@ -7113,7 +7338,7 @@ MaybeLocal<Promise::Resolver> Promise::Resolver::New(Local<Context> context) { PREPARE_FOR_EXECUTION(context, Promise_Resolver, New, Resolver); i::Handle<i::Object> result; has_pending_exception = - !i::Execution::Call(isolate, isolate->promise_create(), + !i::Execution::Call(isolate, isolate->promise_internal_constructor(), isolate->factory()->undefined_value(), 0, NULL) .ToHandle(&result); RETURN_ON_FAILED_EXECUTION(Promise::Resolver); @@ -7158,9 +7383,12 @@ Maybe<bool> Promise::Resolver::Reject(Local<Context> context, Local<Value> value) { PREPARE_FOR_EXECUTION_PRIMITIVE(context, Promise_Resolver, Resolve, bool); auto self = Utils::OpenHandle(this); - i::Handle<i::Object> argv[] = {self, Utils::OpenHandle(*value)}; + + // We pass true to trigger the debugger's on exception handler. + i::Handle<i::Object> argv[] = {self, Utils::OpenHandle(*value), + isolate->factory()->ToBoolean(true)}; has_pending_exception = - i::Execution::Call(isolate, isolate->promise_reject(), + i::Execution::Call(isolate, isolate->promise_internal_reject(), isolate->factory()->undefined_value(), arraysize(argv), argv) .is_null(); @@ -7219,11 +7447,32 @@ bool Promise::HasHandler() { i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this); i::Isolate* isolate = promise->GetIsolate(); LOG_API(isolate, Promise, HasRejectHandler); - ENTER_V8(isolate); - i::Handle<i::Symbol> key = isolate->factory()->promise_has_handler_symbol(); - return i::JSReceiver::GetDataProperty(promise, key)->IsTrue(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); + if (promise->IsJSPromise()) { + i::Handle<i::JSPromise> js_promise = i::Handle<i::JSPromise>::cast(promise); + return js_promise->has_handler(); + } + return false; } +Local<Value> Promise::Result() { + i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this); + i::Isolate* isolate = promise->GetIsolate(); + LOG_API(isolate, Promise, Result); + i::Handle<i::JSPromise> js_promise = i::Handle<i::JSPromise>::cast(promise); + Utils::ApiCheck(js_promise->status() != kPending, "v8_Promise_Result", + "Promise is still pending"); + i::Handle<i::Object> result(js_promise->result(), isolate); + return Utils::ToLocal(result); +} + +Promise::PromiseState Promise::State() { + i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this); + i::Isolate* isolate = promise->GetIsolate(); + LOG_API(isolate, Promise, Status); + i::Handle<i::JSPromise> js_promise = i::Handle<i::JSPromise>::cast(promise); + return static_cast<PromiseState>(js_promise->status()); +} Local<Object> Proxy::GetTarget() { i::Handle<i::JSProxy> self = Utils::OpenHandle(this); @@ -7268,7 +7517,7 @@ Local<String> WasmCompiledModule::GetWasmWireBytes() { i::Handle<i::JSObject>::cast(Utils::OpenHandle(this)); i::Handle<i::WasmCompiledModule> compiled_part = i::handle(i::WasmCompiledModule::cast(obj->GetInternalField(0))); - i::Handle<i::String> wire_bytes = compiled_part->module_bytes(); + i::Handle<i::String> wire_bytes(compiled_part->module_bytes()); return Local<String>::Cast(Utils::ToLocal(wire_bytes)); } @@ -7326,11 +7575,8 @@ MaybeLocal<WasmCompiledModule> WasmCompiledModule::Compile(Isolate* isolate, size_t length) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); i::wasm::ErrorThrower thrower(i_isolate, "WasmCompiledModule::Deserialize()"); - i::MaybeHandle<i::JSObject> maybe_compiled = - i::wasm::CreateModuleObjectFromBytes( - i_isolate, start, start + length, &thrower, - i::wasm::ModuleOrigin::kWasmOrigin, i::Handle<i::Script>::null(), - nullptr, nullptr); + i::MaybeHandle<i::JSObject> maybe_compiled = i::wasm::SyncCompile( + i_isolate, &thrower, i::wasm::ModuleWireBytes(start, start + length)); if (maybe_compiled.is_null()) return MaybeLocal<WasmCompiledModule>(); return Local<WasmCompiledModule>::Cast( Utils::ToLocal(maybe_compiled.ToHandleChecked())); @@ -7382,7 +7628,7 @@ void v8::ArrayBuffer::Neuter() { Utils::ApiCheck(obj->is_neuterable(), "v8::ArrayBuffer::Neuter", "Only neuterable ArrayBuffers can be neutered"); LOG_API(isolate, ArrayBuffer, Neuter); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); obj->Neuter(); } @@ -7396,7 +7642,7 @@ size_t v8::ArrayBuffer::ByteLength() const { Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, ArrayBuffer, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::JSArrayBuffer> obj = i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kNotShared); // TODO(jbroman): It may be useful in the future to provide a MaybeLocal @@ -7415,7 +7661,7 @@ Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, void* data, CHECK(byte_length == 0 || data != NULL); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, ArrayBuffer, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::JSArrayBuffer> obj = i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kNotShared); i::JSArrayBuffer::Setup(obj, i_isolate, @@ -7491,7 +7737,7 @@ size_t v8::TypedArray::Length() { size_t byte_offset, size_t length) { \ i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate(); \ LOG_API(isolate, Type##Array, New); \ - ENTER_V8(isolate); \ + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); \ if (!Utils::ApiCheck(length <= static_cast<size_t>(i::Smi::kMaxValue), \ "v8::" #Type \ "Array::New(Local<ArrayBuffer>, size_t, size_t)", \ @@ -7510,7 +7756,7 @@ size_t v8::TypedArray::Length() { i::Isolate* isolate = \ Utils::OpenHandle(*shared_array_buffer)->GetIsolate(); \ LOG_API(isolate, Type##Array, New); \ - ENTER_V8(isolate); \ + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); \ if (!Utils::ApiCheck( \ length <= static_cast<size_t>(i::Smi::kMaxValue), \ "v8::" #Type \ @@ -7533,7 +7779,7 @@ Local<DataView> DataView::New(Local<ArrayBuffer> array_buffer, i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer); i::Isolate* isolate = buffer->GetIsolate(); LOG_API(isolate, DataView, New); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::Handle<i::JSDataView> obj = isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length); return Utils::ToLocal(obj); @@ -7546,7 +7792,7 @@ Local<DataView> DataView::New(Local<SharedArrayBuffer> shared_array_buffer, i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*shared_array_buffer); i::Isolate* isolate = buffer->GetIsolate(); LOG_API(isolate, DataView, New); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::Handle<i::JSDataView> obj = isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length); return Utils::ToLocal(obj); @@ -7590,7 +7836,7 @@ Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(Isolate* isolate, CHECK(i::FLAG_harmony_sharedarraybuffer); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, SharedArrayBuffer, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::JSArrayBuffer> obj = i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kShared); // TODO(jbroman): It may be useful in the future to provide a MaybeLocal @@ -7611,7 +7857,7 @@ Local<SharedArrayBuffer> v8::SharedArrayBuffer::New( CHECK(byte_length == 0 || data != NULL); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, SharedArrayBuffer, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::JSArrayBuffer> obj = i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kShared); i::JSArrayBuffer::Setup(obj, i_isolate, @@ -7624,49 +7870,26 @@ Local<SharedArrayBuffer> v8::SharedArrayBuffer::New( Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, Symbol, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::Symbol> result = i_isolate->factory()->NewSymbol(); if (!name.IsEmpty()) result->set_name(*Utils::OpenHandle(*name)); return Utils::ToLocal(result); } -static i::Handle<i::Symbol> SymbolFor(i::Isolate* isolate, - i::Handle<i::String> name, - i::Handle<i::String> part, - bool private_symbol) { - i::Handle<i::JSObject> registry = isolate->GetSymbolRegistry(); - i::Handle<i::JSObject> symbols = - i::Handle<i::JSObject>::cast( - i::Object::GetPropertyOrElement(registry, part).ToHandleChecked()); - i::Handle<i::Object> symbol = - i::Object::GetPropertyOrElement(symbols, name).ToHandleChecked(); - if (!symbol->IsSymbol()) { - DCHECK(symbol->IsUndefined(isolate)); - if (private_symbol) - symbol = isolate->factory()->NewPrivateSymbol(); - else - symbol = isolate->factory()->NewSymbol(); - i::Handle<i::Symbol>::cast(symbol)->set_name(*name); - i::Object::SetPropertyOrElement(symbols, name, symbol, i::STRICT).Assert(); - } - return i::Handle<i::Symbol>::cast(symbol); -} - - Local<Symbol> v8::Symbol::For(Isolate* isolate, Local<String> name) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); i::Handle<i::String> i_name = Utils::OpenHandle(*name); - i::Handle<i::String> part = i_isolate->factory()->for_string(); - return Utils::ToLocal(SymbolFor(i_isolate, i_name, part, false)); + return Utils::ToLocal(i_isolate->SymbolFor( + i::Heap::kPublicSymbolTableRootIndex, i_name, false)); } Local<Symbol> v8::Symbol::ForApi(Isolate* isolate, Local<String> name) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); i::Handle<i::String> i_name = Utils::OpenHandle(*name); - i::Handle<i::String> part = i_isolate->factory()->for_api_string(); - return Utils::ToLocal(SymbolFor(i_isolate, i_name, part, false)); + return Utils::ToLocal( + i_isolate->SymbolFor(i::Heap::kApiSymbolTableRootIndex, i_name, false)); } @@ -7681,6 +7904,10 @@ Local<Symbol> v8::Symbol::GetUnscopables(Isolate* isolate) { return Utils::ToLocal(i_isolate->factory()->unscopables_symbol()); } +Local<Symbol> v8::Symbol::GetToPrimitive(Isolate* isolate) { + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + return Utils::ToLocal(i_isolate->factory()->to_primitive_symbol()); +} Local<Symbol> v8::Symbol::GetToStringTag(Isolate* isolate) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); @@ -7697,7 +7924,7 @@ Local<Symbol> v8::Symbol::GetIsConcatSpreadable(Isolate* isolate) { Local<Private> v8::Private::New(Isolate* isolate, Local<String> name) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, Private, New); - ENTER_V8(i_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); i::Handle<i::Symbol> symbol = i_isolate->factory()->NewPrivateSymbol(); if (!name.IsEmpty()) symbol->set_name(*Utils::OpenHandle(*name)); Local<Symbol> result = Utils::ToLocal(symbol); @@ -7708,9 +7935,8 @@ Local<Private> v8::Private::New(Isolate* isolate, Local<String> name) { Local<Private> v8::Private::ForApi(Isolate* isolate, Local<String> name) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); i::Handle<i::String> i_name = Utils::OpenHandle(*name); - i::Handle<i::String> part = i_isolate->factory()->private_api_string(); - Local<Symbol> result = - Utils::ToLocal(SymbolFor(i_isolate, i_name, part, true)); + Local<Symbol> result = Utils::ToLocal(i_isolate->SymbolFor( + i::Heap::kApiPrivateSymbolTableRootIndex, i_name, true)); return v8::Local<Private>(reinterpret_cast<Private*>(*result)); } @@ -7721,7 +7947,7 @@ Local<Number> v8::Number::New(Isolate* isolate, double value) { // Introduce only canonical NaN value into the VM, to avoid signaling NaNs. value = std::numeric_limits<double>::quiet_NaN(); } - ENTER_V8(internal_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate); i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value); return Utils::NumberToLocal(result); } @@ -7733,7 +7959,7 @@ Local<Integer> v8::Integer::New(Isolate* isolate, int32_t value) { return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value), internal_isolate)); } - ENTER_V8(internal_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate); i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value); return Utils::IntegerToLocal(result); } @@ -7745,7 +7971,7 @@ Local<Integer> v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t value) { if (fits_into_int32_t) { return Integer::New(isolate, static_cast<int32_t>(value)); } - ENTER_V8(internal_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate); i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value); return Utils::IntegerToLocal(result); } @@ -7804,6 +8030,18 @@ v8::Local<v8::Context> Isolate::GetEnteredContext() { return Utils::ToLocal(i::Handle<i::Context>::cast(last)); } +v8::Local<v8::Context> Isolate::GetEnteredOrMicrotaskContext() { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); + i::Handle<i::Object> last; + if (isolate->handle_scope_implementer() + ->MicrotaskContextIsLastEnteredContext()) { + last = isolate->handle_scope_implementer()->MicrotaskContext(); + } else { + last = isolate->handle_scope_implementer()->LastEnteredContext(); + } + if (last.is_null()) return Local<Context>(); + return Utils::ToLocal(i::Handle<i::Context>::cast(last)); +} v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); @@ -7969,8 +8207,7 @@ Isolate* Isolate::New(const Isolate::CreateParams& params) { } isolate->set_api_external_references(params.external_references); - isolate->set_deserialize_internal_fields_callback( - params.deserialize_internal_fields_callback); + isolate->set_allow_atomics_wait(params.allow_atomics_wait); SetResourceConstraints(isolate, params.constraints); // TODO(jochen): Once we got rid of Isolate::Current(), we can remove this. Isolate::Scope isolate_scope(v8_isolate); @@ -8227,6 +8464,10 @@ void Isolate::RemoveCallCompletedCallback( reinterpret_cast<CallCompletedCallback>(callback)); } +void Isolate::SetPromiseHook(PromiseHook hook) { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); + isolate->SetPromiseHook(hook); +} void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) { if (callback == NULL) return; @@ -8376,8 +8617,14 @@ void Isolate::IsolateInBackgroundNotification() { void Isolate::MemoryPressureNotification(MemoryPressureLevel level) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); - isolate->heap()->MemoryPressureNotification(level, Locker::IsLocked(this)); + bool on_isolate_thread = + v8::Locker::IsActive() + ? isolate->thread_manager()->IsLockedByCurrentThread() + : i::ThreadId::Current().Equals(isolate->thread_id()); + isolate->heap()->MemoryPressureNotification(level, on_isolate_thread); isolate->allocator()->MemoryPressureNotification(level); + isolate->compiler_dispatcher()->MemoryPressureNotification(level, + on_isolate_thread); } void Isolate::SetRAILMode(RAILMode rail_mode) { @@ -8385,6 +8632,21 @@ void Isolate::SetRAILMode(RAILMode rail_mode) { return isolate->SetRAILMode(rail_mode); } +void Isolate::IncreaseHeapLimitForDebugging() { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); + isolate->heap()->IncreaseHeapLimitForDebugging(); +} + +void Isolate::RestoreOriginalHeapLimit() { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); + isolate->heap()->RestoreOriginalHeapLimit(); +} + +bool Isolate::IsHeapLimitIncreasedForDebugging() { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); + return isolate->heap()->IsHeapLimitIncreasedForDebugging(); +} + void Isolate::SetJitCodeEventHandler(JitCodeEventOptions options, JitCodeEventHandler event_handler) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); @@ -8400,7 +8662,6 @@ void Isolate::SetStackLimit(uintptr_t stack_limit) { isolate->stack_guard()->SetStackLimit(stack_limit); } - void Isolate::GetCodeRange(void** start, size_t* length_in_bytes) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); if (isolate->heap()->memory_allocator()->code_range()->valid()) { @@ -8430,24 +8691,40 @@ void Isolate::SetAllowCodeGenerationFromStringsCallback( isolate->set_allow_code_gen_callback(callback); } +void Isolate::SetAllowWasmCompileCallback(AllowWasmCompileCallback callback) { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); + isolate->set_allow_wasm_compile_callback(callback); +} + +void Isolate::SetAllowWasmInstantiateCallback( + AllowWasmInstantiateCallback callback) { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); + isolate->set_allow_wasm_instantiate_callback(callback); +} bool Isolate::IsDead() { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); return isolate->IsDead(); } - bool Isolate::AddMessageListener(MessageCallback that, Local<Value> data) { + return AddMessageListenerWithErrorLevel(that, kMessageError, data); +} + +bool Isolate::AddMessageListenerWithErrorLevel(MessageCallback that, + int message_levels, + Local<Value> data) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); i::Handle<i::TemplateList> list = isolate->factory()->message_listeners(); - i::Handle<i::FixedArray> listener = isolate->factory()->NewFixedArray(2); + i::Handle<i::FixedArray> listener = isolate->factory()->NewFixedArray(3); i::Handle<i::Foreign> foreign = isolate->factory()->NewForeign(FUNCTION_ADDR(that)); listener->set(0, *foreign); listener->set(1, data.IsEmpty() ? isolate->heap()->undefined_value() : *Utils::OpenHandle(*data)); + listener->set(2, i::Smi::FromInt(message_levels)); list = i::TemplateList::Add(isolate, list, listener); isolate->heap()->SetMessageListeners(*list); return true; @@ -8456,7 +8733,7 @@ bool Isolate::AddMessageListener(MessageCallback that, Local<Value> data) { void Isolate::RemoveMessageListeners(MessageCallback that) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); - ENTER_V8(isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); i::HandleScope scope(isolate); i::DisallowHeapAllocation no_gc; i::TemplateList* listeners = isolate->heap()->message_listeners(); @@ -8638,7 +8915,7 @@ String::Value::~Value() { Local<Value> Exception::NAME(v8::Local<v8::String> raw_message) { \ i::Isolate* isolate = i::Isolate::Current(); \ LOG_API(isolate, NAME, New); \ - ENTER_V8(isolate); \ + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); \ i::Object* error; \ { \ i::HandleScope scope(isolate); \ @@ -8695,15 +8972,18 @@ bool Debug::SetDebugEventListener(Isolate* isolate, EventCallback that, i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); ENTER_V8(i_isolate); i::HandleScope scope(i_isolate); - i::Handle<i::Object> foreign = i_isolate->factory()->undefined_value(); - if (that != NULL) { - foreign = i_isolate->factory()->NewForeign(FUNCTION_ADDR(that)); + if (that == nullptr) { + i_isolate->debug()->SetDebugDelegate(nullptr, false); + } else { + i::Handle<i::Object> i_data = i_isolate->factory()->undefined_value(); + if (!data.IsEmpty()) i_data = Utils::OpenHandle(*data); + i::NativeDebugDelegate* delegate = + new i::NativeDebugDelegate(i_isolate, that, i_data); + i_isolate->debug()->SetDebugDelegate(delegate, true); } - i_isolate->debug()->SetEventListener(foreign, Utils::OpenHandle(*data, true)); return true; } - void Debug::DebugBreak(Isolate* isolate) { reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->RequestDebugBreak(); } @@ -8720,24 +9000,11 @@ bool Debug::CheckDebugBreak(Isolate* isolate) { return internal_isolate->stack_guard()->CheckDebugBreak(); } - void Debug::SetMessageHandler(Isolate* isolate, - v8::Debug::MessageHandler handler) { - i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); - ENTER_V8(i_isolate); - i_isolate->debug()->SetMessageHandler(handler); -} - - -void Debug::SendCommand(Isolate* isolate, - const uint16_t* command, - int length, - ClientData* client_data) { - i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); - internal_isolate->debug()->EnqueueCommandMessage( - i::Vector<const uint16_t>(command, length), client_data); -} + v8::Debug::MessageHandler handler) {} +void Debug::SendCommand(Isolate* isolate, const uint16_t* command, int length, + ClientData* client_data) {} MaybeLocal<Value> Debug::Call(Local<Context> context, v8::Local<v8::Function> fun, @@ -8758,36 +9025,10 @@ MaybeLocal<Value> Debug::Call(Local<Context> context, } -MaybeLocal<Value> Debug::GetMirror(Local<Context> context, - v8::Local<v8::Value> obj) { - PREPARE_FOR_EXECUTION(context, Debug, GetMirror, Value); - i::Debug* isolate_debug = isolate->debug(); - has_pending_exception = !isolate_debug->Load(); - RETURN_ON_FAILED_EXECUTION(Value); - i::Handle<i::JSObject> debug(isolate_debug->debug_context()->global_object()); - auto name = isolate->factory()->NewStringFromStaticChars("MakeMirror"); - auto fun_obj = i::JSReceiver::GetProperty(debug, name).ToHandleChecked(); - auto v8_fun = Utils::CallableToLocal(i::Handle<i::JSFunction>::cast(fun_obj)); - const int kArgc = 1; - v8::Local<v8::Value> argv[kArgc] = {obj}; - Local<Value> result; - has_pending_exception = - !v8_fun->Call(context, Utils::ToLocal(debug), kArgc, argv) - .ToLocal(&result); - RETURN_ON_FAILED_EXECUTION(Value); - RETURN_ESCAPED(result); -} - - -void Debug::ProcessDebugMessages(Isolate* isolate) { - reinterpret_cast<i::Isolate*>(isolate)->debug()->ProcessDebugMessages(true); -} - +void Debug::ProcessDebugMessages(Isolate* isolate) {} Local<Context> Debug::GetDebugContext(Isolate* isolate) { - i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); - ENTER_V8(i_isolate); - return Utils::ToLocal(i_isolate->debug()->GetDebugContext()); + return debug::GetDebugContext(isolate); } @@ -8826,49 +9067,34 @@ MaybeLocal<Array> Debug::GetInternalProperties(Isolate* v8_isolate, return Utils::ToLocal(result); } -bool DebugInterface::SetDebugEventListener(Isolate* isolate, - DebugInterface::EventCallback that, - Local<Value> data) { +Local<Context> debug::GetDebugContext(Isolate* isolate) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); ENTER_V8(i_isolate); - i::HandleScope scope(i_isolate); - i::Handle<i::Object> foreign = i_isolate->factory()->undefined_value(); - if (that != NULL) { - foreign = i_isolate->factory()->NewForeign(FUNCTION_ADDR(that)); - } - i_isolate->debug()->SetEventListener(foreign, Utils::OpenHandle(*data, true)); - return true; -} - -Local<Context> DebugInterface::GetDebugContext(Isolate* isolate) { - return Debug::GetDebugContext(isolate); + return Utils::ToLocal(i_isolate->debug()->GetDebugContext()); } -MaybeLocal<Value> DebugInterface::Call(Local<Context> context, - v8::Local<v8::Function> fun, - v8::Local<v8::Value> data) { +MaybeLocal<Value> debug::Call(Local<Context> context, + v8::Local<v8::Function> fun, + v8::Local<v8::Value> data) { return Debug::Call(context, fun, data); } -void DebugInterface::SetLiveEditEnabled(Isolate* isolate, bool enable) { +void debug::SetLiveEditEnabled(Isolate* isolate, bool enable) { Debug::SetLiveEditEnabled(isolate, enable); } -void DebugInterface::DebugBreak(Isolate* isolate) { - Debug::DebugBreak(isolate); -} +void debug::DebugBreak(Isolate* isolate) { Debug::DebugBreak(isolate); } -void DebugInterface::CancelDebugBreak(Isolate* isolate) { +void debug::CancelDebugBreak(Isolate* isolate) { Debug::CancelDebugBreak(isolate); } -MaybeLocal<Array> DebugInterface::GetInternalProperties(Isolate* isolate, - Local<Value> value) { +MaybeLocal<Array> debug::GetInternalProperties(Isolate* isolate, + Local<Value> value) { return Debug::GetInternalProperties(isolate, value); } -void DebugInterface::ChangeBreakOnException(Isolate* isolate, - ExceptionBreakState type) { +void debug::ChangeBreakOnException(Isolate* isolate, ExceptionBreakState type) { i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); internal_isolate->debug()->ChangeBreakOnException( i::BreakException, type == BreakOnAnyException); @@ -8876,7 +9102,20 @@ void DebugInterface::ChangeBreakOnException(Isolate* isolate, type != NoBreakOnException); } -void DebugInterface::PrepareStep(Isolate* v8_isolate, StepAction action) { +void debug::SetBreakPointsActive(Isolate* v8_isolate, bool is_active) { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); + ENTER_V8(isolate); + isolate->debug()->set_break_points_active(is_active); +} + +void debug::SetOutOfMemoryCallback(Isolate* isolate, + OutOfMemoryCallback callback, void* data) { + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + ENTER_V8(i_isolate); + i_isolate->heap()->SetOutOfMemoryCallback(callback, data); +} + +void debug::PrepareStep(Isolate* v8_isolate, StepAction action) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8(isolate); CHECK(isolate->debug()->CheckExecutionState()); @@ -8886,38 +9125,45 @@ void DebugInterface::PrepareStep(Isolate* v8_isolate, StepAction action) { isolate->debug()->PrepareStep(static_cast<i::StepAction>(action)); } -void DebugInterface::ClearStepping(Isolate* v8_isolate) { +bool debug::HasNonBlackboxedFrameOnStack(Isolate* v8_isolate) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8(isolate); - // Clear all current stepping setup. - isolate->debug()->ClearStepping(); + i::HandleScope scope(isolate); + for (i::StackTraceFrameIterator it(isolate); !it.done(); it.Advance()) { + if (!it.is_javascript()) continue; + if (!isolate->debug()->IsFrameBlackboxed(it.javascript_frame())) { + return true; + } + } + return false; } -v8::Isolate* DebugInterface::Script::GetIsolate() const { +v8::Isolate* debug::Script::GetIsolate() const { return reinterpret_cast<v8::Isolate*>(Utils::OpenHandle(this)->GetIsolate()); } -ScriptOriginOptions DebugInterface::Script::OriginOptions() const { +ScriptOriginOptions debug::Script::OriginOptions() const { return Utils::OpenHandle(this)->origin_options(); } -bool DebugInterface::Script::WasCompiled() const { +bool debug::Script::WasCompiled() const { return Utils::OpenHandle(this)->compilation_state() == i::Script::COMPILATION_STATE_COMPILED; } -int DebugInterface::Script::Id() const { return Utils::OpenHandle(this)->id(); } +int debug::Script::Id() const { return Utils::OpenHandle(this)->id(); } -int DebugInterface::Script::LineOffset() const { +int debug::Script::LineOffset() const { return Utils::OpenHandle(this)->line_offset(); } -int DebugInterface::Script::ColumnOffset() const { +int debug::Script::ColumnOffset() const { return Utils::OpenHandle(this)->column_offset(); } -std::vector<int> DebugInterface::Script::LineEnds() const { +std::vector<int> debug::Script::LineEnds() const { i::Handle<i::Script> script = Utils::OpenHandle(this); + if (script->type() == i::Script::TYPE_WASM) return std::vector<int>(); i::Isolate* isolate = script->GetIsolate(); i::HandleScope scope(isolate); i::Script::InitLineEnds(script); @@ -8931,7 +9177,7 @@ std::vector<int> DebugInterface::Script::LineEnds() const { return result; } -MaybeLocal<String> DebugInterface::Script::Name() const { +MaybeLocal<String> debug::Script::Name() const { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); i::HandleScope handle_scope(isolate); i::Handle<i::Script> script = Utils::OpenHandle(this); @@ -8941,7 +9187,7 @@ MaybeLocal<String> DebugInterface::Script::Name() const { handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value))); } -MaybeLocal<String> DebugInterface::Script::SourceURL() const { +MaybeLocal<String> debug::Script::SourceURL() const { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); i::HandleScope handle_scope(isolate); i::Handle<i::Script> script = Utils::OpenHandle(this); @@ -8951,7 +9197,7 @@ MaybeLocal<String> DebugInterface::Script::SourceURL() const { handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value))); } -MaybeLocal<String> DebugInterface::Script::SourceMappingURL() const { +MaybeLocal<String> debug::Script::SourceMappingURL() const { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); i::HandleScope handle_scope(isolate); i::Handle<i::Script> script = Utils::OpenHandle(this); @@ -8961,17 +9207,15 @@ MaybeLocal<String> DebugInterface::Script::SourceMappingURL() const { handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value))); } -MaybeLocal<String> DebugInterface::Script::ContextData() const { +MaybeLocal<Value> debug::Script::ContextData() const { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); i::HandleScope handle_scope(isolate); i::Handle<i::Script> script = Utils::OpenHandle(this); i::Handle<i::Object> value(script->context_data(), isolate); - if (!value->IsString()) return MaybeLocal<String>(); - return Utils::ToLocal( - handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value))); + return Utils::ToLocal(handle_scope.CloseAndEscape(value)); } -MaybeLocal<String> DebugInterface::Script::Source() const { +MaybeLocal<String> debug::Script::Source() const { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); i::HandleScope handle_scope(isolate); i::Handle<i::Script> script = Utils::OpenHandle(this); @@ -8981,17 +9225,30 @@ MaybeLocal<String> DebugInterface::Script::Source() const { handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value))); } +bool debug::Script::IsWasm() const { + return Utils::OpenHandle(this)->type() == i::Script::TYPE_WASM; +} + +bool debug::Script::IsModule() const { + return Utils::OpenHandle(this)->origin_options().IsModule(); +} + namespace { int GetSmiValue(i::Handle<i::FixedArray> array, int index) { return i::Smi::cast(array->get(index))->value(); } } // namespace -bool DebugInterface::Script::GetPossibleBreakpoints( - const Location& start, const Location& end, - std::vector<Location>* locations) const { +bool debug::Script::GetPossibleBreakpoints( + const debug::Location& start, const debug::Location& end, + std::vector<debug::Location>* locations) const { CHECK(!start.IsEmpty()); i::Handle<i::Script> script = Utils::OpenHandle(this); + if (script->type() == i::Script::TYPE_WASM) { + i::Handle<i::WasmCompiledModule> compiled_module( + i::WasmCompiledModule::cast(script->wasm_compiled_module())); + return compiled_module->GetPossibleBreakpoints(start, end, locations); + } i::Script::InitLineEnds(script); CHECK(script->line_ends()->IsFixedArray()); @@ -9027,7 +9284,7 @@ bool DebugInterface::Script::GetPossibleBreakpoints( if (current_line_end_index > 0) { line_offset = GetSmiValue(line_ends, current_line_end_index - 1) + 1; } - locations->push_back(Location( + locations->push_back(debug::Location( current_line_end_index + script->line_offset(), offset - line_offset + (current_line_end_index == 0 ? script->column_offset() : 0))); @@ -9035,8 +9292,12 @@ bool DebugInterface::Script::GetPossibleBreakpoints( return true; } -int DebugInterface::Script::GetSourcePosition(const Location& location) const { +int debug::Script::GetSourcePosition(const debug::Location& location) const { i::Handle<i::Script> script = Utils::OpenHandle(this); + if (script->type() == i::Script::TYPE_WASM) { + // TODO(clemensh): Return the proper thing for wasm. + return 0; + } int line = std::max(location.GetLineNumber() - script->line_offset(), 0); int column = location.GetColumnNumber(); @@ -9057,49 +9318,84 @@ int DebugInterface::Script::GetSourcePosition(const Location& location) const { return std::min(prev_line_offset + column + 1, line_offset); } -MaybeLocal<DebugInterface::Script> DebugInterface::Script::Wrap( - v8::Isolate* v8_isolate, v8::Local<v8::Object> script) { - i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); - ENTER_V8(isolate); - i::HandleScope handle_scope(isolate); - i::Handle<i::JSReceiver> script_receiver(Utils::OpenHandle(*script)); - if (!script_receiver->IsJSValue()) return MaybeLocal<Script>(); - i::Handle<i::Object> script_value( - i::Handle<i::JSValue>::cast(script_receiver)->value(), isolate); - if (!script_value->IsScript()) { - return MaybeLocal<Script>(); - } - i::Handle<i::Script> script_obj = i::Handle<i::Script>::cast(script_value); - if (script_obj->type() != i::Script::TYPE_NORMAL) return MaybeLocal<Script>(); - return ToApiHandle<DebugInterface::Script>( - handle_scope.CloseAndEscape(script_obj)); +debug::WasmScript* debug::WasmScript::Cast(debug::Script* script) { + CHECK(script->IsWasm()); + return static_cast<WasmScript*>(script); +} + +int debug::WasmScript::NumFunctions() const { + i::DisallowHeapAllocation no_gc; + i::Handle<i::Script> script = Utils::OpenHandle(this); + DCHECK_EQ(i::Script::TYPE_WASM, script->type()); + i::WasmCompiledModule* compiled_module = + i::WasmCompiledModule::cast(script->wasm_compiled_module()); + DCHECK_GE(i::kMaxInt, compiled_module->module()->functions.size()); + return static_cast<int>(compiled_module->module()->functions.size()); +} + +int debug::WasmScript::NumImportedFunctions() const { + i::DisallowHeapAllocation no_gc; + i::Handle<i::Script> script = Utils::OpenHandle(this); + DCHECK_EQ(i::Script::TYPE_WASM, script->type()); + i::WasmCompiledModule* compiled_module = + i::WasmCompiledModule::cast(script->wasm_compiled_module()); + DCHECK_GE(i::kMaxInt, compiled_module->module()->num_imported_functions); + return static_cast<int>(compiled_module->module()->num_imported_functions); +} + +std::pair<int, int> debug::WasmScript::GetFunctionRange( + int function_index) const { + i::DisallowHeapAllocation no_gc; + i::Handle<i::Script> script = Utils::OpenHandle(this); + DCHECK_EQ(i::Script::TYPE_WASM, script->type()); + i::WasmCompiledModule* compiled_module = + i::WasmCompiledModule::cast(script->wasm_compiled_module()); + DCHECK_LE(0, function_index); + DCHECK_GT(compiled_module->module()->functions.size(), function_index); + i::wasm::WasmFunction& func = + compiled_module->module()->functions[function_index]; + DCHECK_GE(i::kMaxInt, func.code_start_offset); + DCHECK_GE(i::kMaxInt, func.code_end_offset); + return std::make_pair(static_cast<int>(func.code_start_offset), + static_cast<int>(func.code_end_offset)); +} + +debug::WasmDisassembly debug::WasmScript::DisassembleFunction( + int function_index) const { + i::DisallowHeapAllocation no_gc; + i::Handle<i::Script> script = Utils::OpenHandle(this); + DCHECK_EQ(i::Script::TYPE_WASM, script->type()); + i::WasmCompiledModule* compiled_module = + i::WasmCompiledModule::cast(script->wasm_compiled_module()); + return compiled_module->DisassembleFunction(function_index); } -DebugInterface::Location::Location(int lineNumber, int columnNumber) - : lineNumber_(lineNumber), columnNumber_(columnNumber) { - CHECK(lineNumber >= 0); - CHECK(columnNumber >= 0); +debug::Location::Location(int line_number, int column_number) + : line_number_(line_number), column_number_(column_number) { + CHECK(line_number >= 0); + CHECK(column_number >= 0); } -DebugInterface::Location::Location() : lineNumber_(-1), columnNumber_(-1) {} +debug::Location::Location() + : line_number_(v8::Function::kLineOffsetNotFound), + column_number_(v8::Function::kLineOffsetNotFound) {} -int DebugInterface::Location::GetLineNumber() const { - CHECK(lineNumber_ >= 0); - return lineNumber_; +int debug::Location::GetLineNumber() const { + CHECK(line_number_ >= 0); + return line_number_; } -int DebugInterface::Location::GetColumnNumber() const { - CHECK(columnNumber_ >= 0); - return columnNumber_; +int debug::Location::GetColumnNumber() const { + CHECK(column_number_ >= 0); + return column_number_; } -bool DebugInterface::Location::IsEmpty() const { - return lineNumber_ == -1 && columnNumber_ == -1; +bool debug::Location::IsEmpty() const { + return line_number_ == -1 && column_number_ == -1; } -void DebugInterface::GetLoadedScripts( - v8::Isolate* v8_isolate, - PersistentValueVector<DebugInterface::Script>& scripts) { +void debug::GetLoadedScripts(v8::Isolate* v8_isolate, + PersistentValueVector<debug::Script>& scripts) { i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); ENTER_V8(isolate); // TODO(kozyatinskiy): remove this GC once tests are dealt with. @@ -9120,6 +9416,127 @@ void DebugInterface::GetLoadedScripts( } } +MaybeLocal<UnboundScript> debug::CompileInspectorScript(Isolate* v8_isolate, + Local<String> source) { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); + PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, UnboundScript); + i::ScriptData* script_data = NULL; + i::Handle<i::String> str = Utils::OpenHandle(*source); + i::Handle<i::SharedFunctionInfo> result; + { + ScriptOriginOptions origin_options; + result = i::Compiler::GetSharedFunctionInfoForScript( + str, i::Handle<i::Object>(), 0, 0, origin_options, + i::Handle<i::Object>(), isolate->native_context(), NULL, &script_data, + ScriptCompiler::kNoCompileOptions, i::INSPECTOR_CODE); + has_pending_exception = result.is_null(); + RETURN_ON_FAILED_EXECUTION(UnboundScript); + } + RETURN_ESCAPED(ToApiHandle<UnboundScript>(result)); +} + +void debug::SetDebugDelegate(Isolate* v8_isolate, + debug::DebugDelegate* delegate) { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); + ENTER_V8(isolate); + isolate->debug()->SetDebugDelegate(delegate, false); +} + +void debug::ResetBlackboxedStateCache(Isolate* v8_isolate, + v8::Local<debug::Script> script) { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); + ENTER_V8(isolate); + i::DisallowHeapAllocation no_gc; + i::SharedFunctionInfo::ScriptIterator iter(Utils::OpenHandle(*script)); + while (i::SharedFunctionInfo* info = iter.Next()) { + info->set_computed_debug_is_blackboxed(false); + } +} + +int debug::EstimatedValueSize(Isolate* v8_isolate, v8::Local<v8::Value> value) { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); + ENTER_V8(isolate); + i::Handle<i::Object> object = Utils::OpenHandle(*value); + if (object->IsSmi()) return i::kPointerSize; + CHECK(object->IsHeapObject()); + return i::Handle<i::HeapObject>::cast(object)->Size(); +} + +v8::MaybeLocal<v8::Array> debug::EntriesPreview(Isolate* v8_isolate, + v8::Local<v8::Value> value, + bool* is_key_value) { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); + ENTER_V8(isolate); + if (value->IsMap()) { + *is_key_value = true; + return value.As<Map>()->AsArray(); + } + if (value->IsSet()) { + *is_key_value = false; + return value.As<Set>()->AsArray(); + } + + i::Handle<i::Object> object = Utils::OpenHandle(*value); + if (object->IsJSWeakCollection()) { + *is_key_value = object->IsJSWeakMap(); + return Utils::ToLocal(i::JSWeakCollection::GetEntries( + i::Handle<i::JSWeakCollection>::cast(object), 0)); + } + if (object->IsJSMapIterator()) { + i::Handle<i::JSMapIterator> iterator = + i::Handle<i::JSMapIterator>::cast(object); + int iterator_kind = i::Smi::cast(iterator->kind())->value(); + *is_key_value = iterator_kind == i::JSMapIterator::kKindEntries; + if (!iterator->HasMore()) return v8::Array::New(v8_isolate); + return Utils::ToLocal(MapAsArray(isolate, iterator->table(), + i::Smi::cast(iterator->index())->value(), + iterator_kind)); + } + if (object->IsJSSetIterator()) { + i::Handle<i::JSSetIterator> it = i::Handle<i::JSSetIterator>::cast(object); + *is_key_value = false; + if (!it->HasMore()) return v8::Array::New(v8_isolate); + return Utils::ToLocal( + SetAsArray(isolate, it->table(), i::Smi::cast(it->index())->value())); + } + return v8::MaybeLocal<v8::Array>(); +} + +MaybeLocal<debug::Script> debug::GeneratorObject::Script() { + i::Handle<i::JSGeneratorObject> obj = Utils::OpenHandle(this); + i::Object* maybe_script = obj->function()->shared()->script(); + if (!maybe_script->IsScript()) return MaybeLocal<debug::Script>(); + i::Handle<i::Script> script(i::Script::cast(maybe_script), obj->GetIsolate()); + return ToApiHandle<debug::Script>(script); +} + +Local<Function> debug::GeneratorObject::Function() { + i::Handle<i::JSGeneratorObject> obj = Utils::OpenHandle(this); + return Utils::ToLocal(handle(obj->function())); +} + +debug::Location debug::GeneratorObject::SuspendedLocation() { + i::Handle<i::JSGeneratorObject> obj = Utils::OpenHandle(this); + CHECK(obj->is_suspended()); + i::Object* maybe_script = obj->function()->shared()->script(); + if (!maybe_script->IsScript()) return debug::Location(); + i::Handle<i::Script> script(i::Script::cast(maybe_script), obj->GetIsolate()); + i::Script::PositionInfo info; + i::Script::GetPositionInfo(script, obj->source_position(), &info, + i::Script::WITH_OFFSET); + return debug::Location(info.line, info.column); +} + +bool debug::GeneratorObject::IsSuspended() { + return Utils::OpenHandle(this)->is_suspended(); +} + +v8::Local<debug::GeneratorObject> debug::GeneratorObject::Cast( + v8::Local<v8::Value> value) { + CHECK(value->IsGeneratorObject()); + return ToApiHandle<debug::GeneratorObject>(Utils::OpenHandle(*value)); +} + Local<String> CpuProfileNode::GetFunctionName() const { const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this); i::Isolate* isolate = node->isolate(); @@ -9137,6 +9554,56 @@ Local<String> CpuProfileNode::GetFunctionName() const { } } +debug::Coverage::FunctionData::FunctionData(i::CoverageFunction* function, + Local<debug::Script> script) + : function_(function) { + i::Handle<i::Script> i_script = v8::Utils::OpenHandle(*script); + i::Script::PositionInfo start; + i::Script::PositionInfo end; + i::Script::GetPositionInfo(i_script, function->start, &start, + i::Script::WITH_OFFSET); + i::Script::GetPositionInfo(i_script, function->end, &end, + i::Script::WITH_OFFSET); + start_ = Location(start.line, start.column); + end_ = Location(end.line, end.column); +} + +uint32_t debug::Coverage::FunctionData::Count() { return function_->count; } + +MaybeLocal<String> debug::Coverage::FunctionData::Name() { + return ToApiHandle<String>(function_->name); +} + +Local<debug::Script> debug::Coverage::ScriptData::GetScript() { + return ToApiHandle<debug::Script>(script_->script); +} + +size_t debug::Coverage::ScriptData::FunctionCount() { + return script_->functions.size(); +} + +debug::Coverage::FunctionData debug::Coverage::ScriptData::GetFunctionData( + size_t i) { + return FunctionData(&script_->functions.at(i), GetScript()); +} + +debug::Coverage::~Coverage() { delete coverage_; } + +size_t debug::Coverage::ScriptCount() { return coverage_->size(); } + +debug::Coverage::ScriptData debug::Coverage::GetScriptData(size_t i) { + return ScriptData(&coverage_->at(i)); +} + +debug::Coverage debug::Coverage::Collect(Isolate* isolate, bool reset_count) { + return Coverage(i::Coverage::Collect(reinterpret_cast<i::Isolate*>(isolate), + reset_count)); +} + +void debug::Coverage::TogglePrecise(Isolate* isolate, bool enable) { + i::Coverage::TogglePrecise(reinterpret_cast<i::Isolate*>(isolate), enable); +} + const char* CpuProfileNode::GetFunctionNameStr() const { const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this); return node->entry()->name(); @@ -9392,13 +9859,12 @@ size_t HeapGraphNode::GetShallowSize() const { int HeapGraphNode::GetChildrenCount() const { - return ToInternal(this)->children().length(); + return ToInternal(this)->children_count(); } const HeapGraphEdge* HeapGraphNode::GetChild(int index) const { - return reinterpret_cast<const HeapGraphEdge*>( - ToInternal(this)->children()[index]); + return reinterpret_cast<const HeapGraphEdge*>(ToInternal(this)->child(index)); } @@ -9548,6 +10014,11 @@ void HeapProfiler::SetWrapperClassInfoProvider(uint16_t class_id, callback); } +void HeapProfiler::SetGetRetainerInfosCallback( + GetRetainerInfosCallback callback) { + reinterpret_cast<i::HeapProfiler*>(this)->SetGetRetainerInfosCallback( + callback); +} size_t HeapProfiler::GetProfilerMemorySize() { return reinterpret_cast<i::HeapProfiler*>(this)-> |