Revert "inspector: move injected script source to native"
This reverts commit 7e079c660b
.
Reason for revert: native implementation should be ready for navigation.
Original change's description:
> inspector: move injected script source to native
>
> - introduced ValueMirror interface, this interface contains methods to generate
> different protocol entities,
> - introduced DebugPropertyIterator, this iterator iterates through object properties
> in the following order: exotic indices, enumerable strings, all other properties,
> - removed all injected script infra, e.g. closure compiler,
>
> R=dgozman@chromium.org
> TBR=yangguo@chromium.org
>
> Bug: chromium:595206
> Change-Id: Idcfc04489ee52e015ad1d1d191c3474cc65e63f2
> Reviewed-on: https://chromium-review.googlesource.com/c/1308353
> Reviewed-by: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
> Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#57150}
TBR=dgozman@chromium.org,yangguo@chromium.org,kozyatinskiy@chromium.org
Change-Id: I8c5c61f4cfe5a66cd33eadd02ab4acec539cc3bb
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:595206
Reviewed-on: https://chromium-review.googlesource.com/c/1310055
Reviewed-by: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57176}
This commit is contained in:
parent
0405d6ef14
commit
fc5c8d7f78
2
BUILD.gn
2
BUILD.gn
@ -1937,8 +1937,6 @@ v8_source_set("v8_base") {
|
|||||||
"src/debug/debug-frames.cc",
|
"src/debug/debug-frames.cc",
|
||||||
"src/debug/debug-frames.h",
|
"src/debug/debug-frames.h",
|
||||||
"src/debug/debug-interface.h",
|
"src/debug/debug-interface.h",
|
||||||
"src/debug/debug-property-iterator.cc",
|
|
||||||
"src/debug/debug-property-iterator.h",
|
|
||||||
"src/debug/debug-scope-iterator.cc",
|
"src/debug/debug-scope-iterator.cc",
|
||||||
"src/debug/debug-scope-iterator.h",
|
"src/debug/debug-scope-iterator.h",
|
||||||
"src/debug/debug-scopes.cc",
|
"src/debug/debug-scopes.cc",
|
||||||
|
11
DEPS
11
DEPS
@ -245,6 +245,17 @@ hooks = [
|
|||||||
'-s', 'v8/test/wasm-spec-tests/tests.tar.gz.sha1',
|
'-s', 'v8/test/wasm-spec-tests/tests.tar.gz.sha1',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'name': 'closure_compiler',
|
||||||
|
'pattern': '.',
|
||||||
|
'action': [ 'download_from_google_storage',
|
||||||
|
'--no_resume',
|
||||||
|
'--no_auth',
|
||||||
|
'-u',
|
||||||
|
'--bucket', 'chromium-v8-closure-compiler',
|
||||||
|
'-s', 'v8/src/inspector/build/closure-compiler.tar.gz.sha1',
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'name': 'sysroot_arm',
|
'name': 'sysroot_arm',
|
||||||
'pattern': '.',
|
'pattern': '.',
|
||||||
|
56
src/api.cc
56
src/api.cc
@ -9548,8 +9548,20 @@ Local<Function> debug::GetBuiltin(Isolate* v8_isolate, Builtin builtin) {
|
|||||||
i::HandleScope handle_scope(isolate);
|
i::HandleScope handle_scope(isolate);
|
||||||
i::Builtins::Name builtin_id;
|
i::Builtins::Name builtin_id;
|
||||||
switch (builtin) {
|
switch (builtin) {
|
||||||
case kStringToLowerCase:
|
case kObjectKeys:
|
||||||
builtin_id = i::Builtins::kStringPrototypeToLocaleLowerCase;
|
builtin_id = i::Builtins::kObjectKeys;
|
||||||
|
break;
|
||||||
|
case kObjectGetPrototypeOf:
|
||||||
|
builtin_id = i::Builtins::kObjectGetPrototypeOf;
|
||||||
|
break;
|
||||||
|
case kObjectGetOwnPropertyDescriptor:
|
||||||
|
builtin_id = i::Builtins::kObjectGetOwnPropertyDescriptor;
|
||||||
|
break;
|
||||||
|
case kObjectGetOwnPropertyNames:
|
||||||
|
builtin_id = i::Builtins::kObjectGetOwnPropertyNames;
|
||||||
|
break;
|
||||||
|
case kObjectGetOwnPropertySymbols:
|
||||||
|
builtin_id = i::Builtins::kObjectGetOwnPropertySymbols;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -9557,11 +9569,10 @@ Local<Function> debug::GetBuiltin(Isolate* v8_isolate, Builtin builtin) {
|
|||||||
|
|
||||||
i::Handle<i::String> name = isolate->factory()->empty_string();
|
i::Handle<i::String> name = isolate->factory()->empty_string();
|
||||||
i::NewFunctionArgs args = i::NewFunctionArgs::ForBuiltinWithoutPrototype(
|
i::NewFunctionArgs args = i::NewFunctionArgs::ForBuiltinWithoutPrototype(
|
||||||
name, builtin_id, i::LanguageMode::kStrict);
|
name, builtin_id, i::LanguageMode::kSloppy);
|
||||||
i::Handle<i::JSFunction> fun = isolate->factory()->NewFunction(args);
|
i::Handle<i::JSFunction> fun = isolate->factory()->NewFunction(args);
|
||||||
|
|
||||||
fun->shared()->set_internal_formal_parameter_count(0);
|
fun->shared()->DontAdaptArguments();
|
||||||
fun->shared()->set_length(0);
|
|
||||||
return Utils::ToLocal(handle_scope.CloseAndEscape(fun));
|
return Utils::ToLocal(handle_scope.CloseAndEscape(fun));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9686,6 +9697,41 @@ void debug::SetReturnValue(v8::Isolate* v8_isolate,
|
|||||||
isolate->debug()->set_return_value(*Utils::OpenHandle(*value));
|
isolate->debug()->set_return_value(*Utils::OpenHandle(*value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int debug::GetNativeAccessorDescriptor(v8::Local<v8::Context> context,
|
||||||
|
v8::Local<v8::Object> v8_object,
|
||||||
|
v8::Local<v8::Name> v8_name) {
|
||||||
|
i::Handle<i::JSReceiver> object = Utils::OpenHandle(*v8_object);
|
||||||
|
i::Handle<i::Name> name = Utils::OpenHandle(*v8_name);
|
||||||
|
uint32_t index;
|
||||||
|
if (name->AsArrayIndex(&index)) {
|
||||||
|
return static_cast<int>(debug::NativeAccessorType::None);
|
||||||
|
}
|
||||||
|
i::LookupIterator it = i::LookupIterator(object->GetIsolate(), object, name,
|
||||||
|
i::LookupIterator::OWN);
|
||||||
|
if (!it.IsFound()) return static_cast<int>(debug::NativeAccessorType::None);
|
||||||
|
if (it.state() != i::LookupIterator::ACCESSOR) {
|
||||||
|
return static_cast<int>(debug::NativeAccessorType::None);
|
||||||
|
}
|
||||||
|
i::Handle<i::Object> structure = it.GetAccessors();
|
||||||
|
if (!structure->IsAccessorInfo()) {
|
||||||
|
return static_cast<int>(debug::NativeAccessorType::None);
|
||||||
|
}
|
||||||
|
auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
|
||||||
|
int result = 0;
|
||||||
|
#define IS_BUILTIN_ACESSOR(_, name, ...) \
|
||||||
|
if (*structure == *isolate->factory()->name##_accessor()) \
|
||||||
|
result |= static_cast<int>(debug::NativeAccessorType::IsBuiltin);
|
||||||
|
ACCESSOR_INFO_LIST_GENERATOR(IS_BUILTIN_ACESSOR, /* not used */)
|
||||||
|
#undef IS_BUILTIN_ACESSOR
|
||||||
|
i::Handle<i::AccessorInfo> accessor_info =
|
||||||
|
i::Handle<i::AccessorInfo>::cast(structure);
|
||||||
|
if (accessor_info->getter())
|
||||||
|
result |= static_cast<int>(debug::NativeAccessorType::HasGetter);
|
||||||
|
if (accessor_info->setter())
|
||||||
|
result |= static_cast<int>(debug::NativeAccessorType::HasSetter);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int64_t debug::GetNextRandomInt64(v8::Isolate* v8_isolate) {
|
int64_t debug::GetNextRandomInt64(v8::Isolate* v8_isolate) {
|
||||||
return reinterpret_cast<i::Isolate*>(v8_isolate)
|
return reinterpret_cast<i::Isolate*>(v8_isolate)
|
||||||
->random_number_generator()
|
->random_number_generator()
|
||||||
|
@ -193,7 +193,13 @@ void ResetBlackboxedStateCache(Isolate* isolate,
|
|||||||
|
|
||||||
int EstimatedValueSize(Isolate* isolate, v8::Local<v8::Value> value);
|
int EstimatedValueSize(Isolate* isolate, v8::Local<v8::Value> value);
|
||||||
|
|
||||||
enum Builtin { kStringToLowerCase };
|
enum Builtin {
|
||||||
|
kObjectKeys,
|
||||||
|
kObjectGetPrototypeOf,
|
||||||
|
kObjectGetOwnPropertyDescriptor,
|
||||||
|
kObjectGetOwnPropertyNames,
|
||||||
|
kObjectGetOwnPropertySymbols,
|
||||||
|
};
|
||||||
|
|
||||||
Local<Function> GetBuiltin(Isolate* isolate, Builtin builtin);
|
Local<Function> GetBuiltin(Isolate* isolate, Builtin builtin);
|
||||||
|
|
||||||
@ -468,9 +474,14 @@ void SetReturnValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
|
|||||||
enum class NativeAccessorType {
|
enum class NativeAccessorType {
|
||||||
None = 0,
|
None = 0,
|
||||||
HasGetter = 1 << 0,
|
HasGetter = 1 << 0,
|
||||||
HasSetter = 1 << 1
|
HasSetter = 1 << 1,
|
||||||
|
IsBuiltin = 1 << 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int GetNativeAccessorDescriptor(v8::Local<v8::Context> context,
|
||||||
|
v8::Local<v8::Object> object,
|
||||||
|
v8::Local<v8::Name> name);
|
||||||
|
|
||||||
int64_t GetNextRandomInt64(v8::Isolate* isolate);
|
int64_t GetNextRandomInt64(v8::Isolate* isolate);
|
||||||
|
|
||||||
v8::MaybeLocal<v8::Value> EvaluateGlobal(v8::Isolate* isolate,
|
v8::MaybeLocal<v8::Value> EvaluateGlobal(v8::Isolate* isolate,
|
||||||
@ -507,39 +518,6 @@ class WeakMap : public v8::Object {
|
|||||||
private:
|
private:
|
||||||
WeakMap();
|
WeakMap();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PropertyDescriptor {
|
|
||||||
bool enumerable : 1;
|
|
||||||
bool has_enumerable : 1;
|
|
||||||
bool configurable : 1;
|
|
||||||
bool has_configurable : 1;
|
|
||||||
bool writable : 1;
|
|
||||||
bool has_writable : 1;
|
|
||||||
v8::Local<v8::Value> value;
|
|
||||||
v8::Local<v8::Value> get;
|
|
||||||
v8::Local<v8::Value> set;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PropertyIterator {
|
|
||||||
public:
|
|
||||||
static std::unique_ptr<PropertyIterator> Create(v8::Local<v8::Object> object);
|
|
||||||
|
|
||||||
virtual ~PropertyIterator() = default;
|
|
||||||
|
|
||||||
virtual bool Done() const = 0;
|
|
||||||
virtual void Advance() = 0;
|
|
||||||
|
|
||||||
virtual v8::Local<v8::Name> name() const = 0;
|
|
||||||
|
|
||||||
virtual bool is_native_accessor() = 0;
|
|
||||||
virtual bool has_native_getter() = 0;
|
|
||||||
virtual bool has_native_setter() = 0;
|
|
||||||
virtual Maybe<PropertyAttribute> attributes() = 0;
|
|
||||||
virtual Maybe<PropertyDescriptor> descriptor() = 0;
|
|
||||||
|
|
||||||
virtual bool is_own() = 0;
|
|
||||||
virtual bool is_array_index() = 0;
|
|
||||||
};
|
|
||||||
} // namespace debug
|
} // namespace debug
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
|
||||||
|
@ -1,213 +0,0 @@
|
|||||||
// Copyright 2018 the V8 project authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#include "src/debug/debug-property-iterator.h"
|
|
||||||
|
|
||||||
#include "src/api-inl.h"
|
|
||||||
#include "src/base/flags.h"
|
|
||||||
#include "src/keys.h"
|
|
||||||
#include "src/objects/js-array-buffer-inl.h"
|
|
||||||
#include "src/property-descriptor.h"
|
|
||||||
#include "src/property-details.h"
|
|
||||||
|
|
||||||
namespace v8 {
|
|
||||||
|
|
||||||
std::unique_ptr<debug::PropertyIterator> debug::PropertyIterator::Create(
|
|
||||||
v8::Local<v8::Object> v8_object) {
|
|
||||||
internal::Isolate* isolate =
|
|
||||||
reinterpret_cast<internal::Isolate*>(v8_object->GetIsolate());
|
|
||||||
return std::unique_ptr<debug::PropertyIterator>(
|
|
||||||
new internal::DebugPropertyIterator(isolate,
|
|
||||||
Utils::OpenHandle(*v8_object)));
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
DebugPropertyIterator::DebugPropertyIterator(Isolate* isolate,
|
|
||||||
Handle<JSReceiver> receiver)
|
|
||||||
: isolate_(isolate),
|
|
||||||
prototype_iterator_(isolate, receiver, kStartAtReceiver,
|
|
||||||
PrototypeIterator::END_AT_NULL) {
|
|
||||||
if (receiver->IsJSProxy()) {
|
|
||||||
is_own_ = false;
|
|
||||||
prototype_iterator_.AdvanceIgnoringProxies();
|
|
||||||
}
|
|
||||||
if (prototype_iterator_.IsAtEnd()) return;
|
|
||||||
FillKeysForCurrentPrototypeAndStage();
|
|
||||||
if (should_move_to_next_stage()) Advance();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DebugPropertyIterator::Done() const {
|
|
||||||
return prototype_iterator_.IsAtEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugPropertyIterator::Advance() {
|
|
||||||
++current_key_index_;
|
|
||||||
calculated_native_accessor_flags_ = false;
|
|
||||||
while (should_move_to_next_stage()) {
|
|
||||||
switch (stage_) {
|
|
||||||
case Stage::kExoticIndices:
|
|
||||||
stage_ = Stage::kEnumerableStrings;
|
|
||||||
break;
|
|
||||||
case Stage::kEnumerableStrings:
|
|
||||||
stage_ = Stage::kAllProperties;
|
|
||||||
break;
|
|
||||||
case Stage::kAllProperties:
|
|
||||||
stage_ = kExoticIndices;
|
|
||||||
is_own_ = false;
|
|
||||||
prototype_iterator_.AdvanceIgnoringProxies();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
FillKeysForCurrentPrototypeAndStage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DebugPropertyIterator::is_native_accessor() {
|
|
||||||
if (stage_ == kExoticIndices) return false;
|
|
||||||
CalculateNativeAccessorFlags();
|
|
||||||
return native_accessor_flags_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DebugPropertyIterator::has_native_getter() {
|
|
||||||
if (stage_ == kExoticIndices) return false;
|
|
||||||
CalculateNativeAccessorFlags();
|
|
||||||
return native_accessor_flags_ &
|
|
||||||
static_cast<int>(debug::NativeAccessorType::HasGetter);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DebugPropertyIterator::has_native_setter() {
|
|
||||||
if (stage_ == kExoticIndices) return false;
|
|
||||||
CalculateNativeAccessorFlags();
|
|
||||||
return native_accessor_flags_ &
|
|
||||||
static_cast<int>(debug::NativeAccessorType::HasSetter);
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle<Name> DebugPropertyIterator::raw_name() const {
|
|
||||||
DCHECK(!Done());
|
|
||||||
if (stage_ == kExoticIndices) {
|
|
||||||
return isolate_->factory()->Uint32ToString(current_key_index_);
|
|
||||||
} else {
|
|
||||||
return Handle<Name>::cast(
|
|
||||||
FixedArray::get(*keys_, current_key_index_, isolate_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
v8::Local<v8::Name> DebugPropertyIterator::name() const {
|
|
||||||
return Utils::ToLocal(raw_name());
|
|
||||||
}
|
|
||||||
|
|
||||||
v8::Maybe<v8::PropertyAttribute> DebugPropertyIterator::attributes() {
|
|
||||||
Handle<JSReceiver> receiver =
|
|
||||||
PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
|
|
||||||
auto result = JSReceiver::GetPropertyAttributes(receiver, raw_name());
|
|
||||||
if (result.IsNothing()) return Nothing<v8::PropertyAttribute>();
|
|
||||||
DCHECK(result.FromJust() != ABSENT);
|
|
||||||
return Just(static_cast<v8::PropertyAttribute>(result.FromJust()));
|
|
||||||
}
|
|
||||||
|
|
||||||
v8::Maybe<v8::debug::PropertyDescriptor> DebugPropertyIterator::descriptor() {
|
|
||||||
Handle<JSReceiver> receiver =
|
|
||||||
PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
|
|
||||||
|
|
||||||
PropertyDescriptor descriptor;
|
|
||||||
Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
|
|
||||||
isolate_, receiver, raw_name(), &descriptor);
|
|
||||||
if (did_get_descriptor.IsNothing()) {
|
|
||||||
return Nothing<v8::debug::PropertyDescriptor>();
|
|
||||||
}
|
|
||||||
DCHECK(did_get_descriptor.FromJust());
|
|
||||||
return Just(v8::debug::PropertyDescriptor{
|
|
||||||
descriptor.enumerable(), descriptor.has_enumerable(),
|
|
||||||
descriptor.configurable(), descriptor.has_configurable(),
|
|
||||||
descriptor.writable(), descriptor.has_writable(),
|
|
||||||
descriptor.has_value() ? Utils::ToLocal(descriptor.value())
|
|
||||||
: v8::Local<v8::Value>(),
|
|
||||||
descriptor.has_get() ? Utils::ToLocal(descriptor.get())
|
|
||||||
: v8::Local<v8::Value>(),
|
|
||||||
descriptor.has_set() ? Utils::ToLocal(descriptor.set())
|
|
||||||
: v8::Local<v8::Value>(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DebugPropertyIterator::is_own() { return is_own_; }
|
|
||||||
|
|
||||||
bool DebugPropertyIterator::is_array_index() {
|
|
||||||
if (stage_ == kExoticIndices) return true;
|
|
||||||
uint32_t index = 0;
|
|
||||||
return raw_name()->AsArrayIndex(&index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugPropertyIterator::FillKeysForCurrentPrototypeAndStage() {
|
|
||||||
current_key_index_ = 0;
|
|
||||||
exotic_length_ = 0;
|
|
||||||
keys_ = Handle<FixedArray>::null();
|
|
||||||
if (prototype_iterator_.IsAtEnd()) return;
|
|
||||||
Handle<JSReceiver> receiver =
|
|
||||||
PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
|
|
||||||
bool has_exotic_indices = receiver->IsJSTypedArray();
|
|
||||||
if (stage_ == kExoticIndices) {
|
|
||||||
if (!has_exotic_indices) return;
|
|
||||||
exotic_length_ = static_cast<uint32_t>(
|
|
||||||
Handle<JSTypedArray>::cast(receiver)->length_value());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bool skip_indices = has_exotic_indices;
|
|
||||||
PropertyFilter filter =
|
|
||||||
stage_ == kEnumerableStrings ? ENUMERABLE_STRINGS : ALL_PROPERTIES;
|
|
||||||
if (!KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, filter,
|
|
||||||
GetKeysConversion::kConvertToString, false,
|
|
||||||
skip_indices)
|
|
||||||
.ToHandle(&keys_)) {
|
|
||||||
keys_ = Handle<FixedArray>::null();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DebugPropertyIterator::should_move_to_next_stage() const {
|
|
||||||
if (prototype_iterator_.IsAtEnd()) return false;
|
|
||||||
if (stage_ == kExoticIndices) return current_key_index_ >= exotic_length_;
|
|
||||||
return keys_.is_null() ||
|
|
||||||
current_key_index_ >= static_cast<uint32_t>(keys_->length());
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
base::Flags<debug::NativeAccessorType, int> GetNativeAccessorDescriptorInternal(
|
|
||||||
Handle<JSReceiver> object, Handle<Name> name) {
|
|
||||||
uint32_t index;
|
|
||||||
if (name->AsArrayIndex(&index)) return debug::NativeAccessorType::None;
|
|
||||||
LookupIterator it =
|
|
||||||
LookupIterator(object->GetIsolate(), object, name, LookupIterator::OWN);
|
|
||||||
if (!it.IsFound()) return debug::NativeAccessorType::None;
|
|
||||||
if (it.state() != LookupIterator::ACCESSOR) {
|
|
||||||
return debug::NativeAccessorType::None;
|
|
||||||
}
|
|
||||||
Handle<Object> structure = it.GetAccessors();
|
|
||||||
if (!structure->IsAccessorInfo()) return debug::NativeAccessorType::None;
|
|
||||||
auto isolate = object->GetIsolate();
|
|
||||||
base::Flags<debug::NativeAccessorType, int> result;
|
|
||||||
#define IS_BUILTIN_ACESSOR(_, name, ...) \
|
|
||||||
if (*structure == *isolate->factory()->name##_accessor()) \
|
|
||||||
return debug::NativeAccessorType::None;
|
|
||||||
ACCESSOR_INFO_LIST_GENERATOR(IS_BUILTIN_ACESSOR, /* not used */)
|
|
||||||
#undef IS_BUILTIN_ACESSOR
|
|
||||||
Handle<AccessorInfo> accessor_info = Handle<AccessorInfo>::cast(structure);
|
|
||||||
if (accessor_info->getter()) {
|
|
||||||
result |= debug::NativeAccessorType::HasGetter;
|
|
||||||
}
|
|
||||||
if (accessor_info->setter()) {
|
|
||||||
result |= debug::NativeAccessorType::HasSetter;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
void DebugPropertyIterator::CalculateNativeAccessorFlags() {
|
|
||||||
if (calculated_native_accessor_flags_) return;
|
|
||||||
Handle<JSReceiver> receiver =
|
|
||||||
PrototypeIterator::GetCurrent<JSReceiver>(prototype_iterator_);
|
|
||||||
native_accessor_flags_ =
|
|
||||||
GetNativeAccessorDescriptorInternal(receiver, raw_name());
|
|
||||||
calculated_native_accessor_flags_ = true;
|
|
||||||
}
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace v8
|
|
@ -1,62 +0,0 @@
|
|||||||
// Copyright 2018 the V8 project authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef V8_DEBUG_DEBUG_PROPERTY_ITERATOR_H_
|
|
||||||
#define V8_DEBUG_DEBUG_PROPERTY_ITERATOR_H_
|
|
||||||
|
|
||||||
#include "src/debug/debug-interface.h"
|
|
||||||
#include "src/handles.h"
|
|
||||||
#include "src/isolate.h"
|
|
||||||
#include "src/prototype.h"
|
|
||||||
|
|
||||||
#include "include/v8.h"
|
|
||||||
|
|
||||||
namespace v8 {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
class JSReceiver;
|
|
||||||
|
|
||||||
class DebugPropertyIterator final : public debug::PropertyIterator {
|
|
||||||
public:
|
|
||||||
DebugPropertyIterator(Isolate* isolate, Handle<JSReceiver> receiver);
|
|
||||||
~DebugPropertyIterator() override = default;
|
|
||||||
|
|
||||||
bool Done() const override;
|
|
||||||
void Advance() override;
|
|
||||||
|
|
||||||
v8::Local<v8::Name> name() const override;
|
|
||||||
bool is_native_accessor() override;
|
|
||||||
bool has_native_getter() override;
|
|
||||||
bool has_native_setter() override;
|
|
||||||
v8::Maybe<v8::PropertyAttribute> attributes() override;
|
|
||||||
v8::Maybe<v8::debug::PropertyDescriptor> descriptor() override;
|
|
||||||
|
|
||||||
bool is_own() override;
|
|
||||||
bool is_array_index() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void FillKeysForCurrentPrototypeAndStage();
|
|
||||||
bool should_move_to_next_stage() const;
|
|
||||||
void CalculateNativeAccessorFlags();
|
|
||||||
Handle<Name> raw_name() const;
|
|
||||||
|
|
||||||
Isolate* isolate_;
|
|
||||||
PrototypeIterator prototype_iterator_;
|
|
||||||
enum Stage { kExoticIndices = 0, kEnumerableStrings = 1, kAllProperties = 2 };
|
|
||||||
Stage stage_ = kExoticIndices;
|
|
||||||
|
|
||||||
uint32_t current_key_index_ = 0;
|
|
||||||
Handle<FixedArray> keys_;
|
|
||||||
uint32_t exotic_length_ = 0;
|
|
||||||
|
|
||||||
bool calculated_native_accessor_flags_ = false;
|
|
||||||
int native_accessor_flags_ = 0;
|
|
||||||
bool is_own_ = true;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(DebugPropertyIterator);
|
|
||||||
};
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace v8
|
|
||||||
|
|
||||||
#endif // V8_DEBUG_DEBUG_PROPERTY_ITERATOR_H_
|
|
@ -61,6 +61,22 @@ inspector_protocol_generate("protocol_generated_sources") {
|
|||||||
outputs = _protocol_generated
|
outputs = _protocol_generated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action("inspector_injected_script") {
|
||||||
|
visibility = [ ":*" ] # Only targets in this file can depend on this.
|
||||||
|
script = "build/xxd.py"
|
||||||
|
inputs = [
|
||||||
|
"injected-script-source.js",
|
||||||
|
]
|
||||||
|
outputs = [
|
||||||
|
"$target_gen_dir/injected-script-source.h",
|
||||||
|
]
|
||||||
|
args = [
|
||||||
|
"InjectedScriptSource_js",
|
||||||
|
rebase_path("injected-script-source.js", root_build_dir),
|
||||||
|
rebase_path("$target_gen_dir/injected-script-source.h", root_build_dir),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
config("inspector_config") {
|
config("inspector_config") {
|
||||||
visibility = [ ":*" ] # Only targets in this file can depend on this.
|
visibility = [ ":*" ] # Only targets in this file can depend on this.
|
||||||
if (is_component_build) {
|
if (is_component_build) {
|
||||||
@ -70,6 +86,7 @@ config("inspector_config") {
|
|||||||
|
|
||||||
v8_source_set("inspector") {
|
v8_source_set("inspector") {
|
||||||
deps = [
|
deps = [
|
||||||
|
":inspector_injected_script",
|
||||||
":protocol_generated_sources",
|
":protocol_generated_sources",
|
||||||
]
|
]
|
||||||
configs = [ ":inspector_config" ]
|
configs = [ ":inspector_config" ]
|
||||||
@ -84,6 +101,7 @@ v8_source_set("inspector") {
|
|||||||
"../../include/v8-inspector-protocol.h",
|
"../../include/v8-inspector-protocol.h",
|
||||||
"../../include/v8-inspector.h",
|
"../../include/v8-inspector.h",
|
||||||
]
|
]
|
||||||
|
sources += get_target_outputs(":inspector_injected_script")
|
||||||
sources += [
|
sources += [
|
||||||
"custom-preview.cc",
|
"custom-preview.cc",
|
||||||
"custom-preview.h",
|
"custom-preview.h",
|
||||||
@ -113,12 +131,18 @@ v8_source_set("inspector") {
|
|||||||
"v8-debugger-script.h",
|
"v8-debugger-script.h",
|
||||||
"v8-debugger.cc",
|
"v8-debugger.cc",
|
||||||
"v8-debugger.h",
|
"v8-debugger.h",
|
||||||
|
"v8-function-call.cc",
|
||||||
|
"v8-function-call.h",
|
||||||
"v8-heap-profiler-agent-impl.cc",
|
"v8-heap-profiler-agent-impl.cc",
|
||||||
"v8-heap-profiler-agent-impl.h",
|
"v8-heap-profiler-agent-impl.h",
|
||||||
|
"v8-injected-script-host.cc",
|
||||||
|
"v8-injected-script-host.h",
|
||||||
"v8-inspector-impl.cc",
|
"v8-inspector-impl.cc",
|
||||||
"v8-inspector-impl.h",
|
"v8-inspector-impl.h",
|
||||||
"v8-inspector-session-impl.cc",
|
"v8-inspector-session-impl.cc",
|
||||||
"v8-inspector-session-impl.h",
|
"v8-inspector-session-impl.h",
|
||||||
|
"v8-internal-value-type.cc",
|
||||||
|
"v8-internal-value-type.h",
|
||||||
"v8-profiler-agent-impl.cc",
|
"v8-profiler-agent-impl.cc",
|
||||||
"v8-profiler-agent-impl.h",
|
"v8-profiler-agent-impl.h",
|
||||||
"v8-regex.cc",
|
"v8-regex.cc",
|
||||||
@ -131,8 +155,6 @@ v8_source_set("inspector") {
|
|||||||
"v8-stack-trace-impl.h",
|
"v8-stack-trace-impl.h",
|
||||||
"v8-value-utils.cc",
|
"v8-value-utils.cc",
|
||||||
"v8-value-utils.h",
|
"v8-value-utils.h",
|
||||||
"value-mirror.cc",
|
|
||||||
"value-mirror.h",
|
|
||||||
"wasm-translation.cc",
|
"wasm-translation.cc",
|
||||||
"wasm-translation.h",
|
"wasm-translation.h",
|
||||||
]
|
]
|
||||||
|
53
src/inspector/PRESUBMIT.py
Normal file
53
src/inspector/PRESUBMIT.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2016 the V8 project authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""v8_inspect presubmit script
|
||||||
|
|
||||||
|
See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
|
||||||
|
for more details about the presubmit API built into gcl.
|
||||||
|
"""
|
||||||
|
|
||||||
|
compile_note = "Be sure to run your patch by the compile-scripts.py script prior to committing!"
|
||||||
|
|
||||||
|
|
||||||
|
def _CompileScripts(input_api, output_api):
|
||||||
|
local_paths = [f.LocalPath() for f in input_api.AffectedFiles()]
|
||||||
|
|
||||||
|
compilation_related_files = [
|
||||||
|
"js_protocol.json"
|
||||||
|
"compile-scripts.js",
|
||||||
|
"injected-script-source.js",
|
||||||
|
"injected_script_externs.js",
|
||||||
|
"check_injected_script_source.js"
|
||||||
|
]
|
||||||
|
|
||||||
|
for file in compilation_related_files:
|
||||||
|
if (any(file in path for path in local_paths)):
|
||||||
|
script_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
|
||||||
|
"build", "compile-scripts.py")
|
||||||
|
proc = input_api.subprocess.Popen(
|
||||||
|
[input_api.python_executable, script_path],
|
||||||
|
stdout=input_api.subprocess.PIPE,
|
||||||
|
stderr=input_api.subprocess.STDOUT)
|
||||||
|
out, _ = proc.communicate()
|
||||||
|
if "ERROR" in out or "WARNING" in out or proc.returncode:
|
||||||
|
return [output_api.PresubmitError(out)]
|
||||||
|
if "NOTE" in out:
|
||||||
|
return [output_api.PresubmitPromptWarning(out + compile_note)]
|
||||||
|
return []
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def CheckChangeOnUpload(input_api, output_api):
|
||||||
|
results = []
|
||||||
|
results.extend(_CompileScripts(input_api, output_api))
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def CheckChangeOnCommit(input_api, output_api):
|
||||||
|
results = []
|
||||||
|
results.extend(_CompileScripts(input_api, output_api))
|
||||||
|
return results
|
88
src/inspector/build/check_injected_script_source.py
Normal file
88
src/inspector/build/check_injected_script_source.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# Copyright (c) 2014 Google Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above
|
||||||
|
# copyright notice, this list of conditions and the following disclaimer
|
||||||
|
# in the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
# * Neither the name of Google Inc. nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
# Copied from blink:
|
||||||
|
# WebKit/Source/devtools/scripts/check_injected_script_source.py
|
||||||
|
#
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def validate_injected_script(fileName):
|
||||||
|
f = open(fileName, "r")
|
||||||
|
lines = f.readlines()
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
proto_functions = "|".join([
|
||||||
|
# Array.prototype.*
|
||||||
|
"concat", "every", "filter", "forEach", "indexOf", "join", "lastIndexOf", "map", "pop",
|
||||||
|
"push", "reduce", "reduceRight", "reverse", "shift", "slice", "some", "sort", "splice", "toLocaleString", "toString", "unshift",
|
||||||
|
# Function.prototype.*
|
||||||
|
"apply", "bind", "call", "isGenerator", "toSource",
|
||||||
|
# Object.prototype.*
|
||||||
|
"toString",
|
||||||
|
])
|
||||||
|
|
||||||
|
global_functions = "|".join([
|
||||||
|
"eval", "uneval", "isFinite", "isNaN", "parseFloat", "parseInt", "decodeURI", "decodeURIComponent",
|
||||||
|
"encodeURI", "encodeURIComponent", "escape", "unescape", "Map", "Set"
|
||||||
|
])
|
||||||
|
|
||||||
|
# Black list:
|
||||||
|
# - instanceof, since e.g. "obj instanceof Error" may throw if Error is overridden and is not a function
|
||||||
|
# - Object.prototype.toString()
|
||||||
|
# - Array.prototype.*
|
||||||
|
# - Function.prototype.*
|
||||||
|
# - Math.*
|
||||||
|
# - Global functions
|
||||||
|
black_list_call_regex = re.compile(r"\sinstanceof\s+\w*|\bMath\.\w+\(|(?<!InjectedScriptHost)\.(" + proto_functions + r")\(|[^\.]\b(" + global_functions + r")\(")
|
||||||
|
|
||||||
|
errors_found = False
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
if line.find("suppressBlacklist") != -1:
|
||||||
|
continue
|
||||||
|
for match in re.finditer(black_list_call_regex, line):
|
||||||
|
errors_found = True
|
||||||
|
print "ERROR: Black listed expression in %s at line %02d column %02d: %s" % (os.path.basename(fileName), i + 1, match.start(), match.group(0))
|
||||||
|
|
||||||
|
if not errors_found:
|
||||||
|
print "OK"
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
if len(argv) < 2:
|
||||||
|
print('ERROR: Usage: %s path/to/injected-script-source.js' % argv[0])
|
||||||
|
return 1
|
||||||
|
|
||||||
|
validate_injected_script(argv[1])
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main(sys.argv))
|
1
src/inspector/build/closure-compiler.tar.gz.sha1
Normal file
1
src/inspector/build/closure-compiler.tar.gz.sha1
Normal file
@ -0,0 +1 @@
|
|||||||
|
69937d3c239ca63e4c9045718886ddd096ffc054
|
150
src/inspector/build/compile-scripts.py
Executable file
150
src/inspector/build/compile-scripts.py
Executable file
@ -0,0 +1,150 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2016 the V8 project authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import os.path as path
|
||||||
|
import generate_protocol_externs
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if len(sys.argv) == 2 and sys.argv[1] == '--help':
|
||||||
|
print("Usage: %s" % path.basename(sys.argv[0]))
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
java_required_major = 1
|
||||||
|
java_required_minor = 7
|
||||||
|
|
||||||
|
v8_inspector_path = path.dirname(path.dirname(path.abspath(__file__)))
|
||||||
|
|
||||||
|
protocol_externs_file = path.join(v8_inspector_path, 'protocol_externs.js')
|
||||||
|
injected_script_source_name = path.join(v8_inspector_path,
|
||||||
|
'injected-script-source.js')
|
||||||
|
injected_script_externs_file = path.join(v8_inspector_path,
|
||||||
|
'injected_script_externs.js')
|
||||||
|
|
||||||
|
generate_protocol_externs.generate_protocol_externs(protocol_externs_file,
|
||||||
|
path.join(v8_inspector_path, 'js_protocol.json'))
|
||||||
|
|
||||||
|
error_warning_regex = re.compile(r'WARNING|ERROR')
|
||||||
|
|
||||||
|
closure_compiler_jar = path.join(v8_inspector_path, 'build',
|
||||||
|
'closure-compiler', 'closure-compiler.jar')
|
||||||
|
|
||||||
|
common_closure_args = [
|
||||||
|
'--checks_only',
|
||||||
|
'--warning_level', 'VERBOSE'
|
||||||
|
]
|
||||||
|
|
||||||
|
# Error reporting and checking.
|
||||||
|
errors_found = False
|
||||||
|
|
||||||
|
def popen(arguments):
|
||||||
|
return subprocess.Popen(arguments, stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT)
|
||||||
|
|
||||||
|
def error_excepthook(exctype, value, traceback):
|
||||||
|
print 'ERROR:'
|
||||||
|
sys.__excepthook__(exctype, value, traceback)
|
||||||
|
sys.excepthook = error_excepthook
|
||||||
|
|
||||||
|
def has_errors(output):
|
||||||
|
return re.search(error_warning_regex, output) != None
|
||||||
|
|
||||||
|
# Find java. Based on
|
||||||
|
# http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python.
|
||||||
|
def which(program):
|
||||||
|
def is_exe(fpath):
|
||||||
|
return path.isfile(fpath) and os.access(fpath, os.X_OK)
|
||||||
|
|
||||||
|
fpath, fname = path.split(program)
|
||||||
|
if fpath:
|
||||||
|
if is_exe(program):
|
||||||
|
return program
|
||||||
|
else:
|
||||||
|
for part in os.environ['PATH'].split(os.pathsep):
|
||||||
|
part = part.strip('"')
|
||||||
|
exe_file = path.join(part, program)
|
||||||
|
if is_exe(exe_file):
|
||||||
|
return exe_file
|
||||||
|
return None
|
||||||
|
|
||||||
|
def find_java():
|
||||||
|
exec_command = None
|
||||||
|
has_server_jvm = True
|
||||||
|
java_path = which('java')
|
||||||
|
if not java_path:
|
||||||
|
java_path = which('java.exe')
|
||||||
|
|
||||||
|
if not java_path:
|
||||||
|
print 'NOTE: No Java executable found in $PATH.'
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
is_ok = False
|
||||||
|
java_version_out, _ = popen([java_path, '-version']).communicate()
|
||||||
|
java_build_regex = re.compile(r'^\w+ version "(\d+)\.(\d+)')
|
||||||
|
# pylint: disable=E1103
|
||||||
|
match = re.search(java_build_regex, java_version_out)
|
||||||
|
if match:
|
||||||
|
major = int(match.group(1))
|
||||||
|
minor = int(match.group(2))
|
||||||
|
is_ok = major >= java_required_major and minor >= java_required_minor
|
||||||
|
if is_ok:
|
||||||
|
exec_command = [java_path, '-Xms1024m', '-server',
|
||||||
|
'-XX:+TieredCompilation']
|
||||||
|
check_server_proc = popen(exec_command + ['-version'])
|
||||||
|
check_server_proc.communicate()
|
||||||
|
if check_server_proc.returncode != 0:
|
||||||
|
# Not all Java installs have server JVMs.
|
||||||
|
exec_command = exec_command.remove('-server')
|
||||||
|
has_server_jvm = False
|
||||||
|
|
||||||
|
if not is_ok:
|
||||||
|
print 'NOTE: Java executable version %d.%d or above not found in $PATH.' % (java_required_major, java_required_minor)
|
||||||
|
sys.exit(0)
|
||||||
|
print 'Java executable: %s%s' % (java_path, '' if has_server_jvm else ' (no server JVM)')
|
||||||
|
return exec_command
|
||||||
|
|
||||||
|
java_exec = find_java()
|
||||||
|
|
||||||
|
spawned_compiler_command = java_exec + [
|
||||||
|
'-jar',
|
||||||
|
closure_compiler_jar
|
||||||
|
] + common_closure_args
|
||||||
|
|
||||||
|
print 'Compiling injected-script-source.js...'
|
||||||
|
|
||||||
|
command = spawned_compiler_command + [
|
||||||
|
'--externs', injected_script_externs_file,
|
||||||
|
'--externs', protocol_externs_file,
|
||||||
|
'--js', injected_script_source_name
|
||||||
|
]
|
||||||
|
|
||||||
|
injected_script_compile_proc = popen(command)
|
||||||
|
|
||||||
|
print 'Validating injected-script-source.js...'
|
||||||
|
injectedscript_check_script_path = path.join(v8_inspector_path, 'build',
|
||||||
|
'check_injected_script_source.py')
|
||||||
|
validate_injected_script_proc = popen([sys.executable,
|
||||||
|
injectedscript_check_script_path, injected_script_source_name])
|
||||||
|
|
||||||
|
print
|
||||||
|
|
||||||
|
(injected_script_compile_out, _) = injected_script_compile_proc.communicate()
|
||||||
|
print 'injected-script-source.js compilation output:%s' % os.linesep
|
||||||
|
print injected_script_compile_out
|
||||||
|
errors_found |= has_errors(injected_script_compile_out)
|
||||||
|
|
||||||
|
(validate_injected_script_out, _) = validate_injected_script_proc.communicate()
|
||||||
|
print 'Validate injected-script-source.js output:%s' % os.linesep
|
||||||
|
print validate_injected_script_out if validate_injected_script_out else '<empty>'
|
||||||
|
errors_found |= has_errors(validate_injected_script_out)
|
||||||
|
|
||||||
|
os.remove(protocol_externs_file)
|
||||||
|
|
||||||
|
if errors_found:
|
||||||
|
print 'ERRORS DETECTED'
|
||||||
|
sys.exit(1)
|
246
src/inspector/build/generate_protocol_externs.py
Executable file
246
src/inspector/build/generate_protocol_externs.py
Executable file
@ -0,0 +1,246 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# Copyright (c) 2011 Google Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above
|
||||||
|
# copyright notice, this list of conditions and the following disclaimer
|
||||||
|
# in the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
# * Neither the name of Google Inc. nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import json
|
||||||
|
|
||||||
|
type_traits = {
|
||||||
|
"any": "*",
|
||||||
|
"string": "string",
|
||||||
|
"integer": "number",
|
||||||
|
"number": "number",
|
||||||
|
"boolean": "boolean",
|
||||||
|
"array": "!Array.<*>",
|
||||||
|
"object": "!Object",
|
||||||
|
}
|
||||||
|
|
||||||
|
promisified_domains = {
|
||||||
|
"Accessibility",
|
||||||
|
"Animation",
|
||||||
|
"CSS",
|
||||||
|
"Emulation",
|
||||||
|
"Profiler"
|
||||||
|
}
|
||||||
|
|
||||||
|
ref_types = {}
|
||||||
|
|
||||||
|
def full_qualified_type_id(domain_name, type_id):
|
||||||
|
if type_id.find(".") == -1:
|
||||||
|
return "%s.%s" % (domain_name, type_id)
|
||||||
|
return type_id
|
||||||
|
|
||||||
|
|
||||||
|
def fix_camel_case(name):
|
||||||
|
prefix = ""
|
||||||
|
if name[0] == "-":
|
||||||
|
prefix = "Negative"
|
||||||
|
name = name[1:]
|
||||||
|
refined = re.sub(r'-(\w)', lambda pat: pat.group(1).upper(), name)
|
||||||
|
refined = to_title_case(refined)
|
||||||
|
return prefix + re.sub(r'(?i)HTML|XML|WML|API', lambda pat: pat.group(0).upper(), refined)
|
||||||
|
|
||||||
|
|
||||||
|
def to_title_case(name):
|
||||||
|
return name[:1].upper() + name[1:]
|
||||||
|
|
||||||
|
|
||||||
|
def generate_enum(name, json):
|
||||||
|
enum_members = []
|
||||||
|
for member in json["enum"]:
|
||||||
|
enum_members.append(" %s: \"%s\"" % (fix_camel_case(member), member))
|
||||||
|
return "\n/** @enum {string} */\n%s = {\n%s\n};\n" % (name, (",\n".join(enum_members)))
|
||||||
|
|
||||||
|
|
||||||
|
def param_type(domain_name, param):
|
||||||
|
if "type" in param:
|
||||||
|
if param["type"] == "array":
|
||||||
|
items = param["items"]
|
||||||
|
return "!Array.<%s>" % param_type(domain_name, items)
|
||||||
|
else:
|
||||||
|
return type_traits[param["type"]]
|
||||||
|
if "$ref" in param:
|
||||||
|
type_id = full_qualified_type_id(domain_name, param["$ref"])
|
||||||
|
if type_id in ref_types:
|
||||||
|
return ref_types[type_id]
|
||||||
|
else:
|
||||||
|
print "Type not found: " + type_id
|
||||||
|
return "!! Type not found: " + type_id
|
||||||
|
|
||||||
|
|
||||||
|
def load_schema(file, domains):
|
||||||
|
input_file = open(file, "r")
|
||||||
|
json_string = input_file.read()
|
||||||
|
parsed_json = json.loads(json_string)
|
||||||
|
domains.extend(parsed_json["domains"])
|
||||||
|
|
||||||
|
|
||||||
|
def generate_protocol_externs(output_path, file1):
|
||||||
|
domains = []
|
||||||
|
load_schema(file1, domains)
|
||||||
|
output_file = open(output_path, "w")
|
||||||
|
|
||||||
|
output_file.write(
|
||||||
|
"""
|
||||||
|
var InspectorBackend = {}
|
||||||
|
|
||||||
|
var Protocol = {};
|
||||||
|
/** @typedef {string}*/
|
||||||
|
Protocol.Error;
|
||||||
|
""")
|
||||||
|
|
||||||
|
for domain in domains:
|
||||||
|
domain_name = domain["domain"]
|
||||||
|
if "types" in domain:
|
||||||
|
for type in domain["types"]:
|
||||||
|
type_id = full_qualified_type_id(domain_name, type["id"])
|
||||||
|
ref_types[type_id] = "%sAgent.%s" % (domain_name, type["id"])
|
||||||
|
|
||||||
|
for domain in domains:
|
||||||
|
domain_name = domain["domain"]
|
||||||
|
promisified = domain_name in promisified_domains
|
||||||
|
|
||||||
|
output_file.write("\n\n/**\n * @constructor\n*/\n")
|
||||||
|
output_file.write("Protocol.%sAgent = function(){};\n" % domain_name)
|
||||||
|
|
||||||
|
if "commands" in domain:
|
||||||
|
for command in domain["commands"]:
|
||||||
|
output_file.write("\n/**\n")
|
||||||
|
params = []
|
||||||
|
has_return_value = "returns" in command
|
||||||
|
explicit_parameters = promisified and has_return_value
|
||||||
|
if ("parameters" in command):
|
||||||
|
for in_param in command["parameters"]:
|
||||||
|
# All parameters are not optional in case of promisified domain with return value.
|
||||||
|
if (not explicit_parameters and "optional" in in_param):
|
||||||
|
params.append("opt_%s" % in_param["name"])
|
||||||
|
output_file.write(" * @param {%s=} opt_%s\n" % (param_type(domain_name, in_param), in_param["name"]))
|
||||||
|
else:
|
||||||
|
params.append(in_param["name"])
|
||||||
|
output_file.write(" * @param {%s} %s\n" % (param_type(domain_name, in_param), in_param["name"]))
|
||||||
|
returns = []
|
||||||
|
returns.append("?Protocol.Error")
|
||||||
|
if ("error" in command):
|
||||||
|
returns.append("%s=" % param_type(domain_name, command["error"]))
|
||||||
|
if (has_return_value):
|
||||||
|
for out_param in command["returns"]:
|
||||||
|
if ("optional" in out_param):
|
||||||
|
returns.append("%s=" % param_type(domain_name, out_param))
|
||||||
|
else:
|
||||||
|
returns.append("%s" % param_type(domain_name, out_param))
|
||||||
|
callback_return_type = "void="
|
||||||
|
if explicit_parameters:
|
||||||
|
callback_return_type = "T"
|
||||||
|
elif promisified:
|
||||||
|
callback_return_type = "T="
|
||||||
|
output_file.write(" * @param {function(%s):%s} opt_callback\n" % (", ".join(returns), callback_return_type))
|
||||||
|
if (promisified):
|
||||||
|
output_file.write(" * @return {!Promise.<T>}\n")
|
||||||
|
output_file.write(" * @template T\n")
|
||||||
|
params.append("opt_callback")
|
||||||
|
|
||||||
|
output_file.write(" */\n")
|
||||||
|
output_file.write("Protocol.%sAgent.prototype.%s = function(%s) {}\n" % (domain_name, command["name"], ", ".join(params)))
|
||||||
|
output_file.write("/** @param {function(%s):void=} opt_callback */\n" % ", ".join(returns))
|
||||||
|
output_file.write("Protocol.%sAgent.prototype.invoke_%s = function(obj, opt_callback) {}\n" % (domain_name, command["name"]))
|
||||||
|
|
||||||
|
output_file.write("\n\n\nvar %sAgent = function(){};\n" % domain_name)
|
||||||
|
|
||||||
|
if "types" in domain:
|
||||||
|
for type in domain["types"]:
|
||||||
|
if type["type"] == "object":
|
||||||
|
typedef_args = []
|
||||||
|
if "properties" in type:
|
||||||
|
for property in type["properties"]:
|
||||||
|
suffix = ""
|
||||||
|
if ("optional" in property):
|
||||||
|
suffix = "|undefined"
|
||||||
|
if "enum" in property:
|
||||||
|
enum_name = "%sAgent.%s%s" % (domain_name, type["id"], to_title_case(property["name"]))
|
||||||
|
output_file.write(generate_enum(enum_name, property))
|
||||||
|
typedef_args.append("%s:(%s%s)" % (property["name"], enum_name, suffix))
|
||||||
|
else:
|
||||||
|
typedef_args.append("%s:(%s%s)" % (property["name"], param_type(domain_name, property), suffix))
|
||||||
|
if (typedef_args):
|
||||||
|
output_file.write("\n/** @typedef {!{%s}} */\n%sAgent.%s;\n" % (", ".join(typedef_args), domain_name, type["id"]))
|
||||||
|
else:
|
||||||
|
output_file.write("\n/** @typedef {!Object} */\n%sAgent.%s;\n" % (domain_name, type["id"]))
|
||||||
|
elif type["type"] == "string" and "enum" in type:
|
||||||
|
output_file.write(generate_enum("%sAgent.%s" % (domain_name, type["id"]), type))
|
||||||
|
elif type["type"] == "array":
|
||||||
|
output_file.write("\n/** @typedef {!Array.<!%s>} */\n%sAgent.%s;\n" % (param_type(domain_name, type["items"]), domain_name, type["id"]))
|
||||||
|
else:
|
||||||
|
output_file.write("\n/** @typedef {%s} */\n%sAgent.%s;\n" % (type_traits[type["type"]], domain_name, type["id"]))
|
||||||
|
|
||||||
|
output_file.write("/** @interface */\n")
|
||||||
|
output_file.write("%sAgent.Dispatcher = function() {};\n" % domain_name)
|
||||||
|
if "events" in domain:
|
||||||
|
for event in domain["events"]:
|
||||||
|
params = []
|
||||||
|
if ("parameters" in event):
|
||||||
|
output_file.write("/**\n")
|
||||||
|
for param in event["parameters"]:
|
||||||
|
if ("optional" in param):
|
||||||
|
params.append("opt_%s" % param["name"])
|
||||||
|
output_file.write(" * @param {%s=} opt_%s\n" % (param_type(domain_name, param), param["name"]))
|
||||||
|
else:
|
||||||
|
params.append(param["name"])
|
||||||
|
output_file.write(" * @param {%s} %s\n" % (param_type(domain_name, param), param["name"]))
|
||||||
|
output_file.write(" */\n")
|
||||||
|
output_file.write("%sAgent.Dispatcher.prototype.%s = function(%s) {};\n" % (domain_name, event["name"], ", ".join(params)))
|
||||||
|
|
||||||
|
output_file.write("\n/** @constructor\n * @param {!Object.<string, !Object>} agentsMap\n */\n")
|
||||||
|
output_file.write("Protocol.Agents = function(agentsMap){this._agentsMap;};\n")
|
||||||
|
output_file.write("/**\n * @param {string} domain\n * @param {!Object} dispatcher\n */\n")
|
||||||
|
output_file.write("Protocol.Agents.prototype.registerDispatcher = function(domain, dispatcher){};\n")
|
||||||
|
for domain in domains:
|
||||||
|
domain_name = domain["domain"]
|
||||||
|
uppercase_length = 0
|
||||||
|
while uppercase_length < len(domain_name) and domain_name[uppercase_length].isupper():
|
||||||
|
uppercase_length += 1
|
||||||
|
|
||||||
|
output_file.write("/** @return {!Protocol.%sAgent}*/\n" % domain_name)
|
||||||
|
output_file.write("Protocol.Agents.prototype.%s = function(){};\n" % (domain_name[:uppercase_length].lower() + domain_name[uppercase_length:] + "Agent"))
|
||||||
|
|
||||||
|
output_file.write("/**\n * @param {!%sAgent.Dispatcher} dispatcher\n */\n" % domain_name)
|
||||||
|
output_file.write("Protocol.Agents.prototype.register%sDispatcher = function(dispatcher) {}\n" % domain_name)
|
||||||
|
|
||||||
|
|
||||||
|
output_file.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
import os.path
|
||||||
|
program_name = os.path.basename(__file__)
|
||||||
|
if len(sys.argv) < 4 or sys.argv[1] != "-o":
|
||||||
|
sys.stderr.write("Usage: %s -o OUTPUT_FILE INPUT_FILE\n" % program_name)
|
||||||
|
exit(1)
|
||||||
|
output_path = sys.argv[2]
|
||||||
|
input_path = sys.argv[3]
|
||||||
|
generate_protocol_externs(output_path, input_path)
|
295
src/inspector/build/rjsmin.py
Executable file
295
src/inspector/build/rjsmin.py
Executable file
@ -0,0 +1,295 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2011 - 2013
|
||||||
|
# Andr\xe9 Malo or his licensors, as applicable
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
r"""
|
||||||
|
=====================
|
||||||
|
Javascript Minifier
|
||||||
|
=====================
|
||||||
|
|
||||||
|
rJSmin is a javascript minifier written in python.
|
||||||
|
|
||||||
|
The minifier is based on the semantics of `jsmin.c by Douglas Crockford`_\.
|
||||||
|
|
||||||
|
The module is a re-implementation aiming for speed, so it can be used at
|
||||||
|
runtime (rather than during a preprocessing step). Usually it produces the
|
||||||
|
same results as the original ``jsmin.c``. It differs in the following ways:
|
||||||
|
|
||||||
|
- there is no error detection: unterminated string, regex and comment
|
||||||
|
literals are treated as regular javascript code and minified as such.
|
||||||
|
- Control characters inside string and regex literals are left untouched; they
|
||||||
|
are not converted to spaces (nor to \n)
|
||||||
|
- Newline characters are not allowed inside string and regex literals, except
|
||||||
|
for line continuations in string literals (ECMA-5).
|
||||||
|
- "return /regex/" is recognized correctly.
|
||||||
|
- "+ +" and "- -" sequences are not collapsed to '++' or '--'
|
||||||
|
- Newlines before ! operators are removed more sensibly
|
||||||
|
- rJSmin does not handle streams, but only complete strings. (However, the
|
||||||
|
module provides a "streamy" interface).
|
||||||
|
|
||||||
|
Since most parts of the logic are handled by the regex engine it's way
|
||||||
|
faster than the original python port of ``jsmin.c`` by Baruch Even. The speed
|
||||||
|
factor varies between about 6 and 55 depending on input and python version
|
||||||
|
(it gets faster the more compressed the input already is). Compared to the
|
||||||
|
speed-refactored python port by Dave St.Germain the performance gain is less
|
||||||
|
dramatic but still between 1.2 and 7. See the docs/BENCHMARKS file for
|
||||||
|
details.
|
||||||
|
|
||||||
|
rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more.
|
||||||
|
|
||||||
|
Both python 2 and python 3 are supported.
|
||||||
|
|
||||||
|
.. _jsmin.c by Douglas Crockford:
|
||||||
|
http://www.crockford.com/javascript/jsmin.c
|
||||||
|
"""
|
||||||
|
__author__ = "Andr\xe9 Malo"
|
||||||
|
__author__ = getattr(__author__, 'decode', lambda x: __author__)('latin-1')
|
||||||
|
__docformat__ = "restructuredtext en"
|
||||||
|
__license__ = "Apache License, Version 2.0"
|
||||||
|
__version__ = '1.0.7'
|
||||||
|
__all__ = ['jsmin']
|
||||||
|
|
||||||
|
import re as _re
|
||||||
|
|
||||||
|
|
||||||
|
def _make_jsmin(python_only=False):
|
||||||
|
"""
|
||||||
|
Generate JS minifier based on `jsmin.c by Douglas Crockford`_
|
||||||
|
|
||||||
|
.. _jsmin.c by Douglas Crockford:
|
||||||
|
http://www.crockford.com/javascript/jsmin.c
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
`python_only` : ``bool``
|
||||||
|
Use only the python variant. If true, the c extension is not even
|
||||||
|
tried to be loaded.
|
||||||
|
|
||||||
|
:Return: Minifier
|
||||||
|
:Rtype: ``callable``
|
||||||
|
"""
|
||||||
|
# pylint: disable = R0912, R0914, W0612
|
||||||
|
if not python_only:
|
||||||
|
try:
|
||||||
|
import _rjsmin
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
return _rjsmin.jsmin
|
||||||
|
try:
|
||||||
|
xrange
|
||||||
|
except NameError:
|
||||||
|
xrange = range # pylint: disable = W0622
|
||||||
|
|
||||||
|
space_chars = r'[\000-\011\013\014\016-\040]'
|
||||||
|
|
||||||
|
line_comment = r'(?://[^\r\n]*)'
|
||||||
|
space_comment = r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
|
||||||
|
string1 = \
|
||||||
|
r'(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^\047\\\r\n]*)*\047)'
|
||||||
|
string2 = r'(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^"\\\r\n]*)*")'
|
||||||
|
strings = r'(?:%s|%s)' % (string1, string2)
|
||||||
|
|
||||||
|
charclass = r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\])'
|
||||||
|
nospecial = r'[^/\\\[\r\n]'
|
||||||
|
regex = r'(?:/(?![\r\n/*])%s*(?:(?:\\[^\r\n]|%s)%s*)*/)' % (
|
||||||
|
nospecial, charclass, nospecial)
|
||||||
|
space = r'(?:%s|%s)' % (space_chars, space_comment)
|
||||||
|
newline = r'(?:%s?[\r\n])' % line_comment
|
||||||
|
|
||||||
|
def fix_charclass(result):
|
||||||
|
""" Fixup string of chars to fit into a regex char class """
|
||||||
|
pos = result.find('-')
|
||||||
|
if pos >= 0:
|
||||||
|
result = r'%s%s-' % (result[:pos], result[pos + 1:])
|
||||||
|
|
||||||
|
def sequentize(string):
|
||||||
|
"""
|
||||||
|
Notate consecutive characters as sequence
|
||||||
|
|
||||||
|
(1-4 instead of 1234)
|
||||||
|
"""
|
||||||
|
first, last, result = None, None, []
|
||||||
|
for char in map(ord, string):
|
||||||
|
if last is None:
|
||||||
|
first = last = char
|
||||||
|
elif last + 1 == char:
|
||||||
|
last = char
|
||||||
|
else:
|
||||||
|
result.append((first, last))
|
||||||
|
first = last = char
|
||||||
|
if last is not None:
|
||||||
|
result.append((first, last))
|
||||||
|
return ''.join(['%s%s%s' % (
|
||||||
|
chr(first),
|
||||||
|
last > first + 1 and '-' or '',
|
||||||
|
last != first and chr(last) or '') for first, last in result])
|
||||||
|
|
||||||
|
return _re.sub(r'([\000-\040\047])', # for better portability
|
||||||
|
lambda m: '\\%03o' % ord(m.group(1)), (sequentize(result)
|
||||||
|
.replace('\\', '\\\\')
|
||||||
|
.replace('[', '\\[')
|
||||||
|
.replace(']', '\\]')))
|
||||||
|
|
||||||
|
def id_literal_(what):
|
||||||
|
""" Make id_literal like char class """
|
||||||
|
match = _re.compile(what).match
|
||||||
|
result = ''.join([chr(c) for c in xrange(127) if not match(chr(c))])
|
||||||
|
return '[^%s]' % fix_charclass(result)
|
||||||
|
|
||||||
|
def not_id_literal_(keep):
|
||||||
|
""" Make negated id_literal like char class """
|
||||||
|
match = _re.compile(id_literal_(keep)).match
|
||||||
|
result = ''.join([chr(c) for c in xrange(127) if not match(chr(c))])
|
||||||
|
return r'[%s]' % fix_charclass(result)
|
||||||
|
|
||||||
|
not_id_literal = not_id_literal_(r'[a-zA-Z0-9_$]')
|
||||||
|
preregex1 = r'[(,=:\[!&|?{};\r\n]'
|
||||||
|
preregex2 = r'%(not_id_literal)sreturn' % locals()
|
||||||
|
|
||||||
|
id_literal = id_literal_(r'[a-zA-Z0-9_$]')
|
||||||
|
id_literal_open = id_literal_(r'[a-zA-Z0-9_${\[(!+-]')
|
||||||
|
id_literal_close = id_literal_(r'[a-zA-Z0-9_$}\])"\047+-]')
|
||||||
|
|
||||||
|
dull = r'[^\047"/\000-\040]'
|
||||||
|
|
||||||
|
space_sub = _re.compile((
|
||||||
|
r'(%(dull)s+)'
|
||||||
|
r'|(%(strings)s%(dull)s*)'
|
||||||
|
r'|(?<=%(preregex1)s)'
|
||||||
|
r'%(space)s*(?:%(newline)s%(space)s*)*'
|
||||||
|
r'(%(regex)s%(dull)s*)'
|
||||||
|
r'|(?<=%(preregex2)s)'
|
||||||
|
r'%(space)s*(?:%(newline)s%(space)s)*'
|
||||||
|
r'(%(regex)s%(dull)s*)'
|
||||||
|
r'|(?<=%(id_literal_close)s)'
|
||||||
|
r'%(space)s*(?:(%(newline)s)%(space)s*)+'
|
||||||
|
r'(?=%(id_literal_open)s)'
|
||||||
|
r'|(?<=%(id_literal)s)(%(space)s)+(?=%(id_literal)s)'
|
||||||
|
r'|(?<=\+)(%(space)s)+(?=\+)'
|
||||||
|
r'|(?<=-)(%(space)s)+(?=-)'
|
||||||
|
r'|%(space)s+'
|
||||||
|
r'|(?:%(newline)s%(space)s*)+') % locals()).sub
|
||||||
|
#print space_sub.__self__.pattern
|
||||||
|
|
||||||
|
def space_subber(match):
|
||||||
|
""" Substitution callback """
|
||||||
|
# pylint: disable = C0321, R0911
|
||||||
|
groups = match.groups()
|
||||||
|
if groups[0]:
|
||||||
|
return groups[0]
|
||||||
|
elif groups[1]:
|
||||||
|
return groups[1]
|
||||||
|
elif groups[2]:
|
||||||
|
return groups[2]
|
||||||
|
elif groups[3]:
|
||||||
|
return groups[3]
|
||||||
|
elif groups[4]:
|
||||||
|
return '\n'
|
||||||
|
elif groups[5] or groups[6] or groups[7]:
|
||||||
|
return ' '
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def jsmin(script): # pylint: disable = W0621
|
||||||
|
r"""
|
||||||
|
Minify javascript based on `jsmin.c by Douglas Crockford`_\.
|
||||||
|
|
||||||
|
Instead of parsing the stream char by char, it uses a regular
|
||||||
|
expression approach which minifies the whole script with one big
|
||||||
|
substitution regex.
|
||||||
|
|
||||||
|
.. _jsmin.c by Douglas Crockford:
|
||||||
|
http://www.crockford.com/javascript/jsmin.c
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
`script` : ``str``
|
||||||
|
Script to minify
|
||||||
|
|
||||||
|
:Return: Minified script
|
||||||
|
:Rtype: ``str``
|
||||||
|
"""
|
||||||
|
return space_sub(space_subber, '\n%s\n' % script).strip()
|
||||||
|
|
||||||
|
return jsmin
|
||||||
|
|
||||||
|
jsmin = _make_jsmin()
|
||||||
|
|
||||||
|
|
||||||
|
def jsmin_for_posers(script):
|
||||||
|
r"""
|
||||||
|
Minify javascript based on `jsmin.c by Douglas Crockford`_\.
|
||||||
|
|
||||||
|
Instead of parsing the stream char by char, it uses a regular
|
||||||
|
expression approach which minifies the whole script with one big
|
||||||
|
substitution regex.
|
||||||
|
|
||||||
|
.. _jsmin.c by Douglas Crockford:
|
||||||
|
http://www.crockford.com/javascript/jsmin.c
|
||||||
|
|
||||||
|
:Warning: This function is the digest of a _make_jsmin() call. It just
|
||||||
|
utilizes the resulting regex. It's just for fun here and may
|
||||||
|
vanish any time. Use the `jsmin` function instead.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
`script` : ``str``
|
||||||
|
Script to minify
|
||||||
|
|
||||||
|
:Return: Minified script
|
||||||
|
:Rtype: ``str``
|
||||||
|
"""
|
||||||
|
def subber(match):
|
||||||
|
""" Substitution callback """
|
||||||
|
groups = match.groups()
|
||||||
|
return (
|
||||||
|
groups[0] or
|
||||||
|
groups[1] or
|
||||||
|
groups[2] or
|
||||||
|
groups[3] or
|
||||||
|
(groups[4] and '\n') or
|
||||||
|
(groups[5] and ' ') or
|
||||||
|
(groups[6] and ' ') or
|
||||||
|
(groups[7] and ' ') or
|
||||||
|
'')
|
||||||
|
|
||||||
|
return _re.sub(
|
||||||
|
r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?'
|
||||||
|
r'\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|'
|
||||||
|
r'\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?<=[(,=:\[!&|?{};\r\n])(?'
|
||||||
|
r':[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*'
|
||||||
|
r'(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*'
|
||||||
|
r'[^*]*\*+(?:[^/*][^*]*\*+)*/))*)*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:('
|
||||||
|
r'?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\['
|
||||||
|
r'\r\n]*)*/)[^\047"/\000-\040]*)|(?<=[\000-#%-,./:-@\[-^`{-~-]return'
|
||||||
|
r')(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/'
|
||||||
|
r'))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:'
|
||||||
|
r'/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?'
|
||||||
|
r':(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/'
|
||||||
|
r'\\\[\r\n]*)*/)[^\047"/\000-\040]*)|(?<=[^\000-!#%&(*,./:-@\[\\^`{|'
|
||||||
|
r'~])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)'
|
||||||
|
r'*/))*(?:((?:(?://[^\r\n]*)?[\r\n]))(?:[\000-\011\013\014\016-\040]'
|
||||||
|
r'|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040"#%-\047)*,./'
|
||||||
|
r':-@\\-^`|-~])|(?<=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-\011\013\01'
|
||||||
|
r'4\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=[^\000-#%-,./:'
|
||||||
|
r'-@\[-^`{-~-])|(?<=\+)((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*'
|
||||||
|
r'\*+(?:[^/*][^*]*\*+)*/)))+(?=\+)|(?<=-)((?:[\000-\011\013\014\016-'
|
||||||
|
r'\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=-)|(?:[\000-\011\013'
|
||||||
|
r'\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+|(?:(?:(?://[^'
|
||||||
|
r'\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^'
|
||||||
|
r'/*][^*]*\*+)*/))*)+', subber, '\n%s\n' % script).strip()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys as _sys
|
||||||
|
_sys.stdout.write(jsmin(_sys.stdin.read()))
|
28
src/inspector/build/xxd.py
Normal file
28
src/inspector/build/xxd.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Copyright 2016 the V8 project authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
"""Represent a file as a C++ constant string.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python xxd.py VAR SOURCE DEST
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import rjsmin
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
variable_name, input_filename, output_filename = sys.argv[1:]
|
||||||
|
with open(input_filename) as input_file:
|
||||||
|
input_text = input_file.read()
|
||||||
|
input_text = rjsmin.jsmin(input_text)
|
||||||
|
hex_values = ['0x{0:02x}'.format(ord(char)) for char in input_text]
|
||||||
|
const_declaration = 'const char %s[] = {\n%s\n};\n' % (
|
||||||
|
variable_name, ', '.join(hex_values))
|
||||||
|
with open(output_filename, 'w') as output_file:
|
||||||
|
output_file.write(const_declaration)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
@ -113,7 +113,7 @@ bool substituteObjectTags(int sessionId, const String16& groupName,
|
|||||||
}
|
}
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject> wrapper;
|
std::unique_ptr<protocol::Runtime::RemoteObject> wrapper;
|
||||||
protocol::Response response =
|
protocol::Response response =
|
||||||
injectedScript->wrapObject(originValue, groupName, WrapMode::kNoPreview,
|
injectedScript->wrapObject(originValue, groupName, false, false,
|
||||||
configValue, maxDepth - 1, &wrapper);
|
configValue, maxDepth - 1, &wrapper);
|
||||||
if (!response.isSuccess() || !wrapper) {
|
if (!response.isSuccess() || !wrapper) {
|
||||||
reportError(context, tryCatch, "cannot wrap value");
|
reportError(context, tryCatch, "cannot wrap value");
|
||||||
@ -379,8 +379,13 @@ void generateCustomPreview(int sessionId, const String16& groupName,
|
|||||||
reportError(context, tryCatch, "cannot find context with specified id");
|
reportError(context, tryCatch, "cannot find context with specified id");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(*preview)->setBodyGetterId(
|
(*preview)->setBodyGetterId(String16::concat(
|
||||||
injectedScript->bindObject(bodyFunction, groupName));
|
"{\"injectedScriptId\":",
|
||||||
|
String16::fromInteger(InspectedContext::contextId(context)),
|
||||||
|
",\"id\":",
|
||||||
|
String16::fromInteger(
|
||||||
|
injectedScript->bindObject(bodyFunction, groupName)),
|
||||||
|
"}"));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
1009
src/inspector/injected-script-source.js
Normal file
1009
src/inspector/injected-script-source.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -30,26 +30,26 @@
|
|||||||
|
|
||||||
#include "src/inspector/injected-script.h"
|
#include "src/inspector/injected-script.h"
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
#include "src/inspector/custom-preview.h"
|
#include "src/inspector/custom-preview.h"
|
||||||
|
#include "src/inspector/injected-script-source.h"
|
||||||
#include "src/inspector/inspected-context.h"
|
#include "src/inspector/inspected-context.h"
|
||||||
#include "src/inspector/protocol/Protocol.h"
|
#include "src/inspector/protocol/Protocol.h"
|
||||||
#include "src/inspector/remote-object-id.h"
|
#include "src/inspector/remote-object-id.h"
|
||||||
#include "src/inspector/string-util.h"
|
#include "src/inspector/string-util.h"
|
||||||
#include "src/inspector/v8-console.h"
|
#include "src/inspector/v8-console.h"
|
||||||
|
#include "src/inspector/v8-function-call.h"
|
||||||
|
#include "src/inspector/v8-injected-script-host.h"
|
||||||
#include "src/inspector/v8-inspector-impl.h"
|
#include "src/inspector/v8-inspector-impl.h"
|
||||||
#include "src/inspector/v8-inspector-session-impl.h"
|
#include "src/inspector/v8-inspector-session-impl.h"
|
||||||
#include "src/inspector/v8-stack-trace-impl.h"
|
#include "src/inspector/v8-stack-trace-impl.h"
|
||||||
#include "src/inspector/v8-value-utils.h"
|
#include "src/inspector/v8-value-utils.h"
|
||||||
#include "src/inspector/value-mirror.h"
|
|
||||||
|
|
||||||
#include "include/v8-inspector.h"
|
#include "include/v8-inspector.h"
|
||||||
|
|
||||||
namespace v8_inspector {
|
namespace v8_inspector {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
static const char privateKeyName[] = "v8-inspector#injectedScript";
|
||||||
static const char kGlobalHandleLabel[] = "DevTools console";
|
static const char kGlobalHandleLabel[] = "DevTools console";
|
||||||
static bool isResolvableNumberLike(String16 query) {
|
static bool isResolvableNumberLike(String16 query) {
|
||||||
return query == "Infinity" || query == "-Infinity" || query == "NaN";
|
return query == "Infinity" || query == "-Infinity" || query == "NaN";
|
||||||
@ -67,7 +67,8 @@ class InjectedScript::ProtocolPromiseHandler {
|
|||||||
static bool add(V8InspectorSessionImpl* session,
|
static bool add(V8InspectorSessionImpl* session,
|
||||||
v8::Local<v8::Context> context, v8::Local<v8::Value> value,
|
v8::Local<v8::Context> context, v8::Local<v8::Value> value,
|
||||||
int executionContextId, const String16& objectGroup,
|
int executionContextId, const String16& objectGroup,
|
||||||
WrapMode wrapMode, EvaluateCallback* callback) {
|
bool returnByValue, bool generatePreview,
|
||||||
|
EvaluateCallback* callback) {
|
||||||
v8::Local<v8::Promise::Resolver> resolver;
|
v8::Local<v8::Promise::Resolver> resolver;
|
||||||
if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) {
|
if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) {
|
||||||
callback->sendFailure(Response::InternalError());
|
callback->sendFailure(Response::InternalError());
|
||||||
@ -80,8 +81,9 @@ class InjectedScript::ProtocolPromiseHandler {
|
|||||||
|
|
||||||
v8::Local<v8::Promise> promise = resolver->GetPromise();
|
v8::Local<v8::Promise> promise = resolver->GetPromise();
|
||||||
V8InspectorImpl* inspector = session->inspector();
|
V8InspectorImpl* inspector = session->inspector();
|
||||||
ProtocolPromiseHandler* handler = new ProtocolPromiseHandler(
|
ProtocolPromiseHandler* handler =
|
||||||
session, executionContextId, objectGroup, wrapMode, callback);
|
new ProtocolPromiseHandler(session, executionContextId, objectGroup,
|
||||||
|
returnByValue, generatePreview, callback);
|
||||||
v8::Local<v8::Value> wrapper = handler->m_wrapper.Get(inspector->isolate());
|
v8::Local<v8::Value> wrapper = handler->m_wrapper.Get(inspector->isolate());
|
||||||
v8::Local<v8::Function> thenCallbackFunction =
|
v8::Local<v8::Function> thenCallbackFunction =
|
||||||
v8::Function::New(context, thenCallback, wrapper, 0,
|
v8::Function::New(context, thenCallback, wrapper, 0,
|
||||||
@ -129,13 +131,15 @@ class InjectedScript::ProtocolPromiseHandler {
|
|||||||
|
|
||||||
ProtocolPromiseHandler(V8InspectorSessionImpl* session,
|
ProtocolPromiseHandler(V8InspectorSessionImpl* session,
|
||||||
int executionContextId, const String16& objectGroup,
|
int executionContextId, const String16& objectGroup,
|
||||||
WrapMode wrapMode, EvaluateCallback* callback)
|
bool returnByValue, bool generatePreview,
|
||||||
|
EvaluateCallback* callback)
|
||||||
: m_inspector(session->inspector()),
|
: m_inspector(session->inspector()),
|
||||||
m_sessionId(session->sessionId()),
|
m_sessionId(session->sessionId()),
|
||||||
m_contextGroupId(session->contextGroupId()),
|
m_contextGroupId(session->contextGroupId()),
|
||||||
m_executionContextId(executionContextId),
|
m_executionContextId(executionContextId),
|
||||||
m_objectGroup(objectGroup),
|
m_objectGroup(objectGroup),
|
||||||
m_wrapMode(wrapMode),
|
m_returnByValue(returnByValue),
|
||||||
|
m_generatePreview(generatePreview),
|
||||||
m_callback(std::move(callback)),
|
m_callback(std::move(callback)),
|
||||||
m_wrapper(m_inspector->isolate(),
|
m_wrapper(m_inspector->isolate(),
|
||||||
v8::External::New(m_inspector->isolate(), this)) {
|
v8::External::New(m_inspector->isolate(), this)) {
|
||||||
@ -167,8 +171,9 @@ class InjectedScript::ProtocolPromiseHandler {
|
|||||||
scope.injectedScript()->takeEvaluateCallback(m_callback);
|
scope.injectedScript()->takeEvaluateCallback(m_callback);
|
||||||
if (!callback) return;
|
if (!callback) return;
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue;
|
std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue;
|
||||||
response = scope.injectedScript()->wrapObject(result, m_objectGroup,
|
response = scope.injectedScript()->wrapObject(
|
||||||
m_wrapMode, &wrappedValue);
|
result, m_objectGroup, m_returnByValue, m_generatePreview,
|
||||||
|
&wrappedValue);
|
||||||
if (!response.isSuccess()) {
|
if (!response.isSuccess()) {
|
||||||
callback->sendFailure(response);
|
callback->sendFailure(response);
|
||||||
return;
|
return;
|
||||||
@ -188,8 +193,9 @@ class InjectedScript::ProtocolPromiseHandler {
|
|||||||
scope.injectedScript()->takeEvaluateCallback(m_callback);
|
scope.injectedScript()->takeEvaluateCallback(m_callback);
|
||||||
if (!callback) return;
|
if (!callback) return;
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue;
|
std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue;
|
||||||
response = scope.injectedScript()->wrapObject(result, m_objectGroup,
|
response = scope.injectedScript()->wrapObject(
|
||||||
m_wrapMode, &wrappedValue);
|
result, m_objectGroup, m_returnByValue, m_generatePreview,
|
||||||
|
&wrappedValue);
|
||||||
if (!response.isSuccess()) {
|
if (!response.isSuccess()) {
|
||||||
callback->sendFailure(response);
|
callback->sendFailure(response);
|
||||||
return;
|
return;
|
||||||
@ -247,127 +253,116 @@ class InjectedScript::ProtocolPromiseHandler {
|
|||||||
int m_contextGroupId;
|
int m_contextGroupId;
|
||||||
int m_executionContextId;
|
int m_executionContextId;
|
||||||
String16 m_objectGroup;
|
String16 m_objectGroup;
|
||||||
WrapMode m_wrapMode;
|
bool m_returnByValue;
|
||||||
|
bool m_generatePreview;
|
||||||
EvaluateCallback* m_callback;
|
EvaluateCallback* m_callback;
|
||||||
v8::Global<v8::External> m_wrapper;
|
v8::Global<v8::External> m_wrapper;
|
||||||
};
|
};
|
||||||
|
|
||||||
InjectedScript::InjectedScript(InspectedContext* context, int sessionId)
|
std::unique_ptr<InjectedScript> InjectedScript::create(
|
||||||
: m_context(context), m_sessionId(sessionId) {}
|
InspectedContext* inspectedContext, int sessionId) {
|
||||||
|
v8::Isolate* isolate = inspectedContext->isolate();
|
||||||
|
v8::HandleScope handles(isolate);
|
||||||
|
v8::TryCatch tryCatch(isolate);
|
||||||
|
v8::Local<v8::Context> context = inspectedContext->context();
|
||||||
|
v8::debug::PostponeInterruptsScope postponeInterrupts(isolate);
|
||||||
|
v8::Context::Scope scope(context);
|
||||||
|
v8::MicrotasksScope microtasksScope(isolate,
|
||||||
|
v8::MicrotasksScope::kDoNotRunMicrotasks);
|
||||||
|
|
||||||
|
// Inject javascript into the context. The compiled script is supposed to
|
||||||
|
// evaluate into
|
||||||
|
// a single anonymous function(it's anonymous to avoid cluttering the global
|
||||||
|
// object with
|
||||||
|
// inspector's stuff) the function is called a few lines below with
|
||||||
|
// InjectedScriptHost wrapper,
|
||||||
|
// injected script id and explicit reference to the inspected global object.
|
||||||
|
// The function is expected
|
||||||
|
// to create and configure InjectedScript instance that is going to be used by
|
||||||
|
// the inspector.
|
||||||
|
StringView injectedScriptSource(
|
||||||
|
reinterpret_cast<const uint8_t*>(InjectedScriptSource_js),
|
||||||
|
sizeof(InjectedScriptSource_js));
|
||||||
|
v8::Local<v8::Value> value;
|
||||||
|
if (!inspectedContext->inspector()
|
||||||
|
->compileAndRunInternalScript(
|
||||||
|
context, toV8String(isolate, injectedScriptSource))
|
||||||
|
.ToLocal(&value)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
DCHECK(value->IsFunction());
|
||||||
|
v8::Local<v8::Object> scriptHostWrapper =
|
||||||
|
V8InjectedScriptHost::create(context, inspectedContext->inspector());
|
||||||
|
v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value);
|
||||||
|
v8::Local<v8::Object> windowGlobal = context->Global();
|
||||||
|
v8::Local<v8::Value> info[] = {
|
||||||
|
scriptHostWrapper, windowGlobal,
|
||||||
|
v8::Number::New(isolate, inspectedContext->contextId())};
|
||||||
|
|
||||||
|
int contextGroupId = inspectedContext->contextGroupId();
|
||||||
|
int contextId = inspectedContext->contextId();
|
||||||
|
V8InspectorImpl* inspector = inspectedContext->inspector();
|
||||||
|
v8::Local<v8::Value> injectedScriptValue;
|
||||||
|
if (!function->Call(context, windowGlobal, arraysize(info), info)
|
||||||
|
.ToLocal(&injectedScriptValue))
|
||||||
|
return nullptr;
|
||||||
|
if (inspector->getContext(contextGroupId, contextId) != inspectedContext)
|
||||||
|
return nullptr;
|
||||||
|
if (!injectedScriptValue->IsObject()) return nullptr;
|
||||||
|
|
||||||
|
std::unique_ptr<InjectedScript> injectedScript(new InjectedScript(
|
||||||
|
inspectedContext, injectedScriptValue.As<v8::Object>(), sessionId));
|
||||||
|
v8::Local<v8::Private> privateKey = v8::Private::ForApi(
|
||||||
|
isolate, v8::String::NewFromUtf8(isolate, privateKeyName,
|
||||||
|
v8::NewStringType::kInternalized)
|
||||||
|
.ToLocalChecked());
|
||||||
|
scriptHostWrapper->SetPrivate(
|
||||||
|
context, privateKey, v8::External::New(isolate, injectedScript.get()));
|
||||||
|
return injectedScript;
|
||||||
|
}
|
||||||
|
|
||||||
|
InjectedScript::InjectedScript(InspectedContext* context,
|
||||||
|
v8::Local<v8::Object> object, int sessionId)
|
||||||
|
: m_context(context),
|
||||||
|
m_value(context->isolate(), object),
|
||||||
|
m_sessionId(sessionId) {}
|
||||||
|
|
||||||
InjectedScript::~InjectedScript() { discardEvaluateCallbacks(); }
|
InjectedScript::~InjectedScript() { discardEvaluateCallbacks(); }
|
||||||
|
|
||||||
namespace {
|
|
||||||
class PropertyAccumulator : public ValueMirror::PropertyAccumulator {
|
|
||||||
public:
|
|
||||||
explicit PropertyAccumulator(std::vector<PropertyMirror>* mirrors)
|
|
||||||
: m_mirrors(mirrors) {}
|
|
||||||
bool Add(PropertyMirror mirror) override {
|
|
||||||
m_mirrors->push_back(std::move(mirror));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<PropertyMirror>* m_mirrors;
|
|
||||||
};
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
Response InjectedScript::getProperties(
|
Response InjectedScript::getProperties(
|
||||||
v8::Local<v8::Object> object, const String16& groupName, bool ownProperties,
|
v8::Local<v8::Object> object, const String16& groupName, bool ownProperties,
|
||||||
bool accessorPropertiesOnly, WrapMode wrapMode,
|
bool accessorPropertiesOnly, bool generatePreview,
|
||||||
std::unique_ptr<Array<PropertyDescriptor>>* properties,
|
std::unique_ptr<Array<PropertyDescriptor>>* properties,
|
||||||
Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
|
Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
|
||||||
v8::HandleScope handles(m_context->isolate());
|
v8::HandleScope handles(m_context->isolate());
|
||||||
v8::Local<v8::Context> context = m_context->context();
|
v8::Local<v8::Context> context = m_context->context();
|
||||||
v8::Isolate* isolate = m_context->isolate();
|
V8FunctionCall function(m_context->inspector(), m_context->context(),
|
||||||
v8::TryCatch tryCatch(isolate);
|
v8Value(), "getProperties");
|
||||||
|
function.appendArgument(object);
|
||||||
|
function.appendArgument(groupName);
|
||||||
|
function.appendArgument(ownProperties);
|
||||||
|
function.appendArgument(accessorPropertiesOnly);
|
||||||
|
function.appendArgument(generatePreview);
|
||||||
|
|
||||||
*properties = Array<PropertyDescriptor>::create();
|
v8::TryCatch tryCatch(m_context->isolate());
|
||||||
std::vector<PropertyMirror> mirrors;
|
v8::Local<v8::Value> resultValue = function.callWithoutExceptionHandling();
|
||||||
PropertyAccumulator accumulator(&mirrors);
|
if (tryCatch.HasCaught()) {
|
||||||
if (!ValueMirror::getProperties(context, object, ownProperties,
|
Response response = createExceptionDetails(
|
||||||
accessorPropertiesOnly, &accumulator)) {
|
tryCatch, groupName, generatePreview, exceptionDetails);
|
||||||
return createExceptionDetails(tryCatch, groupName, wrapMode,
|
|
||||||
exceptionDetails);
|
|
||||||
}
|
|
||||||
for (const PropertyMirror& mirror : mirrors) {
|
|
||||||
std::unique_ptr<PropertyDescriptor> descriptor =
|
|
||||||
PropertyDescriptor::create()
|
|
||||||
.setName(mirror.name)
|
|
||||||
.setConfigurable(mirror.configurable)
|
|
||||||
.setEnumerable(mirror.enumerable)
|
|
||||||
.setIsOwn(mirror.isOwn)
|
|
||||||
.build();
|
|
||||||
Response response;
|
|
||||||
std::unique_ptr<RemoteObject> remoteObject;
|
|
||||||
if (mirror.value) {
|
|
||||||
response =
|
|
||||||
mirror.value->buildRemoteObject(context, wrapMode, &remoteObject);
|
|
||||||
if (!response.isSuccess()) return response;
|
|
||||||
bindRemoteObjectIfNeeded(mirror.value->v8Value(), groupName,
|
|
||||||
remoteObject.get());
|
|
||||||
descriptor->setValue(std::move(remoteObject));
|
|
||||||
descriptor->setWritable(mirror.writable);
|
|
||||||
}
|
|
||||||
if (mirror.getter) {
|
|
||||||
response =
|
|
||||||
mirror.getter->buildRemoteObject(context, wrapMode, &remoteObject);
|
|
||||||
if (!response.isSuccess()) return response;
|
|
||||||
bindRemoteObjectIfNeeded(mirror.getter->v8Value(), groupName,
|
|
||||||
remoteObject.get());
|
|
||||||
descriptor->setGet(std::move(remoteObject));
|
|
||||||
}
|
|
||||||
if (mirror.setter) {
|
|
||||||
response =
|
|
||||||
mirror.setter->buildRemoteObject(context, wrapMode, &remoteObject);
|
|
||||||
if (!response.isSuccess()) return response;
|
|
||||||
bindRemoteObjectIfNeeded(mirror.setter->v8Value(), groupName,
|
|
||||||
remoteObject.get());
|
|
||||||
descriptor->setSet(std::move(remoteObject));
|
|
||||||
}
|
|
||||||
if (mirror.symbol) {
|
|
||||||
response =
|
|
||||||
mirror.symbol->buildRemoteObject(context, wrapMode, &remoteObject);
|
|
||||||
if (!response.isSuccess()) return response;
|
|
||||||
bindRemoteObjectIfNeeded(mirror.symbol->v8Value(), groupName,
|
|
||||||
remoteObject.get());
|
|
||||||
descriptor->setSymbol(std::move(remoteObject));
|
|
||||||
}
|
|
||||||
if (mirror.exception) {
|
|
||||||
response =
|
|
||||||
mirror.exception->buildRemoteObject(context, wrapMode, &remoteObject);
|
|
||||||
if (!response.isSuccess()) return response;
|
|
||||||
bindRemoteObjectIfNeeded(mirror.exception->v8Value(), groupName,
|
|
||||||
remoteObject.get());
|
|
||||||
descriptor->setValue(std::move(remoteObject));
|
|
||||||
descriptor->setWasThrown(true);
|
|
||||||
}
|
|
||||||
(*properties)->addItem(std::move(descriptor));
|
|
||||||
}
|
|
||||||
return Response::OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
Response InjectedScript::getInternalProperties(
|
|
||||||
v8::Local<v8::Value> value, const String16& groupName,
|
|
||||||
std::unique_ptr<protocol::Array<InternalPropertyDescriptor>>* result) {
|
|
||||||
*result = protocol::Array<InternalPropertyDescriptor>::create();
|
|
||||||
std::vector<InternalPropertyMirror> wrappers;
|
|
||||||
if (value->IsObject()) {
|
|
||||||
ValueMirror::getInternalProperties(m_context->context(),
|
|
||||||
value.As<v8::Object>(), &wrappers);
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < wrappers.size(); ++i) {
|
|
||||||
std::unique_ptr<RemoteObject> remoteObject;
|
|
||||||
Response response = wrappers[i].value->buildRemoteObject(
|
|
||||||
m_context->context(), WrapMode::kNoPreview, &remoteObject);
|
|
||||||
if (!response.isSuccess()) return response;
|
if (!response.isSuccess()) return response;
|
||||||
bindRemoteObjectIfNeeded(wrappers[i].value->v8Value(), groupName,
|
// FIXME: make properties optional
|
||||||
remoteObject.get());
|
*properties = Array<PropertyDescriptor>::create();
|
||||||
(*result)->addItem(InternalPropertyDescriptor::create()
|
return Response::OK();
|
||||||
.setName(wrappers[i].name)
|
|
||||||
.setValue(std::move(remoteObject))
|
|
||||||
.build());
|
|
||||||
}
|
}
|
||||||
|
if (resultValue.IsEmpty()) return Response::InternalError();
|
||||||
|
std::unique_ptr<protocol::Value> protocolValue;
|
||||||
|
Response response = toProtocolValue(context, resultValue, &protocolValue);
|
||||||
|
if (!response.isSuccess()) return response;
|
||||||
|
protocol::ErrorSupport errors;
|
||||||
|
std::unique_ptr<Array<PropertyDescriptor>> result =
|
||||||
|
Array<PropertyDescriptor>::fromValue(protocolValue.get(), &errors);
|
||||||
|
if (errors.hasErrors()) return Response::Error(errors.errors());
|
||||||
|
*properties = std::move(result);
|
||||||
return Response::OK();
|
return Response::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,25 +379,37 @@ void InjectedScript::releaseObject(const String16& objectId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Response InjectedScript::wrapObject(
|
Response InjectedScript::wrapObject(
|
||||||
v8::Local<v8::Value> value, const String16& groupName, WrapMode wrapMode,
|
v8::Local<v8::Value> value, const String16& groupName, bool forceValueType,
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject>* result) {
|
bool generatePreview,
|
||||||
return wrapObject(value, groupName, wrapMode, v8::MaybeLocal<v8::Value>(),
|
std::unique_ptr<protocol::Runtime::RemoteObject>* result) const {
|
||||||
kMaxCustomPreviewDepth, result);
|
return wrapObject(value, groupName, forceValueType, generatePreview,
|
||||||
|
v8::MaybeLocal<v8::Value>(), kMaxCustomPreviewDepth,
|
||||||
|
result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Response InjectedScript::wrapObject(
|
Response InjectedScript::wrapObject(
|
||||||
v8::Local<v8::Value> value, const String16& groupName, WrapMode wrapMode,
|
v8::Local<v8::Value> value, const String16& groupName, bool forceValueType,
|
||||||
v8::MaybeLocal<v8::Value> customPreviewConfig, int maxCustomPreviewDepth,
|
bool generatePreview, v8::MaybeLocal<v8::Value> customPreviewConfig,
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject>* result) {
|
int maxCustomPreviewDepth,
|
||||||
|
std::unique_ptr<protocol::Runtime::RemoteObject>* result) const {
|
||||||
|
v8::HandleScope handles(m_context->isolate());
|
||||||
|
v8::Local<v8::Value> wrappedObject;
|
||||||
v8::Local<v8::Context> context = m_context->context();
|
v8::Local<v8::Context> context = m_context->context();
|
||||||
v8::Context::Scope contextScope(context);
|
|
||||||
int customPreviewEnabled = m_customPreviewEnabled;
|
int customPreviewEnabled = m_customPreviewEnabled;
|
||||||
int sessionId = m_sessionId;
|
int sessionId = m_sessionId;
|
||||||
auto obj = ValueMirror::create(m_context->context(), value);
|
|
||||||
if (!obj) return Response::InternalError();
|
Response response = wrapValue(value, groupName, forceValueType,
|
||||||
Response response = obj->buildRemoteObject(context, wrapMode, result);
|
generatePreview, &wrappedObject);
|
||||||
if (!response.isSuccess()) return response;
|
if (!response.isSuccess()) return response;
|
||||||
bindRemoteObjectIfNeeded(value, groupName, result->get());
|
protocol::ErrorSupport errors;
|
||||||
|
std::unique_ptr<protocol::Value> protocolValue;
|
||||||
|
response = toProtocolValue(context, wrappedObject, &protocolValue);
|
||||||
|
if (!response.isSuccess()) return response;
|
||||||
|
|
||||||
|
*result =
|
||||||
|
protocol::Runtime::RemoteObject::fromValue(protocolValue.get(), &errors);
|
||||||
|
if (!result->get()) return Response::Error(errors.errors());
|
||||||
if (customPreviewEnabled && value->IsObject()) {
|
if (customPreviewEnabled && value->IsObject()) {
|
||||||
std::unique_ptr<protocol::Runtime::CustomPreview> customPreview;
|
std::unique_ptr<protocol::Runtime::CustomPreview> customPreview;
|
||||||
generateCustomPreview(sessionId, groupName, context, value.As<v8::Object>(),
|
generateCustomPreview(sessionId, groupName, context, value.As<v8::Object>(),
|
||||||
@ -413,65 +420,47 @@ Response InjectedScript::wrapObject(
|
|||||||
return Response::OK();
|
return Response::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Response InjectedScript::wrapValue(v8::Local<v8::Value> value,
|
||||||
|
const String16& groupName,
|
||||||
|
bool forceValueType, bool generatePreview,
|
||||||
|
v8::Local<v8::Value>* result) const {
|
||||||
|
V8FunctionCall function(m_context->inspector(), m_context->context(),
|
||||||
|
v8Value(), "wrapObject");
|
||||||
|
function.appendArgument(value);
|
||||||
|
function.appendArgument(groupName);
|
||||||
|
function.appendArgument(forceValueType);
|
||||||
|
function.appendArgument(generatePreview);
|
||||||
|
bool hadException = false;
|
||||||
|
*result = function.call(hadException);
|
||||||
|
if (hadException || result->IsEmpty()) return Response::InternalError();
|
||||||
|
return Response::OK();
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapTable(
|
std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapTable(
|
||||||
v8::Local<v8::Object> table, v8::MaybeLocal<v8::Array> maybeColumns) {
|
v8::Local<v8::Value> table, v8::Local<v8::Value> columns) const {
|
||||||
using protocol::Runtime::RemoteObject;
|
v8::HandleScope handles(m_context->isolate());
|
||||||
using protocol::Runtime::ObjectPreview;
|
|
||||||
using protocol::Runtime::PropertyPreview;
|
|
||||||
using protocol::Array;
|
|
||||||
|
|
||||||
v8::Isolate* isolate = m_context->isolate();
|
|
||||||
v8::HandleScope handles(isolate);
|
|
||||||
v8::Local<v8::Context> context = m_context->context();
|
v8::Local<v8::Context> context = m_context->context();
|
||||||
|
V8FunctionCall function(m_context->inspector(), context, v8Value(),
|
||||||
std::unique_ptr<RemoteObject> remoteObject;
|
"wrapTable");
|
||||||
Response response =
|
function.appendArgument(table);
|
||||||
wrapObject(table, "console", WrapMode::kNoPreview, &remoteObject);
|
if (columns.IsEmpty())
|
||||||
if (!remoteObject || !response.isSuccess()) return nullptr;
|
function.appendArgument(false);
|
||||||
|
else
|
||||||
auto mirror = ValueMirror::create(context, table);
|
function.appendArgument(columns);
|
||||||
std::unique_ptr<ObjectPreview> preview;
|
bool hadException = false;
|
||||||
int limit = 100;
|
v8::Local<v8::Value> r = function.call(hadException);
|
||||||
mirror->buildObjectPreview(context, true /* generatePreviewForProperties */,
|
if (hadException || r.IsEmpty()) return nullptr;
|
||||||
&limit, &limit, &preview);
|
std::unique_ptr<protocol::Value> protocolValue;
|
||||||
|
Response response = toProtocolValue(context, r, &protocolValue);
|
||||||
Array<PropertyPreview>* columns = preview->getProperties();
|
if (!response.isSuccess()) return nullptr;
|
||||||
std::unordered_set<String16> selectedColumns;
|
protocol::ErrorSupport errors;
|
||||||
v8::Local<v8::Array> v8Columns;
|
return protocol::Runtime::RemoteObject::fromValue(protocolValue.get(),
|
||||||
if (maybeColumns.ToLocal(&v8Columns)) {
|
&errors);
|
||||||
for (uint32_t i = 0; i < v8Columns->Length(); ++i) {
|
|
||||||
v8::Local<v8::Value> column;
|
|
||||||
if (v8Columns->Get(context, i).ToLocal(&column) && column->IsString()) {
|
|
||||||
selectedColumns.insert(
|
|
||||||
toProtocolString(isolate, column.As<v8::String>()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!selectedColumns.empty()) {
|
|
||||||
for (size_t i = 0; i < columns->length(); ++i) {
|
|
||||||
ObjectPreview* columnPreview = columns->get(i)->getValuePreview(nullptr);
|
|
||||||
if (!columnPreview) continue;
|
|
||||||
|
|
||||||
std::unique_ptr<Array<PropertyPreview>> filtered =
|
|
||||||
Array<PropertyPreview>::create();
|
|
||||||
Array<PropertyPreview>* columns = columnPreview->getProperties();
|
|
||||||
for (size_t j = 0; j < columns->length(); ++j) {
|
|
||||||
PropertyPreview* property = columns->get(j);
|
|
||||||
if (selectedColumns.find(property->getName()) !=
|
|
||||||
selectedColumns.end()) {
|
|
||||||
filtered->addItem(property->clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
columnPreview->setProperties(std::move(filtered));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
remoteObject->setPreview(std::move(preview));
|
|
||||||
return remoteObject;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectedScript::addPromiseCallback(
|
void InjectedScript::addPromiseCallback(
|
||||||
V8InspectorSessionImpl* session, v8::MaybeLocal<v8::Value> value,
|
V8InspectorSessionImpl* session, v8::MaybeLocal<v8::Value> value,
|
||||||
const String16& objectGroup, WrapMode wrapMode,
|
const String16& objectGroup, bool returnByValue, bool generatePreview,
|
||||||
std::unique_ptr<EvaluateCallback> callback) {
|
std::unique_ptr<EvaluateCallback> callback) {
|
||||||
if (value.IsEmpty()) {
|
if (value.IsEmpty()) {
|
||||||
callback->sendFailure(Response::InternalError());
|
callback->sendFailure(Response::InternalError());
|
||||||
@ -481,7 +470,8 @@ void InjectedScript::addPromiseCallback(
|
|||||||
v8::MicrotasksScope::kRunMicrotasks);
|
v8::MicrotasksScope::kRunMicrotasks);
|
||||||
if (ProtocolPromiseHandler::add(
|
if (ProtocolPromiseHandler::add(
|
||||||
session, m_context->context(), value.ToLocalChecked(),
|
session, m_context->context(), value.ToLocalChecked(),
|
||||||
m_context->contextId(), objectGroup, wrapMode, callback.get())) {
|
m_context->contextId(), objectGroup, returnByValue, generatePreview,
|
||||||
|
callback.get())) {
|
||||||
m_evaluateCallbacks.insert(callback.release());
|
m_evaluateCallbacks.insert(callback.release());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -531,6 +521,10 @@ void InjectedScript::setCustomObjectFormatterEnabled(bool enabled) {
|
|||||||
m_customPreviewEnabled = enabled;
|
m_customPreviewEnabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Value> InjectedScript::v8Value() const {
|
||||||
|
return m_value.Get(m_context->isolate());
|
||||||
|
}
|
||||||
|
|
||||||
v8::Local<v8::Value> InjectedScript::lastEvaluationResult() const {
|
v8::Local<v8::Value> InjectedScript::lastEvaluationResult() const {
|
||||||
if (m_lastEvaluationResult.IsEmpty())
|
if (m_lastEvaluationResult.IsEmpty())
|
||||||
return v8::Undefined(m_context->isolate());
|
return v8::Undefined(m_context->isolate());
|
||||||
@ -582,7 +576,7 @@ Response InjectedScript::resolveCallArgument(
|
|||||||
|
|
||||||
Response InjectedScript::createExceptionDetails(
|
Response InjectedScript::createExceptionDetails(
|
||||||
const v8::TryCatch& tryCatch, const String16& objectGroup,
|
const v8::TryCatch& tryCatch, const String16& objectGroup,
|
||||||
WrapMode wrapMode, Maybe<protocol::Runtime::ExceptionDetails>* result) {
|
bool generatePreview, Maybe<protocol::Runtime::ExceptionDetails>* result) {
|
||||||
if (!tryCatch.HasCaught()) return Response::InternalError();
|
if (!tryCatch.HasCaught()) return Response::InternalError();
|
||||||
v8::Local<v8::Message> message = tryCatch.Message();
|
v8::Local<v8::Message> message = tryCatch.Message();
|
||||||
v8::Local<v8::Value> exception = tryCatch.Exception();
|
v8::Local<v8::Value> exception = tryCatch.Exception();
|
||||||
@ -618,10 +612,8 @@ Response InjectedScript::createExceptionDetails(
|
|||||||
if (!exception.IsEmpty()) {
|
if (!exception.IsEmpty()) {
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject> wrapped;
|
std::unique_ptr<protocol::Runtime::RemoteObject> wrapped;
|
||||||
Response response =
|
Response response =
|
||||||
wrapObject(exception, objectGroup,
|
wrapObject(exception, objectGroup, false /* forceValueType */,
|
||||||
exception->IsNativeError() ? WrapMode::kNoPreview
|
generatePreview && !exception->IsNativeError(), &wrapped);
|
||||||
: WrapMode::kWithPreview,
|
|
||||||
&wrapped);
|
|
||||||
if (!response.isSuccess()) return response;
|
if (!response.isSuccess()) return response;
|
||||||
exceptionDetails->setException(std::move(wrapped));
|
exceptionDetails->setException(std::move(wrapped));
|
||||||
}
|
}
|
||||||
@ -631,14 +623,15 @@ Response InjectedScript::createExceptionDetails(
|
|||||||
|
|
||||||
Response InjectedScript::wrapEvaluateResult(
|
Response InjectedScript::wrapEvaluateResult(
|
||||||
v8::MaybeLocal<v8::Value> maybeResultValue, const v8::TryCatch& tryCatch,
|
v8::MaybeLocal<v8::Value> maybeResultValue, const v8::TryCatch& tryCatch,
|
||||||
const String16& objectGroup, WrapMode wrapMode,
|
const String16& objectGroup, bool returnByValue, bool generatePreview,
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject>* result,
|
std::unique_ptr<protocol::Runtime::RemoteObject>* result,
|
||||||
Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
|
Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
|
||||||
v8::Local<v8::Value> resultValue;
|
v8::Local<v8::Value> resultValue;
|
||||||
if (!tryCatch.HasCaught()) {
|
if (!tryCatch.HasCaught()) {
|
||||||
if (!maybeResultValue.ToLocal(&resultValue))
|
if (!maybeResultValue.ToLocal(&resultValue))
|
||||||
return Response::InternalError();
|
return Response::InternalError();
|
||||||
Response response = wrapObject(resultValue, objectGroup, wrapMode, result);
|
Response response = wrapObject(resultValue, objectGroup, returnByValue,
|
||||||
|
generatePreview, result);
|
||||||
if (!response.isSuccess()) return response;
|
if (!response.isSuccess()) return response;
|
||||||
if (objectGroup == "console") {
|
if (objectGroup == "console") {
|
||||||
m_lastEvaluationResult.Reset(m_context->isolate(), resultValue);
|
m_lastEvaluationResult.Reset(m_context->isolate(), resultValue);
|
||||||
@ -650,14 +643,12 @@ Response InjectedScript::wrapEvaluateResult(
|
|||||||
}
|
}
|
||||||
v8::Local<v8::Value> exception = tryCatch.Exception();
|
v8::Local<v8::Value> exception = tryCatch.Exception();
|
||||||
Response response =
|
Response response =
|
||||||
wrapObject(exception, objectGroup,
|
wrapObject(exception, objectGroup, false,
|
||||||
exception->IsNativeError() ? WrapMode::kNoPreview
|
generatePreview && !exception->IsNativeError(), result);
|
||||||
: WrapMode::kWithPreview,
|
|
||||||
result);
|
|
||||||
if (!response.isSuccess()) return response;
|
if (!response.isSuccess()) return response;
|
||||||
// We send exception in result for compatibility reasons, even though it's
|
// We send exception in result for compatibility reasons, even though it's
|
||||||
// accessible through exceptionDetails.exception.
|
// accessible through exceptionDetails.exception.
|
||||||
response = createExceptionDetails(tryCatch, objectGroup, wrapMode,
|
response = createExceptionDetails(tryCatch, objectGroup, generatePreview,
|
||||||
exceptionDetails);
|
exceptionDetails);
|
||||||
if (!response.isSuccess()) return response;
|
if (!response.isSuccess()) return response;
|
||||||
}
|
}
|
||||||
@ -806,31 +797,33 @@ Response InjectedScript::CallFrameScope::findInjectedScript(
|
|||||||
return session->findInjectedScript(remoteId.get(), m_injectedScript);
|
return session->findInjectedScript(remoteId.get(), m_injectedScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
String16 InjectedScript::bindObject(v8::Local<v8::Value> value,
|
InjectedScript* InjectedScript::fromInjectedScriptHost(
|
||||||
const String16& groupName) {
|
v8::Isolate* isolate, v8::Local<v8::Object> injectedScriptObject) {
|
||||||
|
v8::HandleScope handleScope(isolate);
|
||||||
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||||
|
v8::Local<v8::Private> privateKey = v8::Private::ForApi(
|
||||||
|
isolate, v8::String::NewFromUtf8(isolate, privateKeyName,
|
||||||
|
v8::NewStringType::kInternalized)
|
||||||
|
.ToLocalChecked());
|
||||||
|
v8::Local<v8::Value> value =
|
||||||
|
injectedScriptObject->GetPrivate(context, privateKey).ToLocalChecked();
|
||||||
|
DCHECK(value->IsExternal());
|
||||||
|
v8::Local<v8::External> external = value.As<v8::External>();
|
||||||
|
return static_cast<InjectedScript*>(external->Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
int InjectedScript::bindObject(v8::Local<v8::Value> value,
|
||||||
|
const String16& groupName) {
|
||||||
if (m_lastBoundObjectId <= 0) m_lastBoundObjectId = 1;
|
if (m_lastBoundObjectId <= 0) m_lastBoundObjectId = 1;
|
||||||
int id = m_lastBoundObjectId++;
|
int id = m_lastBoundObjectId++;
|
||||||
m_idToWrappedObject[id].Reset(m_context->isolate(), value);
|
m_idToWrappedObject[id].Reset(m_context->isolate(), value);
|
||||||
m_idToWrappedObject[id].AnnotateStrongRetainer(kGlobalHandleLabel);
|
m_idToWrappedObject[id].AnnotateStrongRetainer(kGlobalHandleLabel);
|
||||||
|
|
||||||
if (!groupName.isEmpty() && id > 0) {
|
if (!groupName.isEmpty() && id > 0) {
|
||||||
m_idToObjectGroupName[id] = groupName;
|
m_idToObjectGroupName[id] = groupName;
|
||||||
m_nameToObjectGroup[groupName].push_back(id);
|
m_nameToObjectGroup[groupName].push_back(id);
|
||||||
}
|
}
|
||||||
// TODO(dgozman): get rid of "injectedScript" notion.
|
return id;
|
||||||
return String16::concat(
|
|
||||||
"{\"injectedScriptId\":", String16::fromInteger(m_context->contextId()),
|
|
||||||
",\"id\":", String16::fromInteger(id), "}");
|
|
||||||
}
|
|
||||||
|
|
||||||
void InjectedScript::bindRemoteObjectIfNeeded(
|
|
||||||
v8::Local<v8::Value> value, const String16& groupName,
|
|
||||||
protocol::Runtime::RemoteObject* remoteObject) {
|
|
||||||
if (!remoteObject) return;
|
|
||||||
if (remoteObject->hasValue()) return;
|
|
||||||
if (remoteObject->hasUnserializableValue()) return;
|
|
||||||
if (remoteObject->getType() != RemoteObject::TypeEnum::Undefined) {
|
|
||||||
remoteObject->setObjectId(bindObject(value, groupName));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectedScript::unbindObject(int id) {
|
void InjectedScript::unbindObject(int id) {
|
||||||
|
@ -46,9 +46,9 @@
|
|||||||
namespace v8_inspector {
|
namespace v8_inspector {
|
||||||
|
|
||||||
class RemoteObjectId;
|
class RemoteObjectId;
|
||||||
|
class V8FunctionCall;
|
||||||
class V8InspectorImpl;
|
class V8InspectorImpl;
|
||||||
class V8InspectorSessionImpl;
|
class V8InspectorSessionImpl;
|
||||||
enum class WrapMode;
|
|
||||||
|
|
||||||
using protocol::Maybe;
|
using protocol::Maybe;
|
||||||
using protocol::Response;
|
using protocol::Response;
|
||||||
@ -65,40 +65,38 @@ class EvaluateCallback {
|
|||||||
|
|
||||||
class InjectedScript final {
|
class InjectedScript final {
|
||||||
public:
|
public:
|
||||||
InjectedScript(InspectedContext*, int sessionId);
|
static std::unique_ptr<InjectedScript> create(InspectedContext*,
|
||||||
|
int sessionId);
|
||||||
~InjectedScript();
|
~InjectedScript();
|
||||||
|
static InjectedScript* fromInjectedScriptHost(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::Object>);
|
||||||
|
|
||||||
InspectedContext* context() const { return m_context; }
|
InspectedContext* context() const { return m_context; }
|
||||||
|
|
||||||
Response getProperties(
|
Response getProperties(
|
||||||
v8::Local<v8::Object>, const String16& groupName, bool ownProperties,
|
v8::Local<v8::Object>, const String16& groupName, bool ownProperties,
|
||||||
bool accessorPropertiesOnly, WrapMode wrapMode,
|
bool accessorPropertiesOnly, bool generatePreview,
|
||||||
std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>*
|
std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>*
|
||||||
result,
|
result,
|
||||||
Maybe<protocol::Runtime::ExceptionDetails>*);
|
Maybe<protocol::Runtime::ExceptionDetails>*);
|
||||||
|
|
||||||
Response getInternalProperties(
|
|
||||||
v8::Local<v8::Value>, const String16& groupName,
|
|
||||||
std::unique_ptr<
|
|
||||||
protocol::Array<protocol::Runtime::InternalPropertyDescriptor>>*
|
|
||||||
result);
|
|
||||||
|
|
||||||
void releaseObject(const String16& objectId);
|
void releaseObject(const String16& objectId);
|
||||||
|
|
||||||
Response wrapObject(v8::Local<v8::Value>, const String16& groupName,
|
Response wrapObject(
|
||||||
WrapMode wrapMode,
|
v8::Local<v8::Value>, const String16& groupName, bool forceValueType,
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject>* result);
|
bool generatePreview,
|
||||||
Response wrapObject(v8::Local<v8::Value>, const String16& groupName,
|
std::unique_ptr<protocol::Runtime::RemoteObject>* result) const;
|
||||||
WrapMode wrapMode,
|
Response wrapObject(
|
||||||
v8::MaybeLocal<v8::Value> customPreviewConfig,
|
v8::Local<v8::Value>, const String16& groupName, bool forceValueType,
|
||||||
int maxCustomPreviewDepth,
|
bool generatePreview, v8::MaybeLocal<v8::Value> customPreviewConfig,
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject>* result);
|
int maxCustomPreviewDepth,
|
||||||
|
std::unique_ptr<protocol::Runtime::RemoteObject>* result) const;
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject> wrapTable(
|
std::unique_ptr<protocol::Runtime::RemoteObject> wrapTable(
|
||||||
v8::Local<v8::Object> table, v8::MaybeLocal<v8::Array> columns);
|
v8::Local<v8::Value> table, v8::Local<v8::Value> columns) const;
|
||||||
|
|
||||||
void addPromiseCallback(V8InspectorSessionImpl* session,
|
void addPromiseCallback(V8InspectorSessionImpl* session,
|
||||||
v8::MaybeLocal<v8::Value> value,
|
v8::MaybeLocal<v8::Value> value,
|
||||||
const String16& objectGroup, WrapMode wrapMode,
|
const String16& objectGroup, bool returnByValue,
|
||||||
|
bool generatePreview,
|
||||||
std::unique_ptr<EvaluateCallback> callback);
|
std::unique_ptr<EvaluateCallback> callback);
|
||||||
|
|
||||||
Response findObject(const RemoteObjectId&, v8::Local<v8::Value>*) const;
|
Response findObject(const RemoteObjectId&, v8::Local<v8::Value>*) const;
|
||||||
@ -109,16 +107,18 @@ class InjectedScript final {
|
|||||||
v8::Local<v8::Value>* result);
|
v8::Local<v8::Value>* result);
|
||||||
|
|
||||||
Response createExceptionDetails(
|
Response createExceptionDetails(
|
||||||
const v8::TryCatch&, const String16& groupName, WrapMode wrapMode,
|
const v8::TryCatch&, const String16& groupName, bool generatePreview,
|
||||||
Maybe<protocol::Runtime::ExceptionDetails>* result);
|
Maybe<protocol::Runtime::ExceptionDetails>* result);
|
||||||
Response wrapEvaluateResult(
|
Response wrapEvaluateResult(
|
||||||
v8::MaybeLocal<v8::Value> maybeResultValue, const v8::TryCatch&,
|
v8::MaybeLocal<v8::Value> maybeResultValue, const v8::TryCatch&,
|
||||||
const String16& objectGroup, WrapMode wrapMode,
|
const String16& objectGroup, bool returnByValue, bool generatePreview,
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject>* result,
|
std::unique_ptr<protocol::Runtime::RemoteObject>* result,
|
||||||
Maybe<protocol::Runtime::ExceptionDetails>*);
|
Maybe<protocol::Runtime::ExceptionDetails>*);
|
||||||
v8::Local<v8::Value> lastEvaluationResult() const;
|
v8::Local<v8::Value> lastEvaluationResult() const;
|
||||||
void setLastEvaluationResult(v8::Local<v8::Value> result);
|
void setLastEvaluationResult(v8::Local<v8::Value> result);
|
||||||
|
|
||||||
|
int bindObject(v8::Local<v8::Value>, const String16& groupName);
|
||||||
|
|
||||||
class Scope {
|
class Scope {
|
||||||
public:
|
public:
|
||||||
Response initialize();
|
Response initialize();
|
||||||
@ -196,21 +196,23 @@ class InjectedScript final {
|
|||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CallFrameScope);
|
DISALLOW_COPY_AND_ASSIGN(CallFrameScope);
|
||||||
};
|
};
|
||||||
String16 bindObject(v8::Local<v8::Value>, const String16& groupName);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
InjectedScript(InspectedContext*, v8::Local<v8::Object>, int sessionId);
|
||||||
|
v8::Local<v8::Value> v8Value() const;
|
||||||
|
Response wrapValue(v8::Local<v8::Value>, const String16& groupName,
|
||||||
|
bool forceValueType, bool generatePreview,
|
||||||
|
v8::Local<v8::Value>* result) const;
|
||||||
v8::Local<v8::Object> commandLineAPI();
|
v8::Local<v8::Object> commandLineAPI();
|
||||||
void unbindObject(int id);
|
void unbindObject(int id);
|
||||||
|
|
||||||
void bindRemoteObjectIfNeeded(v8::Local<v8::Value>, const String16& groupName,
|
|
||||||
protocol::Runtime::RemoteObject* remoteObject);
|
|
||||||
|
|
||||||
class ProtocolPromiseHandler;
|
class ProtocolPromiseHandler;
|
||||||
void discardEvaluateCallbacks();
|
void discardEvaluateCallbacks();
|
||||||
std::unique_ptr<EvaluateCallback> takeEvaluateCallback(
|
std::unique_ptr<EvaluateCallback> takeEvaluateCallback(
|
||||||
EvaluateCallback* callback);
|
EvaluateCallback* callback);
|
||||||
|
|
||||||
InspectedContext* m_context;
|
InspectedContext* m_context;
|
||||||
|
v8::Global<v8::Value> m_value;
|
||||||
int m_sessionId;
|
int m_sessionId;
|
||||||
v8::Global<v8::Value> m_lastEvaluationResult;
|
v8::Global<v8::Value> m_lastEvaluationResult;
|
||||||
v8::Global<v8::Object> m_commandLineAPI;
|
v8::Global<v8::Object> m_commandLineAPI;
|
||||||
|
122
src/inspector/injected_script_externs.js
Normal file
122
src/inspector/injected_script_externs.js
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
/** @interface */
|
||||||
|
function InjectedScriptHostClass()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} obj
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.nullifyPrototype = function(obj) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} obj
|
||||||
|
* @param {string} name
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.getProperty = function(obj, name) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} obj
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.internalConstructorName = function(obj) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} obj
|
||||||
|
* @param {function()|undefined} func
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.formatAccessorsAsProperties = function(obj, func) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} obj
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.subtype = function(obj) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} obj
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.isTypedArray = function(obj) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} obj
|
||||||
|
* @return {!Array.<*>}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.getInternalProperties = function(obj) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!Object} object
|
||||||
|
* @param {string} propertyName
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.objectHasOwnProperty = function(object, propertyName) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} value
|
||||||
|
* @param {string} groupName
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.bind = function(value, groupName) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!Object} object
|
||||||
|
* @return {!Object}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.proxyTargetValue = function(object) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!Object} obj
|
||||||
|
* @return {!Array<string>}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.keys = function(obj) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!Object} obj
|
||||||
|
* @return {Object}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.getPrototypeOf = function(obj) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!Object} obj
|
||||||
|
* @param {string} prop
|
||||||
|
* @return {Object}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.getOwnPropertyDescriptor = function(obj, prop) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!Object} obj
|
||||||
|
* @return {!Array<string>}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.getOwnPropertyNames = function(obj) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!Object} obj
|
||||||
|
* @return {!Array<symbol>}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.getOwnPropertySymbols = function(obj) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!Object} obj
|
||||||
|
* @param {string|symbol} name
|
||||||
|
* @return {{isBuiltin:boolean, hasGetter:boolean, hasSetter:boolean}|undefined}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.nativeAccessorDescriptor = function(obj, name) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {!Object} arrayBuffer
|
||||||
|
* @return {Array<Object>|undefined}
|
||||||
|
*/
|
||||||
|
InjectedScriptHostClass.prototype.typedArrayProperties = function(arrayBuffer) {}
|
||||||
|
|
||||||
|
/** @type {!InjectedScriptHostClass} */
|
||||||
|
var InjectedScriptHost;
|
||||||
|
/** @type {!Window} */
|
||||||
|
var inspectedGlobalObject;
|
||||||
|
/** @type {number} */
|
||||||
|
var injectedScriptId;
|
@ -109,12 +109,14 @@ InjectedScript* InspectedContext::getInjectedScript(int sessionId) {
|
|||||||
return it == m_injectedScripts.end() ? nullptr : it->second.get();
|
return it == m_injectedScripts.end() ? nullptr : it->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
InjectedScript* InspectedContext::createInjectedScript(int sessionId) {
|
bool InspectedContext::createInjectedScript(int sessionId) {
|
||||||
std::unique_ptr<InjectedScript> injectedScript =
|
std::unique_ptr<InjectedScript> injectedScript =
|
||||||
v8::base::make_unique<InjectedScript>(this, sessionId);
|
InjectedScript::create(this, sessionId);
|
||||||
|
// InjectedScript::create can destroy |this|.
|
||||||
|
if (!injectedScript) return false;
|
||||||
CHECK(m_injectedScripts.find(sessionId) == m_injectedScripts.end());
|
CHECK(m_injectedScripts.find(sessionId) == m_injectedScripts.end());
|
||||||
m_injectedScripts[sessionId] = std::move(injectedScript);
|
m_injectedScripts[sessionId] = std::move(injectedScript);
|
||||||
return getInjectedScript(sessionId);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InspectedContext::discardInjectedScript(int sessionId) {
|
void InspectedContext::discardInjectedScript(int sessionId) {
|
||||||
|
@ -40,7 +40,7 @@ class InspectedContext {
|
|||||||
V8InspectorImpl* inspector() const { return m_inspector; }
|
V8InspectorImpl* inspector() const { return m_inspector; }
|
||||||
|
|
||||||
InjectedScript* getInjectedScript(int sessionId);
|
InjectedScript* getInjectedScript(int sessionId);
|
||||||
InjectedScript* createInjectedScript(int sessionId);
|
bool createInjectedScript(int sessionId);
|
||||||
void discardInjectedScript(int sessionId);
|
void discardInjectedScript(int sessionId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1890,9 +1890,7 @@
|
|||||||
"error",
|
"error",
|
||||||
"proxy",
|
"proxy",
|
||||||
"promise",
|
"promise",
|
||||||
"typedarray",
|
"typedarray"
|
||||||
"arraybuffer",
|
|
||||||
"dataview"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -887,8 +887,6 @@ domain Runtime
|
|||||||
proxy
|
proxy
|
||||||
promise
|
promise
|
||||||
typedarray
|
typedarray
|
||||||
arraybuffer
|
|
||||||
dataview
|
|
||||||
# Object class (constructor) name. Specified for `object` type values only.
|
# Object class (constructor) name. Specified for `object` type values only.
|
||||||
optional string className
|
optional string className
|
||||||
# Remote object value in case of primitive values or JSON values (if it was requested).
|
# Remote object value in case of primitive values or JSON values (if it was requested).
|
||||||
|
@ -259,33 +259,19 @@ V8ConsoleMessage::wrapArguments(V8InspectorSessionImpl* session,
|
|||||||
|
|
||||||
std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>> args =
|
std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>> args =
|
||||||
protocol::Array<protocol::Runtime::RemoteObject>::create();
|
protocol::Array<protocol::Runtime::RemoteObject>::create();
|
||||||
|
if (m_type == ConsoleAPIType::kTable && generatePreview) {
|
||||||
v8::Local<v8::Value> value = m_arguments[0]->Get(isolate);
|
v8::Local<v8::Value> table = m_arguments[0]->Get(isolate);
|
||||||
if (value->IsObject() && m_type == ConsoleAPIType::kTable &&
|
v8::Local<v8::Value> columns = m_arguments.size() > 1
|
||||||
generatePreview) {
|
? m_arguments[1]->Get(isolate)
|
||||||
v8::MaybeLocal<v8::Array> columns;
|
: v8::Local<v8::Value>();
|
||||||
if (m_arguments.size() > 1) {
|
|
||||||
v8::Local<v8::Value> secondArgument = m_arguments[1]->Get(isolate);
|
|
||||||
if (secondArgument->IsArray()) {
|
|
||||||
columns = v8::Local<v8::Array>::Cast(secondArgument);
|
|
||||||
} else if (secondArgument->IsString()) {
|
|
||||||
v8::TryCatch tryCatch(isolate);
|
|
||||||
v8::Local<v8::Array> array = v8::Array::New(isolate);
|
|
||||||
if (array->Set(context, 0, secondArgument).IsJust()) {
|
|
||||||
columns = array;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject> wrapped =
|
std::unique_ptr<protocol::Runtime::RemoteObject> wrapped =
|
||||||
session->wrapTable(context, v8::Local<v8::Object>::Cast(value),
|
session->wrapTable(context, table, columns);
|
||||||
columns);
|
|
||||||
inspectedContext = inspector->getContext(contextGroupId, contextId);
|
inspectedContext = inspector->getContext(contextGroupId, contextId);
|
||||||
if (!inspectedContext) return nullptr;
|
if (!inspectedContext) return nullptr;
|
||||||
if (wrapped) {
|
if (wrapped)
|
||||||
args->addItem(std::move(wrapped));
|
args->addItem(std::move(wrapped));
|
||||||
} else {
|
else
|
||||||
args = nullptr;
|
args = nullptr;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for (size_t i = 0; i < m_arguments.size(); ++i) {
|
for (size_t i = 0; i < m_arguments.size(); ++i) {
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject> wrapped =
|
std::unique_ptr<protocol::Runtime::RemoteObject> wrapped =
|
||||||
|
@ -600,8 +600,9 @@ static void inspectImpl(const v8::FunctionCallbackInfo<v8::Value>& info,
|
|||||||
InjectedScript* injectedScript = helper.injectedScript(sessionId);
|
InjectedScript* injectedScript = helper.injectedScript(sessionId);
|
||||||
if (!injectedScript) return;
|
if (!injectedScript) return;
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject> wrappedObject;
|
std::unique_ptr<protocol::Runtime::RemoteObject> wrappedObject;
|
||||||
protocol::Response response = injectedScript->wrapObject(
|
protocol::Response response =
|
||||||
value, "", WrapMode::kNoPreview, &wrappedObject);
|
injectedScript->wrapObject(value, "", false /** forceValueType */,
|
||||||
|
false /** generatePreview */, &wrappedObject);
|
||||||
if (!response.isSuccess()) return;
|
if (!response.isSuccess()) return;
|
||||||
|
|
||||||
std::unique_ptr<protocol::DictionaryValue> hints =
|
std::unique_ptr<protocol::DictionaryValue> hints =
|
||||||
|
@ -260,9 +260,8 @@ Response buildScopes(v8::Isolate* isolate, v8::debug::ScopeIterator* iterator,
|
|||||||
|
|
||||||
for (; !iterator->Done(); iterator->Advance()) {
|
for (; !iterator->Done(); iterator->Advance()) {
|
||||||
std::unique_ptr<RemoteObject> object;
|
std::unique_ptr<RemoteObject> object;
|
||||||
Response result =
|
Response result = injectedScript->wrapObject(
|
||||||
injectedScript->wrapObject(iterator->GetObject(), kBacktraceObjectGroup,
|
iterator->GetObject(), kBacktraceObjectGroup, false, false, &object);
|
||||||
WrapMode::kNoPreview, &object);
|
|
||||||
if (!result.isSuccess()) return result;
|
if (!result.isSuccess()) return result;
|
||||||
|
|
||||||
auto scope = Scope::create()
|
auto scope = Scope::create()
|
||||||
@ -1086,12 +1085,10 @@ Response V8DebuggerAgentImpl::evaluateOnCallFrame(
|
|||||||
// context or session.
|
// context or session.
|
||||||
response = scope.initialize();
|
response = scope.initialize();
|
||||||
if (!response.isSuccess()) return response;
|
if (!response.isSuccess()) return response;
|
||||||
WrapMode mode = generatePreview.fromMaybe(false) ? WrapMode::kWithPreview
|
|
||||||
: WrapMode::kNoPreview;
|
|
||||||
if (returnByValue.fromMaybe(false)) mode = WrapMode::kForceValue;
|
|
||||||
return scope.injectedScript()->wrapEvaluateResult(
|
return scope.injectedScript()->wrapEvaluateResult(
|
||||||
maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), mode,
|
maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""),
|
||||||
result, exceptionDetails);
|
returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), result,
|
||||||
|
exceptionDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
Response V8DebuggerAgentImpl::setVariableValue(
|
Response V8DebuggerAgentImpl::setVariableValue(
|
||||||
@ -1271,9 +1268,8 @@ Response V8DebuggerAgentImpl::currentCallFrames(
|
|||||||
if (injectedScript) {
|
if (injectedScript) {
|
||||||
v8::Local<v8::Value> receiver;
|
v8::Local<v8::Value> receiver;
|
||||||
if (iterator->GetReceiver().ToLocal(&receiver)) {
|
if (iterator->GetReceiver().ToLocal(&receiver)) {
|
||||||
res =
|
res = injectedScript->wrapObject(receiver, kBacktraceObjectGroup, false,
|
||||||
injectedScript->wrapObject(receiver, kBacktraceObjectGroup,
|
false, &protocolReceiver);
|
||||||
WrapMode::kNoPreview, &protocolReceiver);
|
|
||||||
if (!res.isSuccess()) return res;
|
if (!res.isSuccess()) return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1324,7 +1320,7 @@ Response V8DebuggerAgentImpl::currentCallFrames(
|
|||||||
if (!returnValue.IsEmpty() && injectedScript) {
|
if (!returnValue.IsEmpty() && injectedScript) {
|
||||||
std::unique_ptr<RemoteObject> value;
|
std::unique_ptr<RemoteObject> value;
|
||||||
res = injectedScript->wrapObject(returnValue, kBacktraceObjectGroup,
|
res = injectedScript->wrapObject(returnValue, kBacktraceObjectGroup,
|
||||||
WrapMode::kNoPreview, &value);
|
false, false, &value);
|
||||||
if (!res.isSuccess()) return res;
|
if (!res.isSuccess()) return res;
|
||||||
frame->setReturnValue(std::move(value));
|
frame->setReturnValue(std::move(value));
|
||||||
}
|
}
|
||||||
@ -1532,8 +1528,8 @@ void V8DebuggerAgentImpl::didPause(
|
|||||||
? protocol::Debugger::Paused::ReasonEnum::PromiseRejection
|
? protocol::Debugger::Paused::ReasonEnum::PromiseRejection
|
||||||
: protocol::Debugger::Paused::ReasonEnum::Exception;
|
: protocol::Debugger::Paused::ReasonEnum::Exception;
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject> obj;
|
std::unique_ptr<protocol::Runtime::RemoteObject> obj;
|
||||||
injectedScript->wrapObject(exception, kBacktraceObjectGroup,
|
injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false,
|
||||||
WrapMode::kNoPreview, &obj);
|
&obj);
|
||||||
std::unique_ptr<protocol::DictionaryValue> breakAuxData;
|
std::unique_ptr<protocol::DictionaryValue> breakAuxData;
|
||||||
if (obj) {
|
if (obj) {
|
||||||
breakAuxData = obj->toValue();
|
breakAuxData = obj->toValue();
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "src/inspector/v8-debugger-agent-impl.h"
|
#include "src/inspector/v8-debugger-agent-impl.h"
|
||||||
#include "src/inspector/v8-inspector-impl.h"
|
#include "src/inspector/v8-inspector-impl.h"
|
||||||
#include "src/inspector/v8-inspector-session-impl.h"
|
#include "src/inspector/v8-inspector-session-impl.h"
|
||||||
|
#include "src/inspector/v8-internal-value-type.h"
|
||||||
#include "src/inspector/v8-runtime-agent-impl.h"
|
#include "src/inspector/v8-runtime-agent-impl.h"
|
||||||
#include "src/inspector/v8-stack-trace-impl.h"
|
#include "src/inspector/v8-stack-trace-impl.h"
|
||||||
#include "src/inspector/v8-value-utils.h"
|
#include "src/inspector/v8-value-utils.h"
|
||||||
@ -23,6 +24,102 @@ namespace {
|
|||||||
static const int kMaxAsyncTaskStacks = 128 * 1024;
|
static const int kMaxAsyncTaskStacks = 128 * 1024;
|
||||||
static const int kNoBreakpointId = 0;
|
static const int kNoBreakpointId = 0;
|
||||||
|
|
||||||
|
v8::MaybeLocal<v8::Array> collectionsEntries(v8::Local<v8::Context> context,
|
||||||
|
v8::Local<v8::Value> value) {
|
||||||
|
v8::Isolate* isolate = context->GetIsolate();
|
||||||
|
v8::Local<v8::Array> entries;
|
||||||
|
bool isKeyValue = false;
|
||||||
|
if (!value->IsObject() ||
|
||||||
|
!value.As<v8::Object>()->PreviewEntries(&isKeyValue).ToLocal(&entries)) {
|
||||||
|
return v8::MaybeLocal<v8::Array>();
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Array> wrappedEntries = v8::Array::New(isolate);
|
||||||
|
CHECK(!isKeyValue || wrappedEntries->Length() % 2 == 0);
|
||||||
|
if (!wrappedEntries->SetPrototype(context, v8::Null(isolate))
|
||||||
|
.FromMaybe(false))
|
||||||
|
return v8::MaybeLocal<v8::Array>();
|
||||||
|
for (uint32_t i = 0; i < entries->Length(); i += isKeyValue ? 2 : 1) {
|
||||||
|
v8::Local<v8::Value> item;
|
||||||
|
if (!entries->Get(context, i).ToLocal(&item)) continue;
|
||||||
|
v8::Local<v8::Value> value;
|
||||||
|
if (isKeyValue && !entries->Get(context, i + 1).ToLocal(&value)) continue;
|
||||||
|
v8::Local<v8::Object> wrapper = v8::Object::New(isolate);
|
||||||
|
if (!wrapper->SetPrototype(context, v8::Null(isolate)).FromMaybe(false))
|
||||||
|
continue;
|
||||||
|
createDataProperty(
|
||||||
|
context, wrapper,
|
||||||
|
toV8StringInternalized(isolate, isKeyValue ? "key" : "value"), item);
|
||||||
|
if (isKeyValue) {
|
||||||
|
createDataProperty(context, wrapper,
|
||||||
|
toV8StringInternalized(isolate, "value"), value);
|
||||||
|
}
|
||||||
|
createDataProperty(context, wrappedEntries, wrappedEntries->Length(),
|
||||||
|
wrapper);
|
||||||
|
}
|
||||||
|
if (!markArrayEntriesAsInternal(context, wrappedEntries,
|
||||||
|
V8InternalValueType::kEntry)) {
|
||||||
|
return v8::MaybeLocal<v8::Array>();
|
||||||
|
}
|
||||||
|
return wrappedEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::MaybeLocal<v8::Object> buildLocation(v8::Local<v8::Context> context,
|
||||||
|
int scriptId, int lineNumber,
|
||||||
|
int columnNumber) {
|
||||||
|
if (scriptId == v8::UnboundScript::kNoScriptId)
|
||||||
|
return v8::MaybeLocal<v8::Object>();
|
||||||
|
if (lineNumber == v8::Function::kLineOffsetNotFound ||
|
||||||
|
columnNumber == v8::Function::kLineOffsetNotFound) {
|
||||||
|
return v8::MaybeLocal<v8::Object>();
|
||||||
|
}
|
||||||
|
v8::Isolate* isolate = context->GetIsolate();
|
||||||
|
v8::Local<v8::Object> location = v8::Object::New(isolate);
|
||||||
|
if (!location->SetPrototype(context, v8::Null(isolate)).FromMaybe(false)) {
|
||||||
|
return v8::MaybeLocal<v8::Object>();
|
||||||
|
}
|
||||||
|
if (!createDataProperty(context, location,
|
||||||
|
toV8StringInternalized(isolate, "scriptId"),
|
||||||
|
toV8String(isolate, String16::fromInteger(scriptId)))
|
||||||
|
.FromMaybe(false)) {
|
||||||
|
return v8::MaybeLocal<v8::Object>();
|
||||||
|
}
|
||||||
|
if (!createDataProperty(context, location,
|
||||||
|
toV8StringInternalized(isolate, "lineNumber"),
|
||||||
|
v8::Integer::New(isolate, lineNumber))
|
||||||
|
.FromMaybe(false)) {
|
||||||
|
return v8::MaybeLocal<v8::Object>();
|
||||||
|
}
|
||||||
|
if (!createDataProperty(context, location,
|
||||||
|
toV8StringInternalized(isolate, "columnNumber"),
|
||||||
|
v8::Integer::New(isolate, columnNumber))
|
||||||
|
.FromMaybe(false)) {
|
||||||
|
return v8::MaybeLocal<v8::Object>();
|
||||||
|
}
|
||||||
|
if (!markAsInternal(context, location, V8InternalValueType::kLocation)) {
|
||||||
|
return v8::MaybeLocal<v8::Object>();
|
||||||
|
}
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::MaybeLocal<v8::Object> generatorObjectLocation(
|
||||||
|
v8::Local<v8::Context> context, v8::Local<v8::Value> value) {
|
||||||
|
if (!value->IsGeneratorObject()) return v8::MaybeLocal<v8::Object>();
|
||||||
|
v8::Local<v8::debug::GeneratorObject> generatorObject =
|
||||||
|
v8::debug::GeneratorObject::Cast(value);
|
||||||
|
if (!generatorObject->IsSuspended()) {
|
||||||
|
v8::Local<v8::Function> func = generatorObject->Function();
|
||||||
|
return buildLocation(context, func->ScriptId(), func->GetScriptLineNumber(),
|
||||||
|
func->GetScriptColumnNumber());
|
||||||
|
}
|
||||||
|
v8::Local<v8::debug::Script> script;
|
||||||
|
if (!generatorObject->Script().ToLocal(&script))
|
||||||
|
return v8::MaybeLocal<v8::Object>();
|
||||||
|
v8::debug::Location suspendedLocation = generatorObject->SuspendedLocation();
|
||||||
|
return buildLocation(context, script->Id(), suspendedLocation.GetLineNumber(),
|
||||||
|
suspendedLocation.GetColumnNumber());
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Map>
|
template <typename Map>
|
||||||
void cleanupExpiredWeakPointers(Map& map) {
|
void cleanupExpiredWeakPointers(Map& map) {
|
||||||
for (auto it = map.begin(); it != map.end();) {
|
for (auto it = map.begin(); it != map.end();) {
|
||||||
@ -617,52 +714,28 @@ v8::MaybeLocal<v8::Value> V8Debugger::getTargetScopes(
|
|||||||
|
|
||||||
for (; !iterator->Done(); iterator->Advance()) {
|
for (; !iterator->Done(); iterator->Advance()) {
|
||||||
v8::Local<v8::Object> scope = v8::Object::New(m_isolate);
|
v8::Local<v8::Object> scope = v8::Object::New(m_isolate);
|
||||||
if (!addInternalObject(context, scope, V8InternalValueType::kScope)) {
|
if (!markAsInternal(context, scope, V8InternalValueType::kScope)) {
|
||||||
return v8::MaybeLocal<v8::Value>();
|
return v8::MaybeLocal<v8::Value>();
|
||||||
}
|
}
|
||||||
String16 nameSuffix = toProtocolStringWithTypeCheck(
|
String16 type = v8_inspector::scopeType(iterator->GetType());
|
||||||
m_isolate, iterator->GetFunctionDebugName());
|
String16 name;
|
||||||
String16 description;
|
v8::Local<v8::Value> maybe_name = iterator->GetFunctionDebugName();
|
||||||
if (nameSuffix.length()) nameSuffix = " (" + nameSuffix + ")";
|
if (!maybe_name->IsUndefined()) {
|
||||||
switch (iterator->GetType()) {
|
name = toProtocolStringWithTypeCheck(m_isolate, maybe_name);
|
||||||
case v8::debug::ScopeIterator::ScopeTypeGlobal:
|
|
||||||
description = "Global" + nameSuffix;
|
|
||||||
break;
|
|
||||||
case v8::debug::ScopeIterator::ScopeTypeLocal:
|
|
||||||
description = "Local" + nameSuffix;
|
|
||||||
break;
|
|
||||||
case v8::debug::ScopeIterator::ScopeTypeWith:
|
|
||||||
description = "With Block" + nameSuffix;
|
|
||||||
break;
|
|
||||||
case v8::debug::ScopeIterator::ScopeTypeClosure:
|
|
||||||
description = "Closure" + nameSuffix;
|
|
||||||
break;
|
|
||||||
case v8::debug::ScopeIterator::ScopeTypeCatch:
|
|
||||||
description = "Catch" + nameSuffix;
|
|
||||||
break;
|
|
||||||
case v8::debug::ScopeIterator::ScopeTypeBlock:
|
|
||||||
description = "Block" + nameSuffix;
|
|
||||||
break;
|
|
||||||
case v8::debug::ScopeIterator::ScopeTypeScript:
|
|
||||||
description = "Script" + nameSuffix;
|
|
||||||
break;
|
|
||||||
case v8::debug::ScopeIterator::ScopeTypeEval:
|
|
||||||
description = "Eval" + nameSuffix;
|
|
||||||
break;
|
|
||||||
case v8::debug::ScopeIterator::ScopeTypeModule:
|
|
||||||
description = "Module" + nameSuffix;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
v8::Local<v8::Object> object = iterator->GetObject();
|
v8::Local<v8::Object> object = iterator->GetObject();
|
||||||
createDataProperty(context, scope,
|
createDataProperty(context, scope,
|
||||||
toV8StringInternalized(m_isolate, "description"),
|
toV8StringInternalized(m_isolate, "type"),
|
||||||
toV8String(m_isolate, description));
|
toV8String(m_isolate, type));
|
||||||
|
createDataProperty(context, scope,
|
||||||
|
toV8StringInternalized(m_isolate, "name"),
|
||||||
|
toV8String(m_isolate, name));
|
||||||
createDataProperty(context, scope,
|
createDataProperty(context, scope,
|
||||||
toV8StringInternalized(m_isolate, "object"), object);
|
toV8StringInternalized(m_isolate, "object"), object);
|
||||||
createDataProperty(context, result, result->Length(), scope);
|
createDataProperty(context, result, result->Length(), scope);
|
||||||
}
|
}
|
||||||
if (!addInternalObject(context, v8::Local<v8::Array>::Cast(result),
|
if (!markAsInternal(context, v8::Local<v8::Array>::Cast(result),
|
||||||
V8InternalValueType::kScopeList))
|
V8InternalValueType::kScopeList))
|
||||||
return v8::MaybeLocal<v8::Value>();
|
return v8::MaybeLocal<v8::Value>();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -677,45 +750,6 @@ v8::MaybeLocal<v8::Value> V8Debugger::generatorScopes(
|
|||||||
return getTargetScopes(context, generator, GENERATOR);
|
return getTargetScopes(context, generator, GENERATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::MaybeLocal<v8::Array> V8Debugger::collectionsEntries(
|
|
||||||
v8::Local<v8::Context> context, v8::Local<v8::Value> value) {
|
|
||||||
v8::Isolate* isolate = context->GetIsolate();
|
|
||||||
v8::Local<v8::Array> entries;
|
|
||||||
bool isKeyValue = false;
|
|
||||||
if (!value->IsObject() ||
|
|
||||||
!value.As<v8::Object>()->PreviewEntries(&isKeyValue).ToLocal(&entries)) {
|
|
||||||
return v8::MaybeLocal<v8::Array>();
|
|
||||||
}
|
|
||||||
|
|
||||||
v8::Local<v8::Array> wrappedEntries = v8::Array::New(isolate);
|
|
||||||
CHECK(!isKeyValue || wrappedEntries->Length() % 2 == 0);
|
|
||||||
if (!wrappedEntries->SetPrototype(context, v8::Null(isolate))
|
|
||||||
.FromMaybe(false))
|
|
||||||
return v8::MaybeLocal<v8::Array>();
|
|
||||||
for (uint32_t i = 0; i < entries->Length(); i += isKeyValue ? 2 : 1) {
|
|
||||||
v8::Local<v8::Value> item;
|
|
||||||
if (!entries->Get(context, i).ToLocal(&item)) continue;
|
|
||||||
v8::Local<v8::Value> value;
|
|
||||||
if (isKeyValue && !entries->Get(context, i + 1).ToLocal(&value)) continue;
|
|
||||||
v8::Local<v8::Object> wrapper = v8::Object::New(isolate);
|
|
||||||
if (!wrapper->SetPrototype(context, v8::Null(isolate)).FromMaybe(false))
|
|
||||||
continue;
|
|
||||||
createDataProperty(
|
|
||||||
context, wrapper,
|
|
||||||
toV8StringInternalized(isolate, isKeyValue ? "key" : "value"), item);
|
|
||||||
if (isKeyValue) {
|
|
||||||
createDataProperty(context, wrapper,
|
|
||||||
toV8StringInternalized(isolate, "value"), value);
|
|
||||||
}
|
|
||||||
if (!addInternalObject(context, wrapper, V8InternalValueType::kEntry)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
createDataProperty(context, wrappedEntries, wrappedEntries->Length(),
|
|
||||||
wrapper);
|
|
||||||
}
|
|
||||||
return wrappedEntries;
|
|
||||||
}
|
|
||||||
|
|
||||||
v8::MaybeLocal<v8::Uint32> V8Debugger::stableObjectId(
|
v8::MaybeLocal<v8::Uint32> V8Debugger::stableObjectId(
|
||||||
v8::Local<v8::Context> context, v8::Local<v8::Value> value) {
|
v8::Local<v8::Context> context, v8::Local<v8::Value> value) {
|
||||||
DCHECK(value->IsObject());
|
DCHECK(value->IsObject());
|
||||||
@ -747,6 +781,25 @@ v8::MaybeLocal<v8::Array> V8Debugger::internalProperties(
|
|||||||
createDataProperty(context, properties, properties->Length(), id);
|
createDataProperty(context, properties, properties->Length(), id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (value->IsFunction()) {
|
||||||
|
v8::Local<v8::Function> function = value.As<v8::Function>();
|
||||||
|
v8::Local<v8::Object> location;
|
||||||
|
if (buildLocation(context, function->ScriptId(),
|
||||||
|
function->GetScriptLineNumber(),
|
||||||
|
function->GetScriptColumnNumber())
|
||||||
|
.ToLocal(&location)) {
|
||||||
|
createDataProperty(
|
||||||
|
context, properties, properties->Length(),
|
||||||
|
toV8StringInternalized(m_isolate, "[[FunctionLocation]]"));
|
||||||
|
createDataProperty(context, properties, properties->Length(), location);
|
||||||
|
}
|
||||||
|
if (function->IsGeneratorFunction()) {
|
||||||
|
createDataProperty(context, properties, properties->Length(),
|
||||||
|
toV8StringInternalized(m_isolate, "[[IsGenerator]]"));
|
||||||
|
createDataProperty(context, properties, properties->Length(),
|
||||||
|
v8::True(m_isolate));
|
||||||
|
}
|
||||||
|
}
|
||||||
v8::Local<v8::Array> entries;
|
v8::Local<v8::Array> entries;
|
||||||
if (collectionsEntries(context, value).ToLocal(&entries)) {
|
if (collectionsEntries(context, value).ToLocal(&entries)) {
|
||||||
createDataProperty(context, properties, properties->Length(),
|
createDataProperty(context, properties, properties->Length(),
|
||||||
@ -754,6 +807,13 @@ v8::MaybeLocal<v8::Array> V8Debugger::internalProperties(
|
|||||||
createDataProperty(context, properties, properties->Length(), entries);
|
createDataProperty(context, properties, properties->Length(), entries);
|
||||||
}
|
}
|
||||||
if (value->IsGeneratorObject()) {
|
if (value->IsGeneratorObject()) {
|
||||||
|
v8::Local<v8::Object> location;
|
||||||
|
if (generatorObjectLocation(context, value).ToLocal(&location)) {
|
||||||
|
createDataProperty(
|
||||||
|
context, properties, properties->Length(),
|
||||||
|
toV8StringInternalized(m_isolate, "[[GeneratorLocation]]"));
|
||||||
|
createDataProperty(context, properties, properties->Length(), location);
|
||||||
|
}
|
||||||
v8::Local<v8::Value> scopes;
|
v8::Local<v8::Value> scopes;
|
||||||
if (generatorScopes(context, value).ToLocal(&scopes)) {
|
if (generatorScopes(context, value).ToLocal(&scopes)) {
|
||||||
createDataProperty(context, properties, properties->Length(),
|
createDataProperty(context, properties, properties->Length(),
|
||||||
@ -1136,31 +1196,6 @@ std::pair<int64_t, int64_t> V8Debugger::debuggerIdFor(
|
|||||||
return std::make_pair(0, 0);
|
return std::make_pair(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool V8Debugger::addInternalObject(v8::Local<v8::Context> context,
|
|
||||||
v8::Local<v8::Object> object,
|
|
||||||
V8InternalValueType type) {
|
|
||||||
if (m_internalObjects.IsEmpty()) {
|
|
||||||
m_internalObjects.Reset(m_isolate, v8::debug::WeakMap::New(m_isolate));
|
|
||||||
}
|
|
||||||
return !m_internalObjects.Get(m_isolate)
|
|
||||||
->Set(context, object,
|
|
||||||
v8::Integer::New(m_isolate, static_cast<int>(type)))
|
|
||||||
.IsEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
V8InternalValueType V8Debugger::getInternalType(v8::Local<v8::Context> context,
|
|
||||||
v8::Local<v8::Object> object) {
|
|
||||||
if (m_internalObjects.IsEmpty()) return V8InternalValueType::kNone;
|
|
||||||
v8::Local<v8::Value> typeValue;
|
|
||||||
if (!m_internalObjects.Get(m_isolate)
|
|
||||||
->Get(context, object)
|
|
||||||
.ToLocal(&typeValue) ||
|
|
||||||
!typeValue->IsUint32()) {
|
|
||||||
return V8InternalValueType::kNone;
|
|
||||||
}
|
|
||||||
return static_cast<V8InternalValueType>(typeValue.As<v8::Int32>()->Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
void V8Debugger::dumpAsyncTaskStacksStateForTest() {
|
void V8Debugger::dumpAsyncTaskStacksStateForTest() {
|
||||||
fprintf(stdout, "Async stacks count: %d\n", m_asyncStacksCount);
|
fprintf(stdout, "Async stacks count: %d\n", m_asyncStacksCount);
|
||||||
fprintf(stdout, "Scheduled async tasks: %zu\n", m_asyncTaskStacks.size());
|
fprintf(stdout, "Scheduled async tasks: %zu\n", m_asyncTaskStacks.size());
|
||||||
|
@ -30,9 +30,6 @@ class V8InspectorImpl;
|
|||||||
class V8StackTraceImpl;
|
class V8StackTraceImpl;
|
||||||
struct V8StackTraceId;
|
struct V8StackTraceId;
|
||||||
|
|
||||||
enum class WrapMode { kForceValue, kNoPreview, kWithPreview };
|
|
||||||
enum class V8InternalValueType { kNone, kEntry, kScope, kScopeList };
|
|
||||||
|
|
||||||
using protocol::Response;
|
using protocol::Response;
|
||||||
using ScheduleStepIntoAsyncCallback =
|
using ScheduleStepIntoAsyncCallback =
|
||||||
protocol::Debugger::Backend::ScheduleStepIntoAsyncCallback;
|
protocol::Debugger::Backend::ScheduleStepIntoAsyncCallback;
|
||||||
@ -137,12 +134,6 @@ class V8Debugger : public v8::debug::DebugDelegate,
|
|||||||
std::shared_ptr<AsyncStackTrace> stackTraceFor(int contextGroupId,
|
std::shared_ptr<AsyncStackTrace> stackTraceFor(int contextGroupId,
|
||||||
const V8StackTraceId& id);
|
const V8StackTraceId& id);
|
||||||
|
|
||||||
bool addInternalObject(v8::Local<v8::Context> context,
|
|
||||||
v8::Local<v8::Object> object,
|
|
||||||
V8InternalValueType type);
|
|
||||||
V8InternalValueType getInternalType(v8::Local<v8::Context> context,
|
|
||||||
v8::Local<v8::Object> object);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void clearContinueToLocation();
|
void clearContinueToLocation();
|
||||||
bool shouldContinueToCurrentLocation();
|
bool shouldContinueToCurrentLocation();
|
||||||
@ -169,8 +160,6 @@ class V8Debugger : public v8::debug::DebugDelegate,
|
|||||||
v8::Local<v8::Function>);
|
v8::Local<v8::Function>);
|
||||||
v8::MaybeLocal<v8::Value> generatorScopes(v8::Local<v8::Context>,
|
v8::MaybeLocal<v8::Value> generatorScopes(v8::Local<v8::Context>,
|
||||||
v8::Local<v8::Value>);
|
v8::Local<v8::Value>);
|
||||||
v8::MaybeLocal<v8::Array> collectionsEntries(v8::Local<v8::Context> context,
|
|
||||||
v8::Local<v8::Value> value);
|
|
||||||
|
|
||||||
void asyncTaskScheduledForStack(const String16& taskName, void* task,
|
void asyncTaskScheduledForStack(const String16& taskName, void* task,
|
||||||
bool recurring);
|
bool recurring);
|
||||||
@ -264,8 +253,6 @@ class V8Debugger : public v8::debug::DebugDelegate,
|
|||||||
uint32_t m_lastStableObjectId = 0;
|
uint32_t m_lastStableObjectId = 0;
|
||||||
v8::Global<v8::debug::WeakMap> m_stableObjectId;
|
v8::Global<v8::debug::WeakMap> m_stableObjectId;
|
||||||
|
|
||||||
v8::Global<v8::debug::WeakMap> m_internalObjects;
|
|
||||||
|
|
||||||
WasmTranslation m_wasmTranslation;
|
WasmTranslation m_wasmTranslation;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(V8Debugger);
|
DISALLOW_COPY_AND_ASSIGN(V8Debugger);
|
||||||
|
115
src/inspector/v8-function-call.cc
Normal file
115
src/inspector/v8-function-call.cc
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
|
* in the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Google Inc. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "src/inspector/v8-function-call.h"
|
||||||
|
|
||||||
|
#include "src/inspector/inspected-context.h"
|
||||||
|
#include "src/inspector/string-util.h"
|
||||||
|
#include "src/inspector/v8-debugger.h"
|
||||||
|
#include "src/inspector/v8-inspector-impl.h"
|
||||||
|
|
||||||
|
#include "include/v8-inspector.h"
|
||||||
|
|
||||||
|
namespace v8_inspector {
|
||||||
|
|
||||||
|
V8FunctionCall::V8FunctionCall(V8InspectorImpl* inspector,
|
||||||
|
v8::Local<v8::Context> context,
|
||||||
|
v8::Local<v8::Value> value, const String16& name)
|
||||||
|
: m_inspector(inspector),
|
||||||
|
m_context(context),
|
||||||
|
m_name(toV8String(context->GetIsolate(), name)),
|
||||||
|
m_value(value) {}
|
||||||
|
|
||||||
|
void V8FunctionCall::appendArgument(v8::Local<v8::Value> value) {
|
||||||
|
m_arguments.push_back(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8FunctionCall::appendArgument(const String16& argument) {
|
||||||
|
m_arguments.push_back(toV8String(m_context->GetIsolate(), argument));
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8FunctionCall::appendArgument(int argument) {
|
||||||
|
m_arguments.push_back(v8::Number::New(m_context->GetIsolate(), argument));
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8FunctionCall::appendArgument(bool argument) {
|
||||||
|
m_arguments.push_back(argument ? v8::True(m_context->GetIsolate())
|
||||||
|
: v8::False(m_context->GetIsolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Value> V8FunctionCall::call(bool& hadException,
|
||||||
|
bool reportExceptions) {
|
||||||
|
v8::TryCatch tryCatch(m_context->GetIsolate());
|
||||||
|
tryCatch.SetVerbose(reportExceptions);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> result = callWithoutExceptionHandling();
|
||||||
|
hadException = tryCatch.HasCaught();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Value> V8FunctionCall::callWithoutExceptionHandling() {
|
||||||
|
v8::Context::Scope contextScope(m_context);
|
||||||
|
|
||||||
|
v8::Local<v8::Object> thisObject = v8::Local<v8::Object>::Cast(m_value);
|
||||||
|
v8::Local<v8::Value> value;
|
||||||
|
if (!thisObject->Get(m_context, m_name).ToLocal(&value))
|
||||||
|
return v8::Local<v8::Value>();
|
||||||
|
|
||||||
|
DCHECK(value->IsFunction());
|
||||||
|
|
||||||
|
v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value);
|
||||||
|
std::unique_ptr<v8::Local<v8::Value>[]> info(
|
||||||
|
new v8::Local<v8::Value>[m_arguments.size()]);
|
||||||
|
for (size_t i = 0; i < m_arguments.size(); ++i) {
|
||||||
|
info[i] = m_arguments[i];
|
||||||
|
DCHECK(!info[i].IsEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
int contextGroupId = m_inspector->contextGroupId(m_context);
|
||||||
|
if (contextGroupId) {
|
||||||
|
m_inspector->client()->muteMetrics(contextGroupId);
|
||||||
|
m_inspector->muteExceptions(contextGroupId);
|
||||||
|
}
|
||||||
|
v8::MicrotasksScope microtasksScope(m_context->GetIsolate(),
|
||||||
|
v8::MicrotasksScope::kDoNotRunMicrotasks);
|
||||||
|
v8::Isolate::AllowJavascriptExecutionScope(m_context->GetIsolate());
|
||||||
|
v8::MaybeLocal<v8::Value> maybeResult = function->Call(
|
||||||
|
m_context, thisObject, static_cast<int>(m_arguments.size()), info.get());
|
||||||
|
if (contextGroupId) {
|
||||||
|
m_inspector->client()->unmuteMetrics(contextGroupId);
|
||||||
|
m_inspector->unmuteExceptions(contextGroupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Value> result;
|
||||||
|
if (!maybeResult.ToLocal(&result)) return v8::Local<v8::Value>();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace v8_inspector
|
65
src/inspector/v8-function-call.h
Normal file
65
src/inspector/v8-function-call.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
|
* in the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Google Inc. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef V8_INSPECTOR_V8_FUNCTION_CALL_H_
|
||||||
|
#define V8_INSPECTOR_V8_FUNCTION_CALL_H_
|
||||||
|
|
||||||
|
#include "src/inspector/string-16.h"
|
||||||
|
|
||||||
|
#include "include/v8.h"
|
||||||
|
|
||||||
|
namespace v8_inspector {
|
||||||
|
|
||||||
|
class V8InspectorImpl;
|
||||||
|
|
||||||
|
class V8FunctionCall {
|
||||||
|
public:
|
||||||
|
V8FunctionCall(V8InspectorImpl*, v8::Local<v8::Context>, v8::Local<v8::Value>,
|
||||||
|
const String16& name);
|
||||||
|
|
||||||
|
void appendArgument(v8::Local<v8::Value>);
|
||||||
|
void appendArgument(const String16&);
|
||||||
|
void appendArgument(int);
|
||||||
|
void appendArgument(bool);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> call(bool& hadException, bool reportExceptions = true);
|
||||||
|
v8::Local<v8::Value> callWithoutExceptionHandling();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
V8InspectorImpl* m_inspector;
|
||||||
|
v8::Local<v8::Context> m_context;
|
||||||
|
std::vector<v8::Local<v8::Value>> m_arguments;
|
||||||
|
v8::Local<v8::String> m_name;
|
||||||
|
v8::Local<v8::Value> m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace v8_inspector
|
||||||
|
|
||||||
|
#endif // V8_INSPECTOR_V8_FUNCTION_CALL_H_
|
427
src/inspector/v8-injected-script-host.cc
Normal file
427
src/inspector/v8-injected-script-host.cc
Normal file
@ -0,0 +1,427 @@
|
|||||||
|
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "src/inspector/v8-injected-script-host.h"
|
||||||
|
|
||||||
|
#include "src/base/macros.h"
|
||||||
|
#include "src/debug/debug-interface.h"
|
||||||
|
#include "src/inspector/injected-script.h"
|
||||||
|
#include "src/inspector/string-util.h"
|
||||||
|
#include "src/inspector/v8-debugger.h"
|
||||||
|
#include "src/inspector/v8-inspector-impl.h"
|
||||||
|
#include "src/inspector/v8-internal-value-type.h"
|
||||||
|
#include "src/inspector/v8-value-utils.h"
|
||||||
|
|
||||||
|
#include "include/v8-inspector.h"
|
||||||
|
|
||||||
|
namespace v8_inspector {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void setFunctionProperty(v8::Local<v8::Context> context,
|
||||||
|
v8::Local<v8::Object> obj, const char* name,
|
||||||
|
v8::FunctionCallback callback,
|
||||||
|
v8::Local<v8::External> external) {
|
||||||
|
v8::Local<v8::String> funcName =
|
||||||
|
toV8StringInternalized(context->GetIsolate(), name);
|
||||||
|
v8::Local<v8::Function> func;
|
||||||
|
if (!v8::Function::New(context, callback, external, 0,
|
||||||
|
v8::ConstructorBehavior::kThrow)
|
||||||
|
.ToLocal(&func))
|
||||||
|
return;
|
||||||
|
func->SetName(funcName);
|
||||||
|
createDataProperty(context, obj, funcName, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
V8InspectorImpl* unwrapInspector(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
|
DCHECK(!info.Data().IsEmpty());
|
||||||
|
DCHECK(info.Data()->IsExternal());
|
||||||
|
V8InspectorImpl* inspector =
|
||||||
|
static_cast<V8InspectorImpl*>(info.Data().As<v8::External>()->Value());
|
||||||
|
DCHECK(inspector);
|
||||||
|
return inspector;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TypedArray>
|
||||||
|
void addTypedArrayProperty(std::vector<v8::Local<v8::Value>>* props,
|
||||||
|
v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::ArrayBuffer> arraybuffer,
|
||||||
|
String16 name, size_t length) {
|
||||||
|
props->push_back(toV8String(isolate, name));
|
||||||
|
props->push_back(TypedArray::New(arraybuffer, 0, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
v8::Local<v8::Object> V8InjectedScriptHost::create(
|
||||||
|
v8::Local<v8::Context> context, V8InspectorImpl* inspector) {
|
||||||
|
v8::Isolate* isolate = inspector->isolate();
|
||||||
|
v8::Local<v8::Object> injectedScriptHost = v8::Object::New(isolate);
|
||||||
|
bool success = injectedScriptHost->SetPrototype(context, v8::Null(isolate))
|
||||||
|
.FromMaybe(false);
|
||||||
|
DCHECK(success);
|
||||||
|
USE(success);
|
||||||
|
v8::Local<v8::External> debuggerExternal =
|
||||||
|
v8::External::New(isolate, inspector);
|
||||||
|
setFunctionProperty(context, injectedScriptHost, "nullifyPrototype",
|
||||||
|
V8InjectedScriptHost::nullifyPrototypeCallback,
|
||||||
|
debuggerExternal);
|
||||||
|
setFunctionProperty(context, injectedScriptHost, "getProperty",
|
||||||
|
V8InjectedScriptHost::getPropertyCallback,
|
||||||
|
debuggerExternal);
|
||||||
|
setFunctionProperty(context, injectedScriptHost, "internalConstructorName",
|
||||||
|
V8InjectedScriptHost::internalConstructorNameCallback,
|
||||||
|
debuggerExternal);
|
||||||
|
setFunctionProperty(
|
||||||
|
context, injectedScriptHost, "formatAccessorsAsProperties",
|
||||||
|
V8InjectedScriptHost::formatAccessorsAsProperties, debuggerExternal);
|
||||||
|
setFunctionProperty(context, injectedScriptHost, "subtype",
|
||||||
|
V8InjectedScriptHost::subtypeCallback, debuggerExternal);
|
||||||
|
setFunctionProperty(context, injectedScriptHost, "getInternalProperties",
|
||||||
|
V8InjectedScriptHost::getInternalPropertiesCallback,
|
||||||
|
debuggerExternal);
|
||||||
|
setFunctionProperty(context, injectedScriptHost, "objectHasOwnProperty",
|
||||||
|
V8InjectedScriptHost::objectHasOwnPropertyCallback,
|
||||||
|
debuggerExternal);
|
||||||
|
setFunctionProperty(context, injectedScriptHost, "bind",
|
||||||
|
V8InjectedScriptHost::bindCallback, debuggerExternal);
|
||||||
|
setFunctionProperty(context, injectedScriptHost, "proxyTargetValue",
|
||||||
|
V8InjectedScriptHost::proxyTargetValueCallback,
|
||||||
|
debuggerExternal);
|
||||||
|
setFunctionProperty(context, injectedScriptHost, "nativeAccessorDescriptor",
|
||||||
|
V8InjectedScriptHost::nativeAccessorDescriptorCallback,
|
||||||
|
debuggerExternal);
|
||||||
|
setFunctionProperty(context, injectedScriptHost, "typedArrayProperties",
|
||||||
|
V8InjectedScriptHost::typedArrayPropertiesCallback,
|
||||||
|
debuggerExternal);
|
||||||
|
createDataProperty(context, injectedScriptHost,
|
||||||
|
toV8StringInternalized(isolate, "keys"),
|
||||||
|
v8::debug::GetBuiltin(isolate, v8::debug::kObjectKeys));
|
||||||
|
createDataProperty(
|
||||||
|
context, injectedScriptHost,
|
||||||
|
toV8StringInternalized(isolate, "getPrototypeOf"),
|
||||||
|
v8::debug::GetBuiltin(isolate, v8::debug::kObjectGetPrototypeOf));
|
||||||
|
createDataProperty(
|
||||||
|
context, injectedScriptHost,
|
||||||
|
toV8StringInternalized(isolate, "getOwnPropertyDescriptor"),
|
||||||
|
v8::debug::GetBuiltin(isolate,
|
||||||
|
v8::debug::kObjectGetOwnPropertyDescriptor));
|
||||||
|
createDataProperty(
|
||||||
|
context, injectedScriptHost,
|
||||||
|
toV8StringInternalized(isolate, "getOwnPropertyNames"),
|
||||||
|
v8::debug::GetBuiltin(isolate, v8::debug::kObjectGetOwnPropertyNames));
|
||||||
|
createDataProperty(
|
||||||
|
context, injectedScriptHost,
|
||||||
|
toV8StringInternalized(isolate, "getOwnPropertySymbols"),
|
||||||
|
v8::debug::GetBuiltin(isolate, v8::debug::kObjectGetOwnPropertySymbols));
|
||||||
|
return injectedScriptHost;
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8InjectedScriptHost::nullifyPrototypeCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
|
CHECK_EQ(1, info.Length());
|
||||||
|
DCHECK(info[0]->IsObject());
|
||||||
|
if (!info[0]->IsObject()) return;
|
||||||
|
v8::Isolate* isolate = info.GetIsolate();
|
||||||
|
info[0]
|
||||||
|
.As<v8::Object>()
|
||||||
|
->SetPrototype(isolate->GetCurrentContext(), v8::Null(isolate))
|
||||||
|
.ToChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8InjectedScriptHost::getPropertyCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
|
CHECK(info.Length() == 2 && info[1]->IsString());
|
||||||
|
if (!info[0]->IsObject()) return;
|
||||||
|
v8::Isolate* isolate = info.GetIsolate();
|
||||||
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||||
|
v8::TryCatch tryCatch(isolate);
|
||||||
|
v8::Isolate::DisallowJavascriptExecutionScope throwJs(
|
||||||
|
isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
|
||||||
|
v8::Local<v8::Value> property;
|
||||||
|
if (info[0]
|
||||||
|
.As<v8::Object>()
|
||||||
|
->Get(context, v8::Local<v8::String>::Cast(info[1]))
|
||||||
|
.ToLocal(&property)) {
|
||||||
|
info.GetReturnValue().Set(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8InjectedScriptHost::internalConstructorNameCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
|
if (info.Length() < 1 || !info[0]->IsObject()) return;
|
||||||
|
|
||||||
|
v8::Local<v8::Object> object = info[0].As<v8::Object>();
|
||||||
|
info.GetReturnValue().Set(object->GetConstructorName());
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8InjectedScriptHost::formatAccessorsAsProperties(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
|
DCHECK_EQ(info.Length(), 2);
|
||||||
|
info.GetReturnValue().Set(false);
|
||||||
|
if (!info[1]->IsFunction()) return;
|
||||||
|
// Check that function is user-defined.
|
||||||
|
if (info[1].As<v8::Function>()->ScriptId() != v8::UnboundScript::kNoScriptId)
|
||||||
|
return;
|
||||||
|
info.GetReturnValue().Set(
|
||||||
|
unwrapInspector(info)->client()->formatAccessorsAsProperties(info[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8InjectedScriptHost::subtypeCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
|
if (info.Length() < 1) return;
|
||||||
|
|
||||||
|
v8::Isolate* isolate = info.GetIsolate();
|
||||||
|
v8::Local<v8::Value> value = info[0];
|
||||||
|
if (value->IsObject()) {
|
||||||
|
v8::Local<v8::Value> internalType = v8InternalValueTypeFrom(
|
||||||
|
isolate->GetCurrentContext(), v8::Local<v8::Object>::Cast(value));
|
||||||
|
if (internalType->IsString()) {
|
||||||
|
info.GetReturnValue().Set(internalType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value->IsArray() || value->IsArgumentsObject()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "array"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsTypedArray()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "typedarray"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsDate()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "date"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsRegExp()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "regexp"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsMap()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "map"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsWeakMap()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "weakmap"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsSet()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "set"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsWeakSet()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "weakset"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsMapIterator() || value->IsSetIterator()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "iterator"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsGeneratorObject()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "generator"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsNativeError()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "error"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsProxy()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "proxy"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsPromise()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "promise"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsArrayBuffer() || value->IsSharedArrayBuffer()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "arraybuffer"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->IsDataView()) {
|
||||||
|
info.GetReturnValue().Set(toV8StringInternalized(isolate, "dataview"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::unique_ptr<StringBuffer> subtype =
|
||||||
|
unwrapInspector(info)->client()->valueSubtype(value);
|
||||||
|
if (subtype) {
|
||||||
|
info.GetReturnValue().Set(toV8String(isolate, subtype->string()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8InjectedScriptHost::getInternalPropertiesCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
|
if (info.Length() < 1) return;
|
||||||
|
|
||||||
|
std::unordered_set<String16> allowedProperties;
|
||||||
|
if (info[0]->IsBooleanObject() || info[0]->IsNumberObject() ||
|
||||||
|
info[0]->IsStringObject() || info[0]->IsSymbolObject() ||
|
||||||
|
info[0]->IsBigIntObject()) {
|
||||||
|
allowedProperties.insert(String16("[[PrimitiveValue]]"));
|
||||||
|
} else if (info[0]->IsPromise()) {
|
||||||
|
allowedProperties.insert(String16("[[PromiseStatus]]"));
|
||||||
|
allowedProperties.insert(String16("[[PromiseValue]]"));
|
||||||
|
} else if (info[0]->IsGeneratorObject()) {
|
||||||
|
allowedProperties.insert(String16("[[GeneratorStatus]]"));
|
||||||
|
} else if (info[0]->IsMap() || info[0]->IsWeakMap() || info[0]->IsSet() ||
|
||||||
|
info[0]->IsWeakSet() || info[0]->IsMapIterator() ||
|
||||||
|
info[0]->IsSetIterator()) {
|
||||||
|
allowedProperties.insert(String16("[[Entries]]"));
|
||||||
|
}
|
||||||
|
if (!allowedProperties.size()) return;
|
||||||
|
|
||||||
|
v8::Isolate* isolate = info.GetIsolate();
|
||||||
|
v8::Local<v8::Array> allProperties;
|
||||||
|
if (!unwrapInspector(info)
|
||||||
|
->debugger()
|
||||||
|
->internalProperties(isolate->GetCurrentContext(), info[0])
|
||||||
|
.ToLocal(&allProperties) ||
|
||||||
|
!allProperties->IsArray() || allProperties->Length() % 2 != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
{
|
||||||
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||||
|
v8::TryCatch tryCatch(isolate);
|
||||||
|
v8::Isolate::DisallowJavascriptExecutionScope throwJs(
|
||||||
|
isolate,
|
||||||
|
v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
|
||||||
|
|
||||||
|
v8::Local<v8::Array> properties = v8::Array::New(isolate);
|
||||||
|
if (tryCatch.HasCaught()) return;
|
||||||
|
|
||||||
|
uint32_t outputIndex = 0;
|
||||||
|
for (uint32_t i = 0; i < allProperties->Length(); i += 2) {
|
||||||
|
v8::Local<v8::Value> key;
|
||||||
|
if (!allProperties->Get(context, i).ToLocal(&key)) continue;
|
||||||
|
if (tryCatch.HasCaught()) {
|
||||||
|
tryCatch.Reset();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String16 keyString = toProtocolStringWithTypeCheck(isolate, key);
|
||||||
|
if (keyString.isEmpty() ||
|
||||||
|
allowedProperties.find(keyString) == allowedProperties.end())
|
||||||
|
continue;
|
||||||
|
v8::Local<v8::Value> value;
|
||||||
|
if (!allProperties->Get(context, i + 1).ToLocal(&value)) continue;
|
||||||
|
if (tryCatch.HasCaught()) {
|
||||||
|
tryCatch.Reset();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
createDataProperty(context, properties, outputIndex++, key);
|
||||||
|
createDataProperty(context, properties, outputIndex++, value);
|
||||||
|
}
|
||||||
|
info.GetReturnValue().Set(properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8InjectedScriptHost::objectHasOwnPropertyCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
|
if (info.Length() < 2 || !info[0]->IsObject() || !info[1]->IsString()) return;
|
||||||
|
bool result = info[0]
|
||||||
|
.As<v8::Object>()
|
||||||
|
->HasOwnProperty(info.GetIsolate()->GetCurrentContext(),
|
||||||
|
v8::Local<v8::String>::Cast(info[1]))
|
||||||
|
.FromMaybe(false);
|
||||||
|
info.GetReturnValue().Set(v8::Boolean::New(info.GetIsolate(), result));
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8InjectedScriptHost::bindCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
|
if (info.Length() < 2 || !info[1]->IsString()) return;
|
||||||
|
InjectedScript* injectedScript =
|
||||||
|
InjectedScript::fromInjectedScriptHost(info.GetIsolate(), info.Holder());
|
||||||
|
if (!injectedScript) return;
|
||||||
|
|
||||||
|
v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
|
||||||
|
v8::Local<v8::String> v8groupName =
|
||||||
|
info[1]->ToString(context).ToLocalChecked();
|
||||||
|
String16 groupName =
|
||||||
|
toProtocolStringWithTypeCheck(info.GetIsolate(), v8groupName);
|
||||||
|
int id = injectedScript->bindObject(info[0], groupName);
|
||||||
|
info.GetReturnValue().Set(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8InjectedScriptHost::proxyTargetValueCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
|
if (info.Length() != 1 || !info[0]->IsProxy()) {
|
||||||
|
UNREACHABLE();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
v8::Local<v8::Value> target = info[0].As<v8::Proxy>();
|
||||||
|
while (target->IsProxy())
|
||||||
|
target = v8::Local<v8::Proxy>::Cast(target)->GetTarget();
|
||||||
|
info.GetReturnValue().Set(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8InjectedScriptHost::nativeAccessorDescriptorCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
|
v8::Isolate* isolate = info.GetIsolate();
|
||||||
|
if (info.Length() != 2 || !info[0]->IsObject() || !info[1]->IsName()) {
|
||||||
|
info.GetReturnValue().Set(v8::Undefined(isolate));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||||
|
int flags = v8::debug::GetNativeAccessorDescriptor(
|
||||||
|
context, v8::Local<v8::Object>::Cast(info[0]),
|
||||||
|
v8::Local<v8::Name>::Cast(info[1]));
|
||||||
|
if (flags == static_cast<int>(v8::debug::NativeAccessorType::None)) {
|
||||||
|
info.GetReturnValue().Set(v8::Undefined(isolate));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isBuiltin =
|
||||||
|
flags & static_cast<int>(v8::debug::NativeAccessorType::IsBuiltin);
|
||||||
|
bool hasGetter =
|
||||||
|
flags & static_cast<int>(v8::debug::NativeAccessorType::HasGetter);
|
||||||
|
bool hasSetter =
|
||||||
|
flags & static_cast<int>(v8::debug::NativeAccessorType::HasSetter);
|
||||||
|
v8::Local<v8::Object> result = v8::Object::New(isolate);
|
||||||
|
result->SetPrototype(context, v8::Null(isolate)).ToChecked();
|
||||||
|
createDataProperty(context, result, toV8String(isolate, "isBuiltin"),
|
||||||
|
v8::Boolean::New(isolate, isBuiltin));
|
||||||
|
createDataProperty(context, result, toV8String(isolate, "hasGetter"),
|
||||||
|
v8::Boolean::New(isolate, hasGetter));
|
||||||
|
createDataProperty(context, result, toV8String(isolate, "hasSetter"),
|
||||||
|
v8::Boolean::New(isolate, hasSetter));
|
||||||
|
info.GetReturnValue().Set(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8InjectedScriptHost::typedArrayPropertiesCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
|
v8::Isolate* isolate = info.GetIsolate();
|
||||||
|
if (info.Length() != 1 || !info[0]->IsArrayBuffer()) return;
|
||||||
|
|
||||||
|
v8::TryCatch tryCatch(isolate);
|
||||||
|
v8::Isolate::DisallowJavascriptExecutionScope throwJs(
|
||||||
|
isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
|
||||||
|
v8::Local<v8::ArrayBuffer> arrayBuffer = info[0].As<v8::ArrayBuffer>();
|
||||||
|
size_t length = arrayBuffer->ByteLength();
|
||||||
|
if (length == 0) return;
|
||||||
|
std::vector<v8::Local<v8::Value>> arrays_vector;
|
||||||
|
addTypedArrayProperty<v8::Int8Array>(&arrays_vector, isolate, arrayBuffer,
|
||||||
|
"[[Int8Array]]", length);
|
||||||
|
addTypedArrayProperty<v8::Uint8Array>(&arrays_vector, isolate, arrayBuffer,
|
||||||
|
"[[Uint8Array]]", length);
|
||||||
|
|
||||||
|
if (length % 2 == 0) {
|
||||||
|
addTypedArrayProperty<v8::Int16Array>(&arrays_vector, isolate, arrayBuffer,
|
||||||
|
"[[Int16Array]]", length / 2);
|
||||||
|
}
|
||||||
|
if (length % 4 == 0) {
|
||||||
|
addTypedArrayProperty<v8::Int32Array>(&arrays_vector, isolate, arrayBuffer,
|
||||||
|
"[[Int32Array]]", length / 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tryCatch.HasCaught()) return;
|
||||||
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||||
|
v8::Local<v8::Array> arrays =
|
||||||
|
v8::Array::New(isolate, static_cast<uint32_t>(arrays_vector.size()));
|
||||||
|
for (uint32_t i = 0; i < static_cast<uint32_t>(arrays_vector.size()); i++)
|
||||||
|
createDataProperty(context, arrays, i, arrays_vector[i]);
|
||||||
|
if (tryCatch.HasCaught()) return;
|
||||||
|
info.GetReturnValue().Set(arrays);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace v8_inspector
|
53
src/inspector/v8-injected-script-host.h
Normal file
53
src/inspector/v8-injected-script-host.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef V8_INSPECTOR_V8_INJECTED_SCRIPT_HOST_H_
|
||||||
|
#define V8_INSPECTOR_V8_INJECTED_SCRIPT_HOST_H_
|
||||||
|
|
||||||
|
#include "include/v8.h"
|
||||||
|
|
||||||
|
namespace v8_inspector {
|
||||||
|
|
||||||
|
class V8InspectorImpl;
|
||||||
|
|
||||||
|
// SECURITY NOTE: Although the InjectedScriptHost is intended for use solely by
|
||||||
|
// the inspector,
|
||||||
|
// a reference to the InjectedScriptHost may be leaked to the page being
|
||||||
|
// inspected. Thus, the
|
||||||
|
// InjectedScriptHost must never implemment methods that have more power over
|
||||||
|
// the page than the
|
||||||
|
// page already has itself (e.g. origin restriction bypasses).
|
||||||
|
|
||||||
|
class V8InjectedScriptHost {
|
||||||
|
public:
|
||||||
|
// We expect that debugger outlives any JS context and thus
|
||||||
|
// V8InjectedScriptHost (owned by JS)
|
||||||
|
// is destroyed before inspector.
|
||||||
|
static v8::Local<v8::Object> create(v8::Local<v8::Context>, V8InspectorImpl*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void nullifyPrototypeCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>&);
|
||||||
|
static void getPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>&);
|
||||||
|
static void internalConstructorNameCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>&);
|
||||||
|
static void formatAccessorsAsProperties(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>&);
|
||||||
|
static void subtypeCallback(const v8::FunctionCallbackInfo<v8::Value>&);
|
||||||
|
static void getInternalPropertiesCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>&);
|
||||||
|
static void objectHasOwnPropertyCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>&);
|
||||||
|
static void bindCallback(const v8::FunctionCallbackInfo<v8::Value>&);
|
||||||
|
static void proxyTargetValueCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>&);
|
||||||
|
static void nativeAccessorDescriptorCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>&);
|
||||||
|
static void typedArrayPropertiesCallback(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace v8_inspector
|
||||||
|
|
||||||
|
#endif // V8_INSPECTOR_V8_INJECTED_SCRIPT_HOST_H_
|
@ -203,7 +203,12 @@ Response V8InspectorSessionImpl::findInjectedScript(
|
|||||||
if (!context) return Response::Error("Cannot find context with specified id");
|
if (!context) return Response::Error("Cannot find context with specified id");
|
||||||
injectedScript = context->getInjectedScript(m_sessionId);
|
injectedScript = context->getInjectedScript(m_sessionId);
|
||||||
if (!injectedScript) {
|
if (!injectedScript) {
|
||||||
injectedScript = context->createInjectedScript(m_sessionId);
|
if (!context->createInjectedScript(m_sessionId)) {
|
||||||
|
if (m_inspector->isolate()->IsExecutionTerminating())
|
||||||
|
return Response::Error("Execution was terminated");
|
||||||
|
return Response::Error("Cannot access specified execution context");
|
||||||
|
}
|
||||||
|
injectedScript = context->getInjectedScript(m_sessionId);
|
||||||
if (m_customObjectFormatterEnabled)
|
if (m_customObjectFormatterEnabled)
|
||||||
injectedScript->setCustomObjectFormatterEnabled(true);
|
injectedScript->setCustomObjectFormatterEnabled(true);
|
||||||
}
|
}
|
||||||
@ -280,16 +285,14 @@ V8InspectorSessionImpl::wrapObject(v8::Local<v8::Context> context,
|
|||||||
findInjectedScript(InspectedContext::contextId(context), injectedScript);
|
findInjectedScript(InspectedContext::contextId(context), injectedScript);
|
||||||
if (!injectedScript) return nullptr;
|
if (!injectedScript) return nullptr;
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject> result;
|
std::unique_ptr<protocol::Runtime::RemoteObject> result;
|
||||||
injectedScript->wrapObject(
|
injectedScript->wrapObject(value, groupName, false, generatePreview, &result);
|
||||||
value, groupName,
|
|
||||||
generatePreview ? WrapMode::kWithPreview : WrapMode::kNoPreview, &result);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject>
|
std::unique_ptr<protocol::Runtime::RemoteObject>
|
||||||
V8InspectorSessionImpl::wrapTable(v8::Local<v8::Context> context,
|
V8InspectorSessionImpl::wrapTable(v8::Local<v8::Context> context,
|
||||||
v8::Local<v8::Object> table,
|
v8::Local<v8::Value> table,
|
||||||
v8::MaybeLocal<v8::Array> columns) {
|
v8::Local<v8::Value> columns) {
|
||||||
InjectedScript* injectedScript = nullptr;
|
InjectedScript* injectedScript = nullptr;
|
||||||
findInjectedScript(InspectedContext::contextId(context), injectedScript);
|
findInjectedScript(InspectedContext::contextId(context), injectedScript);
|
||||||
if (!injectedScript) return nullptr;
|
if (!injectedScript) return nullptr;
|
||||||
|
@ -55,8 +55,8 @@ class V8InspectorSessionImpl : public V8InspectorSession,
|
|||||||
v8::Local<v8::Context>, v8::Local<v8::Value>, const String16& groupName,
|
v8::Local<v8::Context>, v8::Local<v8::Value>, const String16& groupName,
|
||||||
bool generatePreview);
|
bool generatePreview);
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject> wrapTable(
|
std::unique_ptr<protocol::Runtime::RemoteObject> wrapTable(
|
||||||
v8::Local<v8::Context>, v8::Local<v8::Object> table,
|
v8::Local<v8::Context>, v8::Local<v8::Value> table,
|
||||||
v8::MaybeLocal<v8::Array> columns);
|
v8::Local<v8::Value> columns);
|
||||||
std::vector<std::unique_ptr<protocol::Schema::Domain>> supportedDomainsImpl();
|
std::vector<std::unique_ptr<protocol::Schema::Domain>> supportedDomainsImpl();
|
||||||
Response unwrapObject(const String16& objectId, v8::Local<v8::Value>*,
|
Response unwrapObject(const String16& objectId, v8::Local<v8::Value>*,
|
||||||
v8::Local<v8::Context>*, String16* objectGroup);
|
v8::Local<v8::Context>*, String16* objectGroup);
|
||||||
|
75
src/inspector/v8-internal-value-type.cc
Normal file
75
src/inspector/v8-internal-value-type.cc
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "src/inspector/v8-internal-value-type.h"
|
||||||
|
|
||||||
|
#include "src/inspector/string-util.h"
|
||||||
|
|
||||||
|
namespace v8_inspector {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
v8::Local<v8::Private> internalSubtypePrivate(v8::Isolate* isolate) {
|
||||||
|
return v8::Private::ForApi(
|
||||||
|
isolate,
|
||||||
|
toV8StringInternalized(isolate, "V8InternalType#internalSubtype"));
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::String> subtypeForInternalType(v8::Isolate* isolate,
|
||||||
|
V8InternalValueType type) {
|
||||||
|
switch (type) {
|
||||||
|
case V8InternalValueType::kEntry:
|
||||||
|
return toV8StringInternalized(isolate, "internal#entry");
|
||||||
|
case V8InternalValueType::kLocation:
|
||||||
|
return toV8StringInternalized(isolate, "internal#location");
|
||||||
|
case V8InternalValueType::kScope:
|
||||||
|
return toV8StringInternalized(isolate, "internal#scope");
|
||||||
|
case V8InternalValueType::kScopeList:
|
||||||
|
return toV8StringInternalized(isolate, "internal#scopeList");
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool markAsInternal(v8::Local<v8::Context> context,
|
||||||
|
v8::Local<v8::Object> object, V8InternalValueType type) {
|
||||||
|
v8::Isolate* isolate = context->GetIsolate();
|
||||||
|
v8::Local<v8::Private> privateValue = internalSubtypePrivate(isolate);
|
||||||
|
v8::Local<v8::String> subtype = subtypeForInternalType(isolate, type);
|
||||||
|
return object->SetPrivate(context, privateValue, subtype).FromMaybe(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool markArrayEntriesAsInternal(v8::Local<v8::Context> context,
|
||||||
|
v8::Local<v8::Array> array,
|
||||||
|
V8InternalValueType type) {
|
||||||
|
v8::Isolate* isolate = context->GetIsolate();
|
||||||
|
v8::Local<v8::Private> privateValue = internalSubtypePrivate(isolate);
|
||||||
|
v8::Local<v8::String> subtype = subtypeForInternalType(isolate, type);
|
||||||
|
for (uint32_t i = 0; i < array->Length(); ++i) {
|
||||||
|
v8::Local<v8::Value> entry;
|
||||||
|
if (!array->Get(context, i).ToLocal(&entry) || !entry->IsObject())
|
||||||
|
return false;
|
||||||
|
if (!entry.As<v8::Object>()
|
||||||
|
->SetPrivate(context, privateValue, subtype)
|
||||||
|
.FromMaybe(false))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Value> v8InternalValueTypeFrom(v8::Local<v8::Context> context,
|
||||||
|
v8::Local<v8::Object> object) {
|
||||||
|
v8::Isolate* isolate = context->GetIsolate();
|
||||||
|
v8::Local<v8::Private> privateValue = internalSubtypePrivate(isolate);
|
||||||
|
if (!object->HasPrivate(context, privateValue).FromMaybe(false))
|
||||||
|
return v8::Null(isolate);
|
||||||
|
v8::Local<v8::Value> subtypeValue;
|
||||||
|
if (!object->GetPrivate(context, privateValue).ToLocal(&subtypeValue) ||
|
||||||
|
!subtypeValue->IsString())
|
||||||
|
return v8::Null(isolate);
|
||||||
|
return subtypeValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace v8_inspector
|
23
src/inspector/v8-internal-value-type.h
Normal file
23
src/inspector/v8-internal-value-type.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef V8_INSPECTOR_V8_INTERNAL_VALUE_TYPE_H_
|
||||||
|
#define V8_INSPECTOR_V8_INTERNAL_VALUE_TYPE_H_
|
||||||
|
|
||||||
|
#include "include/v8.h"
|
||||||
|
|
||||||
|
namespace v8_inspector {
|
||||||
|
|
||||||
|
enum class V8InternalValueType { kEntry, kLocation, kScope, kScopeList };
|
||||||
|
|
||||||
|
bool markAsInternal(v8::Local<v8::Context>, v8::Local<v8::Object>,
|
||||||
|
V8InternalValueType);
|
||||||
|
bool markArrayEntriesAsInternal(v8::Local<v8::Context>, v8::Local<v8::Array>,
|
||||||
|
V8InternalValueType);
|
||||||
|
v8::Local<v8::Value> v8InternalValueTypeFrom(v8::Local<v8::Context>,
|
||||||
|
v8::Local<v8::Object>);
|
||||||
|
|
||||||
|
} // namespace v8_inspector
|
||||||
|
|
||||||
|
#endif // V8_INSPECTOR_V8_INTERNAL_VALUE_TYPE_H_
|
@ -90,14 +90,14 @@ template <typename ProtocolCallback>
|
|||||||
bool wrapEvaluateResultAsync(InjectedScript* injectedScript,
|
bool wrapEvaluateResultAsync(InjectedScript* injectedScript,
|
||||||
v8::MaybeLocal<v8::Value> maybeResultValue,
|
v8::MaybeLocal<v8::Value> maybeResultValue,
|
||||||
const v8::TryCatch& tryCatch,
|
const v8::TryCatch& tryCatch,
|
||||||
const String16& objectGroup, WrapMode wrapMode,
|
const String16& objectGroup, bool returnByValue,
|
||||||
ProtocolCallback* callback) {
|
bool generatePreview, ProtocolCallback* callback) {
|
||||||
std::unique_ptr<RemoteObject> result;
|
std::unique_ptr<RemoteObject> result;
|
||||||
Maybe<protocol::Runtime::ExceptionDetails> exceptionDetails;
|
Maybe<protocol::Runtime::ExceptionDetails> exceptionDetails;
|
||||||
|
|
||||||
Response response = injectedScript->wrapEvaluateResult(
|
Response response = injectedScript->wrapEvaluateResult(
|
||||||
maybeResultValue, tryCatch, objectGroup, wrapMode, &result,
|
maybeResultValue, tryCatch, objectGroup, returnByValue, generatePreview,
|
||||||
&exceptionDetails);
|
&result, &exceptionDetails);
|
||||||
if (response.isSuccess()) {
|
if (response.isSuccess()) {
|
||||||
callback->sendSuccess(std::move(result), std::move(exceptionDetails));
|
callback->sendSuccess(std::move(result), std::move(exceptionDetails));
|
||||||
return true;
|
return true;
|
||||||
@ -110,8 +110,8 @@ void innerCallFunctionOn(
|
|||||||
V8InspectorSessionImpl* session, InjectedScript::Scope& scope,
|
V8InspectorSessionImpl* session, InjectedScript::Scope& scope,
|
||||||
v8::Local<v8::Value> recv, const String16& expression,
|
v8::Local<v8::Value> recv, const String16& expression,
|
||||||
Maybe<protocol::Array<protocol::Runtime::CallArgument>> optionalArguments,
|
Maybe<protocol::Array<protocol::Runtime::CallArgument>> optionalArguments,
|
||||||
bool silent, WrapMode wrapMode, bool userGesture, bool awaitPromise,
|
bool silent, bool returnByValue, bool generatePreview, bool userGesture,
|
||||||
const String16& objectGroup,
|
bool awaitPromise, const String16& objectGroup,
|
||||||
std::unique_ptr<V8RuntimeAgentImpl::CallFunctionOnCallback> callback) {
|
std::unique_ptr<V8RuntimeAgentImpl::CallFunctionOnCallback> callback) {
|
||||||
V8InspectorImpl* inspector = session->inspector();
|
V8InspectorImpl* inspector = session->inspector();
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ void innerCallFunctionOn(
|
|||||||
|
|
||||||
if (scope.tryCatch().HasCaught()) {
|
if (scope.tryCatch().HasCaught()) {
|
||||||
wrapEvaluateResultAsync(scope.injectedScript(), maybeFunctionValue,
|
wrapEvaluateResultAsync(scope.injectedScript(), maybeFunctionValue,
|
||||||
scope.tryCatch(), objectGroup, WrapMode::kNoPreview,
|
scope.tryCatch(), objectGroup, false, false,
|
||||||
callback.get());
|
callback.get());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -189,13 +189,13 @@ void innerCallFunctionOn(
|
|||||||
|
|
||||||
if (!awaitPromise || scope.tryCatch().HasCaught()) {
|
if (!awaitPromise || scope.tryCatch().HasCaught()) {
|
||||||
wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
|
wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
|
||||||
scope.tryCatch(), objectGroup, wrapMode,
|
scope.tryCatch(), objectGroup, returnByValue,
|
||||||
callback.get());
|
generatePreview, callback.get());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.injectedScript()->addPromiseCallback(
|
scope.injectedScript()->addPromiseCallback(
|
||||||
session, maybeResultValue, objectGroup, wrapMode,
|
session, maybeResultValue, objectGroup, returnByValue, generatePreview,
|
||||||
EvaluateCallbackWrapper<V8RuntimeAgentImpl::CallFunctionOnCallback>::wrap(
|
EvaluateCallbackWrapper<V8RuntimeAgentImpl::CallFunctionOnCallback>::wrap(
|
||||||
std::move(callback)));
|
std::move(callback)));
|
||||||
}
|
}
|
||||||
@ -284,17 +284,16 @@ void V8RuntimeAgentImpl::evaluate(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WrapMode mode = generatePreview.fromMaybe(false) ? WrapMode::kWithPreview
|
|
||||||
: WrapMode::kNoPreview;
|
|
||||||
if (returnByValue.fromMaybe(false)) mode = WrapMode::kForceValue;
|
|
||||||
if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) {
|
if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) {
|
||||||
wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
|
wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
|
||||||
scope.tryCatch(), objectGroup.fromMaybe(""), mode,
|
scope.tryCatch(), objectGroup.fromMaybe(""),
|
||||||
callback.get());
|
returnByValue.fromMaybe(false),
|
||||||
|
generatePreview.fromMaybe(false), callback.get());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scope.injectedScript()->addPromiseCallback(
|
scope.injectedScript()->addPromiseCallback(
|
||||||
m_session, maybeResultValue, objectGroup.fromMaybe(""), mode,
|
m_session, maybeResultValue, objectGroup.fromMaybe(""),
|
||||||
|
returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
|
||||||
EvaluateCallbackWrapper<EvaluateCallback>::wrap(std::move(callback)));
|
EvaluateCallbackWrapper<EvaluateCallback>::wrap(std::move(callback)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,11 +312,9 @@ void V8RuntimeAgentImpl::awaitPromise(
|
|||||||
Response::Error("Could not find promise with given id"));
|
Response::Error("Could not find promise with given id"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WrapMode mode = generatePreview.fromMaybe(false) ? WrapMode::kWithPreview
|
|
||||||
: WrapMode::kNoPreview;
|
|
||||||
if (returnByValue.fromMaybe(false)) mode = WrapMode::kForceValue;
|
|
||||||
scope.injectedScript()->addPromiseCallback(
|
scope.injectedScript()->addPromiseCallback(
|
||||||
m_session, scope.object(), scope.objectGroupName(), mode,
|
m_session, scope.object(), scope.objectGroupName(),
|
||||||
|
returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
|
||||||
EvaluateCallbackWrapper<AwaitPromiseCallback>::wrap(std::move(callback)));
|
EvaluateCallbackWrapper<AwaitPromiseCallback>::wrap(std::move(callback)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,9 +335,6 @@ void V8RuntimeAgentImpl::callFunctionOn(
|
|||||||
"Either ObjectId or executionContextId must be specified"));
|
"Either ObjectId or executionContextId must be specified"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WrapMode mode = generatePreview.fromMaybe(false) ? WrapMode::kWithPreview
|
|
||||||
: WrapMode::kNoPreview;
|
|
||||||
if (returnByValue.fromMaybe(false)) mode = WrapMode::kForceValue;
|
|
||||||
if (objectId.isJust()) {
|
if (objectId.isJust()) {
|
||||||
InjectedScript::ObjectScope scope(m_session, objectId.fromJust());
|
InjectedScript::ObjectScope scope(m_session, objectId.fromJust());
|
||||||
Response response = scope.initialize();
|
Response response = scope.initialize();
|
||||||
@ -348,13 +342,14 @@ void V8RuntimeAgentImpl::callFunctionOn(
|
|||||||
callback->sendFailure(response);
|
callback->sendFailure(response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
innerCallFunctionOn(m_session, scope, scope.object(), expression,
|
innerCallFunctionOn(
|
||||||
std::move(optionalArguments), silent.fromMaybe(false),
|
m_session, scope, scope.object(), expression,
|
||||||
mode, userGesture.fromMaybe(false),
|
std::move(optionalArguments), silent.fromMaybe(false),
|
||||||
awaitPromise.fromMaybe(false),
|
returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
|
||||||
objectGroup.isJust() ? objectGroup.fromMaybe(String16())
|
userGesture.fromMaybe(false), awaitPromise.fromMaybe(false),
|
||||||
: scope.objectGroupName(),
|
objectGroup.isJust() ? objectGroup.fromMaybe(String16())
|
||||||
std::move(callback));
|
: scope.objectGroupName(),
|
||||||
|
std::move(callback));
|
||||||
} else {
|
} else {
|
||||||
int contextId = 0;
|
int contextId = 0;
|
||||||
Response response =
|
Response response =
|
||||||
@ -370,11 +365,12 @@ void V8RuntimeAgentImpl::callFunctionOn(
|
|||||||
callback->sendFailure(response);
|
callback->sendFailure(response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
innerCallFunctionOn(m_session, scope, scope.context()->Global(), expression,
|
innerCallFunctionOn(
|
||||||
std::move(optionalArguments), silent.fromMaybe(false),
|
m_session, scope, scope.context()->Global(), expression,
|
||||||
mode, userGesture.fromMaybe(false),
|
std::move(optionalArguments), silent.fromMaybe(false),
|
||||||
awaitPromise.fromMaybe(false),
|
returnByValue.fromMaybe(false), generatePreview.fromMaybe(false),
|
||||||
objectGroup.fromMaybe(""), std::move(callback));
|
userGesture.fromMaybe(false), awaitPromise.fromMaybe(false),
|
||||||
|
objectGroup.fromMaybe(""), std::move(callback));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,18 +397,40 @@ Response V8RuntimeAgentImpl::getProperties(
|
|||||||
v8::Local<v8::Object> object = scope.object().As<v8::Object>();
|
v8::Local<v8::Object> object = scope.object().As<v8::Object>();
|
||||||
response = scope.injectedScript()->getProperties(
|
response = scope.injectedScript()->getProperties(
|
||||||
object, scope.objectGroupName(), ownProperties.fromMaybe(false),
|
object, scope.objectGroupName(), ownProperties.fromMaybe(false),
|
||||||
accessorPropertiesOnly.fromMaybe(false),
|
accessorPropertiesOnly.fromMaybe(false), generatePreview.fromMaybe(false),
|
||||||
generatePreview.fromMaybe(false) ? WrapMode::kWithPreview
|
|
||||||
: WrapMode::kNoPreview,
|
|
||||||
result, exceptionDetails);
|
result, exceptionDetails);
|
||||||
if (!response.isSuccess()) return response;
|
if (!response.isSuccess()) return response;
|
||||||
if (exceptionDetails->isJust() || accessorPropertiesOnly.fromMaybe(false))
|
if (exceptionDetails->isJust() || accessorPropertiesOnly.fromMaybe(false))
|
||||||
return Response::OK();
|
return Response::OK();
|
||||||
|
v8::Local<v8::Array> propertiesArray;
|
||||||
|
if (!m_inspector->debugger()
|
||||||
|
->internalProperties(scope.context(), scope.object())
|
||||||
|
.ToLocal(&propertiesArray)) {
|
||||||
|
return Response::InternalError();
|
||||||
|
}
|
||||||
std::unique_ptr<protocol::Array<InternalPropertyDescriptor>>
|
std::unique_ptr<protocol::Array<InternalPropertyDescriptor>>
|
||||||
propertiesProtocolArray;
|
propertiesProtocolArray =
|
||||||
response = scope.injectedScript()->getInternalProperties(
|
protocol::Array<InternalPropertyDescriptor>::create();
|
||||||
object, scope.objectGroupName(), &propertiesProtocolArray);
|
for (uint32_t i = 0; i < propertiesArray->Length(); i += 2) {
|
||||||
if (!response.isSuccess()) return response;
|
v8::Local<v8::Value> name;
|
||||||
|
if (!propertiesArray->Get(scope.context(), i).ToLocal(&name) ||
|
||||||
|
!name->IsString()) {
|
||||||
|
return Response::InternalError();
|
||||||
|
}
|
||||||
|
v8::Local<v8::Value> value;
|
||||||
|
if (!propertiesArray->Get(scope.context(), i + 1).ToLocal(&value))
|
||||||
|
return Response::InternalError();
|
||||||
|
std::unique_ptr<RemoteObject> wrappedValue;
|
||||||
|
protocol::Response response = scope.injectedScript()->wrapObject(
|
||||||
|
value, scope.objectGroupName(), false, false, &wrappedValue);
|
||||||
|
if (!response.isSuccess()) return response;
|
||||||
|
propertiesProtocolArray->addItem(
|
||||||
|
InternalPropertyDescriptor::create()
|
||||||
|
.setName(
|
||||||
|
toProtocolString(m_inspector->isolate(), name.As<v8::String>()))
|
||||||
|
.setValue(std::move(wrappedValue))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
if (propertiesProtocolArray->length())
|
if (propertiesProtocolArray->length())
|
||||||
*internalProperties = std::move(propertiesProtocolArray);
|
*internalProperties = std::move(propertiesProtocolArray);
|
||||||
return Response::OK();
|
return Response::OK();
|
||||||
@ -481,7 +499,7 @@ Response V8RuntimeAgentImpl::compileScript(
|
|||||||
if (!isOk) {
|
if (!isOk) {
|
||||||
if (scope.tryCatch().HasCaught()) {
|
if (scope.tryCatch().HasCaught()) {
|
||||||
response = scope.injectedScript()->createExceptionDetails(
|
response = scope.injectedScript()->createExceptionDetails(
|
||||||
scope.tryCatch(), String16(), WrapMode::kNoPreview, exceptionDetails);
|
scope.tryCatch(), String16(), false, exceptionDetails);
|
||||||
if (!response.isSuccess()) return response;
|
if (!response.isSuccess()) return response;
|
||||||
return Response::OK();
|
return Response::OK();
|
||||||
} else {
|
} else {
|
||||||
@ -559,18 +577,17 @@ void V8RuntimeAgentImpl::runScript(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WrapMode mode = generatePreview.fromMaybe(false) ? WrapMode::kWithPreview
|
|
||||||
: WrapMode::kNoPreview;
|
|
||||||
if (returnByValue.fromMaybe(false)) mode = WrapMode::kForceValue;
|
|
||||||
if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) {
|
if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) {
|
||||||
wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
|
wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
|
||||||
scope.tryCatch(), objectGroup.fromMaybe(""), mode,
|
scope.tryCatch(), objectGroup.fromMaybe(""),
|
||||||
callback.get());
|
returnByValue.fromMaybe(false),
|
||||||
|
generatePreview.fromMaybe(false), callback.get());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scope.injectedScript()->addPromiseCallback(
|
scope.injectedScript()->addPromiseCallback(
|
||||||
m_session, maybeResultValue.ToLocalChecked(), objectGroup.fromMaybe(""),
|
m_session, maybeResultValue.ToLocalChecked(),
|
||||||
mode,
|
objectGroup.fromMaybe(""), returnByValue.fromMaybe(false),
|
||||||
|
generatePreview.fromMaybe(false),
|
||||||
EvaluateCallbackWrapper<RunScriptCallback>::wrap(std::move(callback)));
|
EvaluateCallbackWrapper<RunScriptCallback>::wrap(std::move(callback)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,8 +603,8 @@ Response V8RuntimeAgentImpl::queryObjects(
|
|||||||
v8::Local<v8::Array> resultArray = m_inspector->debugger()->queryObjects(
|
v8::Local<v8::Array> resultArray = m_inspector->debugger()->queryObjects(
|
||||||
scope.context(), v8::Local<v8::Object>::Cast(scope.object()));
|
scope.context(), v8::Local<v8::Object>::Cast(scope.object()));
|
||||||
return scope.injectedScript()->wrapObject(
|
return scope.injectedScript()->wrapObject(
|
||||||
resultArray, objectGroup.fromMaybe(scope.objectGroupName()),
|
resultArray, objectGroup.fromMaybe(scope.objectGroupName()), false, false,
|
||||||
WrapMode::kNoPreview, objects);
|
objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
Response V8RuntimeAgentImpl::globalLexicalScopeNames(
|
Response V8RuntimeAgentImpl::globalLexicalScopeNames(
|
||||||
|
@ -6,6 +6,102 @@
|
|||||||
|
|
||||||
namespace v8_inspector {
|
namespace v8_inspector {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
protocol::Response toProtocolValue(v8::Local<v8::Context> context,
|
||||||
|
v8::Local<v8::Value> value, int maxDepth,
|
||||||
|
std::unique_ptr<protocol::Value>* result) {
|
||||||
|
using protocol::Response;
|
||||||
|
if (value.IsEmpty()) {
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!maxDepth) return Response::Error("Object reference chain is too long");
|
||||||
|
maxDepth--;
|
||||||
|
|
||||||
|
if (value->IsNull() || value->IsUndefined()) {
|
||||||
|
*result = protocol::Value::null();
|
||||||
|
return Response::OK();
|
||||||
|
}
|
||||||
|
if (value->IsBoolean()) {
|
||||||
|
*result =
|
||||||
|
protocol::FundamentalValue::create(value.As<v8::Boolean>()->Value());
|
||||||
|
return Response::OK();
|
||||||
|
}
|
||||||
|
if (value->IsNumber()) {
|
||||||
|
double doubleValue = value.As<v8::Number>()->Value();
|
||||||
|
int intValue = static_cast<int>(doubleValue);
|
||||||
|
if (intValue == doubleValue) {
|
||||||
|
*result = protocol::FundamentalValue::create(intValue);
|
||||||
|
return Response::OK();
|
||||||
|
}
|
||||||
|
*result = protocol::FundamentalValue::create(doubleValue);
|
||||||
|
return Response::OK();
|
||||||
|
}
|
||||||
|
if (value->IsString()) {
|
||||||
|
*result = protocol::StringValue::create(
|
||||||
|
toProtocolString(context->GetIsolate(), value.As<v8::String>()));
|
||||||
|
return Response::OK();
|
||||||
|
}
|
||||||
|
if (value->IsArray()) {
|
||||||
|
v8::Local<v8::Array> array = value.As<v8::Array>();
|
||||||
|
std::unique_ptr<protocol::ListValue> inspectorArray =
|
||||||
|
protocol::ListValue::create();
|
||||||
|
uint32_t length = array->Length();
|
||||||
|
for (uint32_t i = 0; i < length; i++) {
|
||||||
|
v8::Local<v8::Value> value;
|
||||||
|
if (!array->Get(context, i).ToLocal(&value))
|
||||||
|
return Response::InternalError();
|
||||||
|
std::unique_ptr<protocol::Value> element;
|
||||||
|
Response response = toProtocolValue(context, value, maxDepth, &element);
|
||||||
|
if (!response.isSuccess()) return response;
|
||||||
|
inspectorArray->pushValue(std::move(element));
|
||||||
|
}
|
||||||
|
*result = std::move(inspectorArray);
|
||||||
|
return Response::OK();
|
||||||
|
}
|
||||||
|
if (value->IsObject()) {
|
||||||
|
std::unique_ptr<protocol::DictionaryValue> jsonObject =
|
||||||
|
protocol::DictionaryValue::create();
|
||||||
|
v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
|
||||||
|
v8::Local<v8::Array> propertyNames;
|
||||||
|
if (!object->GetPropertyNames(context).ToLocal(&propertyNames))
|
||||||
|
return Response::InternalError();
|
||||||
|
uint32_t length = propertyNames->Length();
|
||||||
|
for (uint32_t i = 0; i < length; i++) {
|
||||||
|
v8::Local<v8::Value> name;
|
||||||
|
if (!propertyNames->Get(context, i).ToLocal(&name))
|
||||||
|
return Response::InternalError();
|
||||||
|
// FIXME(yurys): v8::Object should support GetOwnPropertyNames
|
||||||
|
if (name->IsString()) {
|
||||||
|
v8::Maybe<bool> hasRealNamedProperty = object->HasRealNamedProperty(
|
||||||
|
context, v8::Local<v8::String>::Cast(name));
|
||||||
|
if (hasRealNamedProperty.IsNothing() ||
|
||||||
|
!hasRealNamedProperty.FromJust())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
v8::Local<v8::String> propertyName;
|
||||||
|
if (!name->ToString(context).ToLocal(&propertyName)) continue;
|
||||||
|
v8::Local<v8::Value> property;
|
||||||
|
if (!object->Get(context, name).ToLocal(&property))
|
||||||
|
return Response::InternalError();
|
||||||
|
if (property->IsUndefined()) continue;
|
||||||
|
std::unique_ptr<protocol::Value> propertyValue;
|
||||||
|
Response response =
|
||||||
|
toProtocolValue(context, property, maxDepth, &propertyValue);
|
||||||
|
if (!response.isSuccess()) return response;
|
||||||
|
jsonObject->setValue(
|
||||||
|
toProtocolString(context->GetIsolate(), propertyName),
|
||||||
|
std::move(propertyValue));
|
||||||
|
}
|
||||||
|
*result = std::move(jsonObject);
|
||||||
|
return Response::OK();
|
||||||
|
}
|
||||||
|
return Response::Error("Object couldn't be returned by value");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
v8::Maybe<bool> createDataProperty(v8::Local<v8::Context> context,
|
v8::Maybe<bool> createDataProperty(v8::Local<v8::Context> context,
|
||||||
v8::Local<v8::Object> object,
|
v8::Local<v8::Object> object,
|
||||||
v8::Local<v8::Name> key,
|
v8::Local<v8::Name> key,
|
||||||
@ -26,4 +122,11 @@ v8::Maybe<bool> createDataProperty(v8::Local<v8::Context> context,
|
|||||||
v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
|
v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
|
||||||
return array->CreateDataProperty(context, index, value);
|
return array->CreateDataProperty(context, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protocol::Response toProtocolValue(v8::Local<v8::Context> context,
|
||||||
|
v8::Local<v8::Value> value,
|
||||||
|
std::unique_ptr<protocol::Value>* result) {
|
||||||
|
return toProtocolValue(context, value, 1000, result);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace v8_inspector
|
} // namespace v8_inspector
|
||||||
|
@ -18,6 +18,9 @@ v8::Maybe<bool> createDataProperty(v8::Local<v8::Context>,
|
|||||||
v8::Maybe<bool> createDataProperty(v8::Local<v8::Context>, v8::Local<v8::Array>,
|
v8::Maybe<bool> createDataProperty(v8::Local<v8::Context>, v8::Local<v8::Array>,
|
||||||
int index, v8::Local<v8::Value>);
|
int index, v8::Local<v8::Value>);
|
||||||
|
|
||||||
|
protocol::Response toProtocolValue(v8::Local<v8::Context>, v8::Local<v8::Value>,
|
||||||
|
std::unique_ptr<protocol::Value>* result);
|
||||||
|
|
||||||
} // namespace v8_inspector
|
} // namespace v8_inspector
|
||||||
|
|
||||||
#endif // V8_INSPECTOR_V8_VALUE_UTILS_H_
|
#endif // V8_INSPECTOR_V8_VALUE_UTILS_H_
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,79 +0,0 @@
|
|||||||
// Copyright 2018 the V8 project authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef V8_INSPECTOR_VALUE_MIRROR_H_
|
|
||||||
#define V8_INSPECTOR_VALUE_MIRROR_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "src/base/macros.h"
|
|
||||||
#include "src/inspector/protocol/Protocol.h"
|
|
||||||
#include "src/inspector/protocol/Runtime.h"
|
|
||||||
#include "src/inspector/string-16.h"
|
|
||||||
|
|
||||||
#include "include/v8-inspector.h"
|
|
||||||
#include "include/v8.h"
|
|
||||||
|
|
||||||
namespace v8_inspector {
|
|
||||||
|
|
||||||
class ValueMirror;
|
|
||||||
enum class WrapMode;
|
|
||||||
|
|
||||||
struct InternalPropertyMirror {
|
|
||||||
String16 name;
|
|
||||||
std::unique_ptr<ValueMirror> value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PropertyMirror {
|
|
||||||
String16 name;
|
|
||||||
bool writable;
|
|
||||||
bool configurable;
|
|
||||||
bool enumerable;
|
|
||||||
bool isOwn;
|
|
||||||
bool isIndex;
|
|
||||||
std::unique_ptr<ValueMirror> value;
|
|
||||||
std::unique_ptr<ValueMirror> getter;
|
|
||||||
std::unique_ptr<ValueMirror> setter;
|
|
||||||
std::unique_ptr<ValueMirror> symbol;
|
|
||||||
std::unique_ptr<ValueMirror> exception;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ValueMirror {
|
|
||||||
public:
|
|
||||||
virtual ~ValueMirror();
|
|
||||||
|
|
||||||
static std::unique_ptr<ValueMirror> create(v8::Local<v8::Context> context,
|
|
||||||
v8::Local<v8::Value> value);
|
|
||||||
virtual protocol::Response buildRemoteObject(
|
|
||||||
v8::Local<v8::Context> context, WrapMode mode,
|
|
||||||
std::unique_ptr<protocol::Runtime::RemoteObject>* result) = 0;
|
|
||||||
virtual void buildPropertyPreview(
|
|
||||||
v8::Local<v8::Context> context, const String16& name,
|
|
||||||
std::unique_ptr<protocol::Runtime::PropertyPreview>*) {}
|
|
||||||
virtual void buildObjectPreview(
|
|
||||||
v8::Local<v8::Context> context, bool generatePreviewForProperties,
|
|
||||||
int* nameLimit, int* indexLimit,
|
|
||||||
std::unique_ptr<protocol::Runtime::ObjectPreview>*) {}
|
|
||||||
virtual void buildEntryPreview(
|
|
||||||
v8::Local<v8::Context> context, bool generatePreviewForProperties,
|
|
||||||
int* nameLimit, int* indexLimit,
|
|
||||||
std::unique_ptr<protocol::Runtime::ObjectPreview>*) {}
|
|
||||||
virtual v8::Local<v8::Value> v8Value() = 0;
|
|
||||||
|
|
||||||
class PropertyAccumulator {
|
|
||||||
public:
|
|
||||||
virtual ~PropertyAccumulator() = default;
|
|
||||||
virtual bool Add(PropertyMirror mirror) = 0;
|
|
||||||
};
|
|
||||||
static bool getProperties(v8::Local<v8::Context> context,
|
|
||||||
v8::Local<v8::Object> object, bool ownProperties,
|
|
||||||
bool accessorPropertiesOnly,
|
|
||||||
PropertyAccumulator* accumulator);
|
|
||||||
static void getInternalProperties(
|
|
||||||
v8::Local<v8::Context> context, v8::Local<v8::Object> object,
|
|
||||||
std::vector<InternalPropertyMirror>* mirrors);
|
|
||||||
};
|
|
||||||
} // namespace v8_inspector
|
|
||||||
|
|
||||||
#endif // V8_INSPECTOR_VALUE_MIRROR_H_
|
|
@ -44,6 +44,7 @@ v8_executable("inspector-test") {
|
|||||||
"sessions/",
|
"sessions/",
|
||||||
"testcfg.py",
|
"testcfg.py",
|
||||||
"type-profiler/",
|
"type-profiler/",
|
||||||
|
"../../src/inspector/injected-script-source.js",
|
||||||
]
|
]
|
||||||
|
|
||||||
cflags = []
|
cflags = []
|
||||||
|
@ -26,7 +26,18 @@ expression: Object(Symbol(42))
|
|||||||
{
|
{
|
||||||
name : [[PrimitiveValue]]
|
name : [[PrimitiveValue]]
|
||||||
type : symbol
|
type : symbol
|
||||||
value : Symbol(42)
|
valuePreview : {
|
||||||
|
description : Symbol
|
||||||
|
overflow : false
|
||||||
|
properties : [
|
||||||
|
[0] : {
|
||||||
|
name : description
|
||||||
|
type : string
|
||||||
|
value : 42
|
||||||
|
}
|
||||||
|
]
|
||||||
|
type : object
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expression: Object(BigInt(2))
|
expression: Object(BigInt(2))
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
Tests that stepping ignores injected script
|
||||||
|
InjectedSciptSource was not reached
|
21
test/inspector/debugger/stepping-ignores-injected-script.js
Normal file
21
test/inspector/debugger/stepping-ignores-injected-script.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
let {session, contextGroup, Protocol} = InspectorTest.start('Tests that stepping ignores injected script');
|
||||||
|
|
||||||
|
Protocol.Debugger.onPaused(message => {
|
||||||
|
let url = session._scriptMap.get(message.params.callFrames[0].location.scriptId).url;
|
||||||
|
if (url !== 'test.js') {
|
||||||
|
InspectorTest.log('InjectedSciptSource on stack.');
|
||||||
|
InspectorTest.completeTest();
|
||||||
|
}
|
||||||
|
Protocol.Debugger.stepInto();
|
||||||
|
});
|
||||||
|
|
||||||
|
session.setupScriptMap();
|
||||||
|
Protocol.Debugger.enable();
|
||||||
|
Protocol.Debugger.pause();
|
||||||
|
Protocol.Runtime.evaluate({expression: 'console.log(42)//# sourceURL=test.js'})
|
||||||
|
.then(() => InspectorTest.log('InjectedSciptSource was not reached'))
|
||||||
|
.then(InspectorTest.completeTest);
|
@ -0,0 +1,2 @@
|
|||||||
|
Tests that stepping does not ignore injected script when passed a flag
|
||||||
|
InjectedSciptSource on stack.
|
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
// Flags: --expose-inspector-scripts
|
||||||
|
|
||||||
|
let {session, contextGroup, Protocol} = InspectorTest.start('Tests that stepping does not ignore injected script when passed a flag');
|
||||||
|
|
||||||
|
Protocol.Debugger.onPaused(message => {
|
||||||
|
let url = session._scriptMap.get(message.params.callFrames[0].location.scriptId).url;
|
||||||
|
if (url !== 'test.js') {
|
||||||
|
InspectorTest.log('InjectedSciptSource on stack.');
|
||||||
|
InspectorTest.completeTest();
|
||||||
|
}
|
||||||
|
Protocol.Debugger.stepInto();
|
||||||
|
});
|
||||||
|
|
||||||
|
session.setupScriptMap();
|
||||||
|
Protocol.Debugger.enable();
|
||||||
|
Protocol.Debugger.pause();
|
||||||
|
Protocol.Runtime.evaluate({expression: 'console.log(42)//# sourceURL=test.js'})
|
||||||
|
.then(() => InspectorTest.log('InjectedSciptSource was not reached'))
|
||||||
|
.then(InspectorTest.completeTest);
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
['system == android', {
|
['system == android', {
|
||||||
|
# https://crbug.com/v8/8160
|
||||||
|
'debugger/stepping-with-exposed-injected-script': [FAIL],
|
||||||
# https://crbug.com/v8/8197
|
# https://crbug.com/v8/8197
|
||||||
'debugger/get-possible-breakpoints-class-fields': [SKIP],
|
'debugger/get-possible-breakpoints-class-fields': [SKIP],
|
||||||
}], # 'system == android'
|
}], # 'system == android'
|
||||||
|
@ -176,6 +176,8 @@ InspectorTest.ContextGroup = class {
|
|||||||
|
|
||||||
if (session) {
|
if (session) {
|
||||||
InspectorTest.log('WARNING: setupInjectedScriptEnvironment with debug flag for debugging only and should not be landed.');
|
InspectorTest.log('WARNING: setupInjectedScriptEnvironment with debug flag for debugging only and should not be landed.');
|
||||||
|
InspectorTest.log('WARNING: run test with --expose-inspector-scripts flag to get more details.');
|
||||||
|
InspectorTest.log('WARNING: you can additionally comment rjsmin in xxd.py to get unminified injected-script-source.js.');
|
||||||
session.setupScriptMap();
|
session.setupScriptMap();
|
||||||
session.Protocol.Debugger.enable();
|
session.Protocol.Debugger.enable();
|
||||||
session.Protocol.Debugger.onPaused(message => {
|
session.Protocol.Debugger.onPaused(message => {
|
||||||
|
@ -239,7 +239,6 @@ Checks console methods
|
|||||||
name : 0
|
name : 0
|
||||||
subtype : array
|
subtype : array
|
||||||
type : object
|
type : object
|
||||||
value : Array(2)
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Array(2)
|
description : Array(2)
|
||||||
overflow : false
|
overflow : false
|
||||||
@ -263,7 +262,6 @@ Checks console methods
|
|||||||
name : 1
|
name : 1
|
||||||
subtype : array
|
subtype : array
|
||||||
type : object
|
type : object
|
||||||
value : Array(2)
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Array(2)
|
description : Array(2)
|
||||||
overflow : false
|
overflow : false
|
||||||
@ -330,7 +328,6 @@ Checks console methods
|
|||||||
name : 0
|
name : 0
|
||||||
subtype : array
|
subtype : array
|
||||||
type : object
|
type : object
|
||||||
value : Array(2)
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Array(2)
|
description : Array(2)
|
||||||
overflow : false
|
overflow : false
|
||||||
@ -349,7 +346,6 @@ Checks console methods
|
|||||||
name : 1
|
name : 1
|
||||||
subtype : array
|
subtype : array
|
||||||
type : object
|
type : object
|
||||||
value : Array(2)
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Array(2)
|
description : Array(2)
|
||||||
overflow : false
|
overflow : false
|
||||||
|
@ -47,9 +47,8 @@ console.table
|
|||||||
name : 0
|
name : 0
|
||||||
subtype : array
|
subtype : array
|
||||||
type : object
|
type : object
|
||||||
value : Array(2)
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Array(2)
|
description : Array(3)
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
@ -71,9 +70,8 @@ console.table
|
|||||||
name : 1
|
name : 1
|
||||||
subtype : array
|
subtype : array
|
||||||
type : object
|
type : object
|
||||||
value : Array(2)
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Array(2)
|
description : Array(3)
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
@ -95,9 +93,8 @@ console.table
|
|||||||
name : 2
|
name : 2
|
||||||
subtype : array
|
subtype : array
|
||||||
type : object
|
type : object
|
||||||
value : Array(2)
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Array(2)
|
description : Array(3)
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
@ -126,9 +123,8 @@ console.table
|
|||||||
[0] : {
|
[0] : {
|
||||||
name : 0
|
name : 0
|
||||||
type : object
|
type : object
|
||||||
value : Person
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Person
|
description : Array(3)
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
@ -142,15 +138,15 @@ console.table
|
|||||||
value : Smith
|
value : Smith
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
subtype : array
|
||||||
type : object
|
type : object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[1] : {
|
[1] : {
|
||||||
name : 1
|
name : 1
|
||||||
type : object
|
type : object
|
||||||
value : Person
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Person
|
description : Array(3)
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
@ -164,15 +160,15 @@ console.table
|
|||||||
value : Doe
|
value : Doe
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
subtype : array
|
||||||
type : object
|
type : object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[2] : {
|
[2] : {
|
||||||
name : 2
|
name : 2
|
||||||
type : object
|
type : object
|
||||||
value : Person
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Person
|
description : Array(3)
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
@ -186,6 +182,7 @@ console.table
|
|||||||
value : Jones
|
value : Jones
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
subtype : array
|
||||||
type : object
|
type : object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,9 +197,8 @@ console.table
|
|||||||
[0] : {
|
[0] : {
|
||||||
name : mother
|
name : mother
|
||||||
type : object
|
type : object
|
||||||
value : Person
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Person
|
description : Object
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
@ -222,9 +218,8 @@ console.table
|
|||||||
[1] : {
|
[1] : {
|
||||||
name : father
|
name : father
|
||||||
type : object
|
type : object
|
||||||
value : Person
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Person
|
description : Object
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
@ -244,9 +239,8 @@ console.table
|
|||||||
[2] : {
|
[2] : {
|
||||||
name : daughter
|
name : daughter
|
||||||
type : object
|
type : object
|
||||||
value : Person
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Person
|
description : Object
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
@ -273,9 +267,8 @@ console.table
|
|||||||
[0] : {
|
[0] : {
|
||||||
name : 0
|
name : 0
|
||||||
type : object
|
type : object
|
||||||
value : Person
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Person
|
description : Array(3)
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
@ -284,15 +277,15 @@ console.table
|
|||||||
value : John
|
value : John
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
subtype : array
|
||||||
type : object
|
type : object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[1] : {
|
[1] : {
|
||||||
name : 1
|
name : 1
|
||||||
type : object
|
type : object
|
||||||
value : Person
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Person
|
description : Array(3)
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
@ -301,15 +294,15 @@ console.table
|
|||||||
value : Jane
|
value : Jane
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
subtype : array
|
||||||
type : object
|
type : object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[2] : {
|
[2] : {
|
||||||
name : 2
|
name : 2
|
||||||
type : object
|
type : object
|
||||||
value : Person
|
|
||||||
valuePreview : {
|
valuePreview : {
|
||||||
description : Person
|
description : Array(3)
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
@ -318,6 +311,7 @@ console.table
|
|||||||
value : Emily
|
value : Emily
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
subtype : array
|
||||||
type : object
|
type : object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,10 @@ expression: (function* foo() { yield 1 })
|
|||||||
result : {
|
result : {
|
||||||
internalProperties : [
|
internalProperties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
|
name : [[StableObjectId]]
|
||||||
|
value : <StablectObjectId>
|
||||||
|
}
|
||||||
|
[1] : {
|
||||||
name : [[FunctionLocation]]
|
name : [[FunctionLocation]]
|
||||||
value : {
|
value : {
|
||||||
description : Object
|
description : Object
|
||||||
@ -19,17 +23,13 @@ expression: (function* foo() { yield 1 })
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[1] : {
|
[2] : {
|
||||||
name : [[IsGenerator]]
|
name : [[IsGenerator]]
|
||||||
value : {
|
value : {
|
||||||
type : boolean
|
type : boolean
|
||||||
value : true
|
value : true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[2] : {
|
|
||||||
name : [[StableObjectId]]
|
|
||||||
value : <StablectObjectId>
|
|
||||||
}
|
|
||||||
[3] : {
|
[3] : {
|
||||||
name : [[Scopes]]
|
name : [[Scopes]]
|
||||||
value : {
|
value : {
|
||||||
@ -51,6 +51,10 @@ expression: (function foo() {})
|
|||||||
result : {
|
result : {
|
||||||
internalProperties : [
|
internalProperties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
|
name : [[StableObjectId]]
|
||||||
|
value : <StablectObjectId>
|
||||||
|
}
|
||||||
|
[1] : {
|
||||||
name : [[FunctionLocation]]
|
name : [[FunctionLocation]]
|
||||||
value : {
|
value : {
|
||||||
description : Object
|
description : Object
|
||||||
@ -63,10 +67,6 @@ expression: (function foo() {})
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[1] : {
|
|
||||||
name : [[StableObjectId]]
|
|
||||||
value : <StablectObjectId>
|
|
||||||
}
|
|
||||||
[2] : {
|
[2] : {
|
||||||
name : [[Scopes]]
|
name : [[Scopes]]
|
||||||
value : {
|
value : {
|
||||||
@ -242,6 +242,35 @@ expression: gen1
|
|||||||
result : {
|
result : {
|
||||||
internalProperties : [
|
internalProperties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
|
name : [[GeneratorStatus]]
|
||||||
|
value : {
|
||||||
|
type : string
|
||||||
|
value : suspended
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[1] : {
|
||||||
|
name : [[GeneratorFunction]]
|
||||||
|
value : {
|
||||||
|
className : GeneratorFunction
|
||||||
|
description : function* foo() { yield 1; }
|
||||||
|
objectId : <objectId>
|
||||||
|
type : function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[2] : {
|
||||||
|
name : [[GeneratorReceiver]]
|
||||||
|
value : {
|
||||||
|
className : global
|
||||||
|
description : global
|
||||||
|
objectId : <objectId>
|
||||||
|
type : object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[3] : {
|
||||||
|
name : [[StableObjectId]]
|
||||||
|
value : <StablectObjectId>
|
||||||
|
}
|
||||||
|
[4] : {
|
||||||
name : [[GeneratorLocation]]
|
name : [[GeneratorLocation]]
|
||||||
value : {
|
value : {
|
||||||
description : Object
|
description : Object
|
||||||
@ -254,35 +283,6 @@ expression: gen1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[1] : {
|
|
||||||
name : [[GeneratorStatus]]
|
|
||||||
value : {
|
|
||||||
type : string
|
|
||||||
value : suspended
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[2] : {
|
|
||||||
name : [[GeneratorFunction]]
|
|
||||||
value : {
|
|
||||||
className : GeneratorFunction
|
|
||||||
description : function* foo() { yield 1; }
|
|
||||||
objectId : <objectId>
|
|
||||||
type : function
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[3] : {
|
|
||||||
name : [[GeneratorReceiver]]
|
|
||||||
value : {
|
|
||||||
className : global
|
|
||||||
description : global
|
|
||||||
objectId : <objectId>
|
|
||||||
type : object
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[4] : {
|
|
||||||
name : [[StableObjectId]]
|
|
||||||
value : <StablectObjectId>
|
|
||||||
}
|
|
||||||
[5] : {
|
[5] : {
|
||||||
name : [[Scopes]]
|
name : [[Scopes]]
|
||||||
value : {
|
value : {
|
||||||
@ -302,6 +302,35 @@ expression: gen1.next();gen1
|
|||||||
result : {
|
result : {
|
||||||
internalProperties : [
|
internalProperties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
|
name : [[GeneratorStatus]]
|
||||||
|
value : {
|
||||||
|
type : string
|
||||||
|
value : suspended
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[1] : {
|
||||||
|
name : [[GeneratorFunction]]
|
||||||
|
value : {
|
||||||
|
className : GeneratorFunction
|
||||||
|
description : function* foo() { yield 1; }
|
||||||
|
objectId : <objectId>
|
||||||
|
type : function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[2] : {
|
||||||
|
name : [[GeneratorReceiver]]
|
||||||
|
value : {
|
||||||
|
className : global
|
||||||
|
description : global
|
||||||
|
objectId : <objectId>
|
||||||
|
type : object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[3] : {
|
||||||
|
name : [[StableObjectId]]
|
||||||
|
value : <StablectObjectId>
|
||||||
|
}
|
||||||
|
[4] : {
|
||||||
name : [[GeneratorLocation]]
|
name : [[GeneratorLocation]]
|
||||||
value : {
|
value : {
|
||||||
description : Object
|
description : Object
|
||||||
@ -314,35 +343,6 @@ expression: gen1.next();gen1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[1] : {
|
|
||||||
name : [[GeneratorStatus]]
|
|
||||||
value : {
|
|
||||||
type : string
|
|
||||||
value : suspended
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[2] : {
|
|
||||||
name : [[GeneratorFunction]]
|
|
||||||
value : {
|
|
||||||
className : GeneratorFunction
|
|
||||||
description : function* foo() { yield 1; }
|
|
||||||
objectId : <objectId>
|
|
||||||
type : function
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[3] : {
|
|
||||||
name : [[GeneratorReceiver]]
|
|
||||||
value : {
|
|
||||||
className : global
|
|
||||||
description : global
|
|
||||||
objectId : <objectId>
|
|
||||||
type : object
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[4] : {
|
|
||||||
name : [[StableObjectId]]
|
|
||||||
value : <StablectObjectId>
|
|
||||||
}
|
|
||||||
[5] : {
|
[5] : {
|
||||||
name : [[Scopes]]
|
name : [[Scopes]]
|
||||||
value : {
|
value : {
|
||||||
@ -362,6 +362,35 @@ expression: gen1.next();gen1
|
|||||||
result : {
|
result : {
|
||||||
internalProperties : [
|
internalProperties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
|
name : [[GeneratorStatus]]
|
||||||
|
value : {
|
||||||
|
type : string
|
||||||
|
value : closed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[1] : {
|
||||||
|
name : [[GeneratorFunction]]
|
||||||
|
value : {
|
||||||
|
className : GeneratorFunction
|
||||||
|
description : function* foo() { yield 1; }
|
||||||
|
objectId : <objectId>
|
||||||
|
type : function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[2] : {
|
||||||
|
name : [[GeneratorReceiver]]
|
||||||
|
value : {
|
||||||
|
className : global
|
||||||
|
description : global
|
||||||
|
objectId : <objectId>
|
||||||
|
type : object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[3] : {
|
||||||
|
name : [[StableObjectId]]
|
||||||
|
value : <StablectObjectId>
|
||||||
|
}
|
||||||
|
[4] : {
|
||||||
name : [[GeneratorLocation]]
|
name : [[GeneratorLocation]]
|
||||||
value : {
|
value : {
|
||||||
description : Object
|
description : Object
|
||||||
@ -374,35 +403,6 @@ expression: gen1.next();gen1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[1] : {
|
|
||||||
name : [[GeneratorStatus]]
|
|
||||||
value : {
|
|
||||||
type : string
|
|
||||||
value : closed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[2] : {
|
|
||||||
name : [[GeneratorFunction]]
|
|
||||||
value : {
|
|
||||||
className : GeneratorFunction
|
|
||||||
description : function* foo() { yield 1; }
|
|
||||||
objectId : <objectId>
|
|
||||||
type : function
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[3] : {
|
|
||||||
name : [[GeneratorReceiver]]
|
|
||||||
value : {
|
|
||||||
className : global
|
|
||||||
description : global
|
|
||||||
objectId : <objectId>
|
|
||||||
type : object
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[4] : {
|
|
||||||
name : [[StableObjectId]]
|
|
||||||
value : <StablectObjectId>
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -414,6 +414,35 @@ expression: gen2
|
|||||||
result : {
|
result : {
|
||||||
internalProperties : [
|
internalProperties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
|
name : [[GeneratorStatus]]
|
||||||
|
value : {
|
||||||
|
type : string
|
||||||
|
value : suspended
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[1] : {
|
||||||
|
name : [[GeneratorFunction]]
|
||||||
|
value : {
|
||||||
|
className : GeneratorFunction
|
||||||
|
description : function* foo() { yield 1; }
|
||||||
|
objectId : <objectId>
|
||||||
|
type : function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[2] : {
|
||||||
|
name : [[GeneratorReceiver]]
|
||||||
|
value : {
|
||||||
|
className : global
|
||||||
|
description : global
|
||||||
|
objectId : <objectId>
|
||||||
|
type : object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[3] : {
|
||||||
|
name : [[StableObjectId]]
|
||||||
|
value : <StablectObjectId>
|
||||||
|
}
|
||||||
|
[4] : {
|
||||||
name : [[GeneratorLocation]]
|
name : [[GeneratorLocation]]
|
||||||
value : {
|
value : {
|
||||||
description : Object
|
description : Object
|
||||||
@ -426,35 +455,6 @@ expression: gen2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[1] : {
|
|
||||||
name : [[GeneratorStatus]]
|
|
||||||
value : {
|
|
||||||
type : string
|
|
||||||
value : suspended
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[2] : {
|
|
||||||
name : [[GeneratorFunction]]
|
|
||||||
value : {
|
|
||||||
className : GeneratorFunction
|
|
||||||
description : function* foo() { yield 1; }
|
|
||||||
objectId : <objectId>
|
|
||||||
type : function
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[3] : {
|
|
||||||
name : [[GeneratorReceiver]]
|
|
||||||
value : {
|
|
||||||
className : global
|
|
||||||
description : global
|
|
||||||
objectId : <objectId>
|
|
||||||
type : object
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[4] : {
|
|
||||||
name : [[StableObjectId]]
|
|
||||||
value : <StablectObjectId>
|
|
||||||
}
|
|
||||||
[5] : {
|
[5] : {
|
||||||
name : [[Scopes]]
|
name : [[Scopes]]
|
||||||
value : {
|
value : {
|
||||||
@ -474,6 +474,35 @@ expression: gen2.next();gen2
|
|||||||
result : {
|
result : {
|
||||||
internalProperties : [
|
internalProperties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
|
name : [[GeneratorStatus]]
|
||||||
|
value : {
|
||||||
|
type : string
|
||||||
|
value : suspended
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[1] : {
|
||||||
|
name : [[GeneratorFunction]]
|
||||||
|
value : {
|
||||||
|
className : GeneratorFunction
|
||||||
|
description : function* foo() { yield 1; }
|
||||||
|
objectId : <objectId>
|
||||||
|
type : function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[2] : {
|
||||||
|
name : [[GeneratorReceiver]]
|
||||||
|
value : {
|
||||||
|
className : global
|
||||||
|
description : global
|
||||||
|
objectId : <objectId>
|
||||||
|
type : object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[3] : {
|
||||||
|
name : [[StableObjectId]]
|
||||||
|
value : <StablectObjectId>
|
||||||
|
}
|
||||||
|
[4] : {
|
||||||
name : [[GeneratorLocation]]
|
name : [[GeneratorLocation]]
|
||||||
value : {
|
value : {
|
||||||
description : Object
|
description : Object
|
||||||
@ -486,35 +515,6 @@ expression: gen2.next();gen2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[1] : {
|
|
||||||
name : [[GeneratorStatus]]
|
|
||||||
value : {
|
|
||||||
type : string
|
|
||||||
value : suspended
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[2] : {
|
|
||||||
name : [[GeneratorFunction]]
|
|
||||||
value : {
|
|
||||||
className : GeneratorFunction
|
|
||||||
description : function* foo() { yield 1; }
|
|
||||||
objectId : <objectId>
|
|
||||||
type : function
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[3] : {
|
|
||||||
name : [[GeneratorReceiver]]
|
|
||||||
value : {
|
|
||||||
className : global
|
|
||||||
description : global
|
|
||||||
objectId : <objectId>
|
|
||||||
type : object
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[4] : {
|
|
||||||
name : [[StableObjectId]]
|
|
||||||
value : <StablectObjectId>
|
|
||||||
}
|
|
||||||
[5] : {
|
[5] : {
|
||||||
name : [[Scopes]]
|
name : [[Scopes]]
|
||||||
value : {
|
value : {
|
||||||
@ -534,6 +534,35 @@ expression: gen2.next();gen2
|
|||||||
result : {
|
result : {
|
||||||
internalProperties : [
|
internalProperties : [
|
||||||
[0] : {
|
[0] : {
|
||||||
|
name : [[GeneratorStatus]]
|
||||||
|
value : {
|
||||||
|
type : string
|
||||||
|
value : closed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[1] : {
|
||||||
|
name : [[GeneratorFunction]]
|
||||||
|
value : {
|
||||||
|
className : GeneratorFunction
|
||||||
|
description : function* foo() { yield 1; }
|
||||||
|
objectId : <objectId>
|
||||||
|
type : function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[2] : {
|
||||||
|
name : [[GeneratorReceiver]]
|
||||||
|
value : {
|
||||||
|
className : global
|
||||||
|
description : global
|
||||||
|
objectId : <objectId>
|
||||||
|
type : object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[3] : {
|
||||||
|
name : [[StableObjectId]]
|
||||||
|
value : <StablectObjectId>
|
||||||
|
}
|
||||||
|
[4] : {
|
||||||
name : [[GeneratorLocation]]
|
name : [[GeneratorLocation]]
|
||||||
value : {
|
value : {
|
||||||
description : Object
|
description : Object
|
||||||
@ -546,35 +575,6 @@ expression: gen2.next();gen2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[1] : {
|
|
||||||
name : [[GeneratorStatus]]
|
|
||||||
value : {
|
|
||||||
type : string
|
|
||||||
value : closed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[2] : {
|
|
||||||
name : [[GeneratorFunction]]
|
|
||||||
value : {
|
|
||||||
className : GeneratorFunction
|
|
||||||
description : function* foo() { yield 1; }
|
|
||||||
objectId : <objectId>
|
|
||||||
type : function
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[3] : {
|
|
||||||
name : [[GeneratorReceiver]]
|
|
||||||
value : {
|
|
||||||
className : global
|
|
||||||
description : global
|
|
||||||
objectId : <objectId>
|
|
||||||
type : object
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[4] : {
|
|
||||||
name : [[StableObjectId]]
|
|
||||||
value : <StablectObjectId>
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -589,6 +589,8 @@ Running test: testMap
|
|||||||
objectId : <objectId>
|
objectId : <objectId>
|
||||||
preview : {
|
preview : {
|
||||||
description : Map(0)
|
description : Map(0)
|
||||||
|
entries : [
|
||||||
|
]
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
]
|
]
|
||||||
@ -816,6 +818,8 @@ Running test: testMap
|
|||||||
objectId : <objectId>
|
objectId : <objectId>
|
||||||
preview : {
|
preview : {
|
||||||
description : MapIterator
|
description : MapIterator
|
||||||
|
entries : [
|
||||||
|
]
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
]
|
]
|
||||||
@ -893,6 +897,8 @@ Running test: testMap
|
|||||||
objectId : <objectId>
|
objectId : <objectId>
|
||||||
preview : {
|
preview : {
|
||||||
description : MapIterator
|
description : MapIterator
|
||||||
|
entries : [
|
||||||
|
]
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
]
|
]
|
||||||
@ -1110,6 +1116,8 @@ Running test: testWeakMap
|
|||||||
objectId : <objectId>
|
objectId : <objectId>
|
||||||
preview : {
|
preview : {
|
||||||
description : WeakMap
|
description : WeakMap
|
||||||
|
entries : [
|
||||||
|
]
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
]
|
]
|
||||||
@ -1194,6 +1202,8 @@ Running test: testWeakSet
|
|||||||
objectId : <objectId>
|
objectId : <objectId>
|
||||||
preview : {
|
preview : {
|
||||||
description : WeakSet
|
description : WeakSet
|
||||||
|
entries : [
|
||||||
|
]
|
||||||
overflow : false
|
overflow : false
|
||||||
properties : [
|
properties : [
|
||||||
]
|
]
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
Runtime.getProperties for objects with accessor
|
Runtime.getProperties for objects with accessor
|
||||||
title property with getter and setter:
|
title property with getter and setter:
|
||||||
{
|
{
|
||||||
configurable : true
|
configurable : false
|
||||||
enumerable : true
|
enumerable : false
|
||||||
get : {
|
get : {
|
||||||
className : Function
|
className : Function
|
||||||
description : function () { [native code] }
|
description : function nativeGetter() { [native code] }
|
||||||
objectId : <objectId>
|
objectId : <objectId>
|
||||||
type : function
|
type : function
|
||||||
}
|
}
|
||||||
@ -13,18 +13,18 @@ title property with getter and setter:
|
|||||||
name : title
|
name : title
|
||||||
set : {
|
set : {
|
||||||
className : Function
|
className : Function
|
||||||
description : function () { [native code] }
|
description : function nativeSetter() { [native code] }
|
||||||
objectId : <objectId>
|
objectId : <objectId>
|
||||||
type : function
|
type : function
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
title property with getter only:
|
title property with getter only:
|
||||||
{
|
{
|
||||||
configurable : true
|
configurable : false
|
||||||
enumerable : true
|
enumerable : false
|
||||||
get : {
|
get : {
|
||||||
className : Function
|
className : Function
|
||||||
description : function () { [native code] }
|
description : function nativeGetter() { [native code] }
|
||||||
objectId : <objectId>
|
objectId : <objectId>
|
||||||
type : function
|
type : function
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ Terminate first evaluation (it forces injected-script-source compilation)
|
|||||||
{
|
{
|
||||||
error : {
|
error : {
|
||||||
code : -32000
|
code : -32000
|
||||||
message : Execution was terminated
|
message : Cannot access specified execution context
|
||||||
}
|
}
|
||||||
id : <messageId>
|
id : <messageId>
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ class TestCase(testcase.TestCase):
|
|||||||
|
|
||||||
def _get_resources(self):
|
def _get_resources(self):
|
||||||
return [
|
return [
|
||||||
|
os.path.join('src', 'inspector', 'injected-script-source.js'),
|
||||||
os.path.join(
|
os.path.join(
|
||||||
'test', 'inspector', 'debugger', 'resources', 'break-locations.js'),
|
'test', 'inspector', 'debugger', 'resources', 'break-locations.js'),
|
||||||
]
|
]
|
||||||
|
@ -412,15 +412,21 @@ class SourceProcessor(SourceFileProcessor):
|
|||||||
|
|
||||||
IGNORE_COPYRIGHTS = ['box2d.js',
|
IGNORE_COPYRIGHTS = ['box2d.js',
|
||||||
'cpplint.py',
|
'cpplint.py',
|
||||||
|
'check_injected_script_source.py',
|
||||||
'copy.js',
|
'copy.js',
|
||||||
'corrections.js',
|
'corrections.js',
|
||||||
'crypto.js',
|
'crypto.js',
|
||||||
'daemon.py',
|
'daemon.py',
|
||||||
|
'debugger-script.js',
|
||||||
'earley-boyer.js',
|
'earley-boyer.js',
|
||||||
'fannkuch.js',
|
'fannkuch.js',
|
||||||
'fasta.js',
|
'fasta.js',
|
||||||
|
'generate_protocol_externs.py',
|
||||||
'injected-script.cc',
|
'injected-script.cc',
|
||||||
'injected-script.h',
|
'injected-script.h',
|
||||||
|
'injected-script-source.js',
|
||||||
|
'java-script-call-frame.cc',
|
||||||
|
'java-script-call-frame.h',
|
||||||
'jsmin.py',
|
'jsmin.py',
|
||||||
'libraries.cc',
|
'libraries.cc',
|
||||||
'libraries-empty.cc',
|
'libraries-empty.cc',
|
||||||
@ -432,11 +438,14 @@ class SourceProcessor(SourceFileProcessor):
|
|||||||
'raytrace.js',
|
'raytrace.js',
|
||||||
'regexp-pcre.js',
|
'regexp-pcre.js',
|
||||||
'resources-123.js',
|
'resources-123.js',
|
||||||
|
'rjsmin.py',
|
||||||
'sqlite.js',
|
'sqlite.js',
|
||||||
'sqlite-change-heap.js',
|
'sqlite-change-heap.js',
|
||||||
'sqlite-pointer-masking.js',
|
'sqlite-pointer-masking.js',
|
||||||
'sqlite-safe-heap.js',
|
'sqlite-safe-heap.js',
|
||||||
'v8-debugger-script.h',
|
'v8-debugger-script.h',
|
||||||
|
'v8-function-call.cc',
|
||||||
|
'v8-function-call.h',
|
||||||
'v8-inspector-impl.cc',
|
'v8-inspector-impl.cc',
|
||||||
'v8-inspector-impl.h',
|
'v8-inspector-impl.h',
|
||||||
'v8-runtime-agent-impl.cc',
|
'v8-runtime-agent-impl.cc',
|
||||||
|
Loading…
Reference in New Issue
Block a user