Revert of Provide accessor for object internal properties that doesn't require debugger to be active (patchset #3 id:40001 of https://codereview.chromium.org/1126103006/)
Reason for revert: GC mole issues: https://chromegw.corp.google.com/i/client.v8/builders/V8%20Linux%20-%20gcmole/builds/1950/steps/GCMole%20ia32/logs/stdio Original issue's description: > Provide accessor for object internal properties that doesn't require debugger to be active > > Some of the DevTools' clients need to inspect JS objects without enabling debugger. This CL allows to inspect object's internal properties without enabling debugger and instantiating debug context. > > Note that now debug context can be created lazily if v8::Debug::GetDebugContext is called when there is no debug listener. This is fragile and has already resulted in some subtle error. I'm going to fix that in a separate CL. > > BUG=chromium:481845 > LOG=Y > > Committed: https://crrev.com/bdeb0de88c8cf5f2c78f261b45314138f525110d > Cr-Commit-Position: refs/heads/master@{#28362} TBR=pfeldman@chromium.org,kozyatinskiy@chromium.org,yurys@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=chromium:481845 Review URL: https://codereview.chromium.org/1133243002 Cr-Commit-Position: refs/heads/master@{#28365}
This commit is contained in:
parent
7f2636e067
commit
396236bfa0
@ -260,16 +260,6 @@ class V8_EXPORT Debug {
|
||||
* unexpectedly used. LiveEdit is enabled by default.
|
||||
*/
|
||||
static void SetLiveEditEnabled(Isolate* isolate, bool enable);
|
||||
|
||||
/**
|
||||
* Returns array of internal properties specific to the value type. Result has
|
||||
* the following
|
||||
* format: [<name>, <value>,...,<name>, <value>]. Result array will be
|
||||
* allocated in the current
|
||||
* context.
|
||||
*/
|
||||
static MaybeLocal<Array> GetInternalProperties(Isolate* isolate,
|
||||
Local<Value> value);
|
||||
};
|
||||
|
||||
|
||||
|
23
src/api.cc
23
src/api.cc
@ -6090,7 +6090,16 @@ Local<Object> Array::CloneElementAt(uint32_t index) {
|
||||
|
||||
bool Value::IsPromise() const {
|
||||
auto self = Utils::OpenHandle(this);
|
||||
return i::Object::IsPromise(self);
|
||||
if (!self->IsJSObject()) return false;
|
||||
auto js_object = i::Handle<i::JSObject>::cast(self);
|
||||
// Promises can't have access checks.
|
||||
if (js_object->map()->is_access_check_needed()) return false;
|
||||
auto isolate = js_object->GetIsolate();
|
||||
// TODO(dcarney): this should just be read from the symbol registry so as not
|
||||
// to be context dependent.
|
||||
auto key = isolate->promise_status();
|
||||
// Shouldn't be possible to throw here.
|
||||
return i::JSObject::HasRealNamedProperty(js_object, key).FromJust();
|
||||
}
|
||||
|
||||
|
||||
@ -7385,18 +7394,6 @@ void Debug::SetLiveEditEnabled(Isolate* isolate, bool enable) {
|
||||
}
|
||||
|
||||
|
||||
MaybeLocal<Array> Debug::GetInternalProperties(Isolate* v8_isolate,
|
||||
Local<Value> value) {
|
||||
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
ENTER_V8(isolate);
|
||||
i::Handle<i::Object> val = Utils::OpenHandle(*value);
|
||||
i::Handle<i::JSArray> result;
|
||||
if (!i::Runtime::GetInternalProperties(isolate, val).ToHandle(&result))
|
||||
return MaybeLocal<Array>();
|
||||
return Utils::ToLocal(result);
|
||||
}
|
||||
|
||||
|
||||
Handle<String> CpuProfileNode::GetFunctionName() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
|
||||
|
@ -1611,7 +1611,6 @@ void Genesis::InstallNativeFunctions() {
|
||||
to_complete_property_descriptor);
|
||||
|
||||
INSTALL_NATIVE(Symbol, "$promiseStatus", promise_status);
|
||||
INSTALL_NATIVE(Symbol, "$promiseValue", promise_value);
|
||||
INSTALL_NATIVE(JSFunction, "$promiseCreate", promise_create);
|
||||
INSTALL_NATIVE(JSFunction, "$promiseResolve", promise_resolve);
|
||||
INSTALL_NATIVE(JSFunction, "$promiseReject", promise_reject);
|
||||
|
@ -157,7 +157,6 @@ enum BindingFlags {
|
||||
V(ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX, Object, \
|
||||
error_message_for_code_gen_from_strings) \
|
||||
V(PROMISE_STATUS_INDEX, Symbol, promise_status) \
|
||||
V(PROMISE_VALUE_INDEX, Symbol, promise_value) \
|
||||
V(PROMISE_CREATE_INDEX, JSFunction, promise_create) \
|
||||
V(PROMISE_RESOLVE_INDEX, JSFunction, promise_resolve) \
|
||||
V(PROMISE_REJECT_INDEX, JSFunction, promise_reject) \
|
||||
@ -394,7 +393,6 @@ class Context: public FixedArray {
|
||||
RUN_MICROTASKS_INDEX,
|
||||
ENQUEUE_MICROTASK_INDEX,
|
||||
PROMISE_STATUS_INDEX,
|
||||
PROMISE_VALUE_INDEX,
|
||||
PROMISE_CREATE_INDEX,
|
||||
PROMISE_RESOLVE_INDEX,
|
||||
PROMISE_REJECT_INDEX,
|
||||
|
@ -904,12 +904,57 @@ ObjectMirror.prototype.toText = function() {
|
||||
* @return {Array} array (possibly empty) of InternalProperty instances
|
||||
*/
|
||||
ObjectMirror.GetInternalProperties = function(value) {
|
||||
var properties = %DebugGetInternalProperties(value);
|
||||
var result = [];
|
||||
for (var i = 0; i < properties.length; i += 2) {
|
||||
result.push(new InternalPropertyMirror(properties[i], properties[i + 1]));
|
||||
if (IS_STRING_WRAPPER(value) || IS_NUMBER_WRAPPER(value) ||
|
||||
IS_BOOLEAN_WRAPPER(value)) {
|
||||
var primitiveValue = %_ValueOf(value);
|
||||
return [new InternalPropertyMirror("[[PrimitiveValue]]", primitiveValue)];
|
||||
} else if (IS_FUNCTION(value)) {
|
||||
var bindings = %BoundFunctionGetBindings(value);
|
||||
var result = [];
|
||||
if (bindings && IS_ARRAY(bindings)) {
|
||||
result.push(new InternalPropertyMirror("[[TargetFunction]]",
|
||||
bindings[0]));
|
||||
result.push(new InternalPropertyMirror("[[BoundThis]]", bindings[1]));
|
||||
var boundArgs = [];
|
||||
for (var i = 2; i < bindings.length; i++) {
|
||||
boundArgs.push(bindings[i]);
|
||||
}
|
||||
result.push(new InternalPropertyMirror("[[BoundArgs]]", boundArgs));
|
||||
}
|
||||
return result;
|
||||
} else if (IS_MAP_ITERATOR(value) || IS_SET_ITERATOR(value)) {
|
||||
var details = IS_MAP_ITERATOR(value) ? %MapIteratorDetails(value)
|
||||
: %SetIteratorDetails(value);
|
||||
var kind;
|
||||
switch (details[2]) {
|
||||
case 1: kind = "keys"; break;
|
||||
case 2: kind = "values"; break;
|
||||
case 3: kind = "entries"; break;
|
||||
}
|
||||
var result = [
|
||||
new InternalPropertyMirror("[[IteratorHasMore]]", details[0]),
|
||||
new InternalPropertyMirror("[[IteratorIndex]]", details[1])
|
||||
];
|
||||
if (kind) {
|
||||
result.push(new InternalPropertyMirror("[[IteratorKind]]", kind));
|
||||
}
|
||||
return result;
|
||||
} else if (IS_GENERATOR(value)) {
|
||||
return [
|
||||
new InternalPropertyMirror("[[GeneratorStatus]]",
|
||||
GeneratorGetStatus_(value)),
|
||||
new InternalPropertyMirror("[[GeneratorFunction]]",
|
||||
%GeneratorGetFunction(value)),
|
||||
new InternalPropertyMirror("[[GeneratorReceiver]]",
|
||||
%GeneratorGetReceiver(value))
|
||||
];
|
||||
} else if (ObjectIsPromise(value)) {
|
||||
return [
|
||||
new InternalPropertyMirror("[[PromiseStatus]]", PromiseGetStatus_(value)),
|
||||
new InternalPropertyMirror("[[PromiseValue]]", PromiseGetValue_(value))
|
||||
];
|
||||
}
|
||||
return result;
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
|
@ -112,20 +112,6 @@ bool Object::IsCallable() const {
|
||||
}
|
||||
|
||||
|
||||
bool Object::IsPromise(Handle<Object> object) {
|
||||
if (!object->IsJSObject()) return false;
|
||||
auto js_object = Handle<JSObject>::cast(object);
|
||||
// Promises can't have access checks.
|
||||
if (js_object->map()->is_access_check_needed()) return false;
|
||||
auto isolate = js_object->GetIsolate();
|
||||
// TODO(dcarney): this should just be read from the symbol registry so as not
|
||||
// to be context dependent.
|
||||
auto key = isolate->promise_status();
|
||||
// Shouldn't be possible to throw here.
|
||||
return JSObject::HasRealNamedProperty(js_object, key).FromJust();
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
|
||||
for (; it->IsFound(); it->Next()) {
|
||||
switch (it->state()) {
|
||||
|
@ -1056,7 +1056,6 @@ class Object {
|
||||
INLINE(bool IsOrderedHashSet() const);
|
||||
INLINE(bool IsOrderedHashMap() const);
|
||||
bool IsCallable() const;
|
||||
static bool IsPromise(Handle<Object> object);
|
||||
|
||||
// Oddball testing.
|
||||
INLINE(bool IsUndefined() const);
|
||||
|
@ -101,156 +101,6 @@ static Handle<Object> DebugGetProperty(LookupIterator* it,
|
||||
}
|
||||
|
||||
|
||||
static Handle<Object> DebugGetProperty(Handle<Object> object,
|
||||
Handle<Name> name) {
|
||||
LookupIterator it(object, name);
|
||||
return DebugGetProperty(&it);
|
||||
}
|
||||
|
||||
|
||||
template <class IteratorType>
|
||||
static MaybeHandle<JSArray> GetIteratorInternalProperties(
|
||||
Isolate* isolate, Handle<IteratorType> object) {
|
||||
Factory* factory = isolate->factory();
|
||||
Handle<IteratorType> iterator = Handle<IteratorType>::cast(object);
|
||||
RUNTIME_ASSERT_HANDLIFIED(iterator->kind()->IsSmi(), JSArray);
|
||||
const char* kind = NULL;
|
||||
switch (Smi::cast(iterator->kind())->value()) {
|
||||
case IteratorType::kKindKeys:
|
||||
kind = "keys";
|
||||
break;
|
||||
case IteratorType::kKindValues:
|
||||
kind = "values";
|
||||
break;
|
||||
case IteratorType::kKindEntries:
|
||||
kind = "entries";
|
||||
break;
|
||||
default:
|
||||
RUNTIME_ASSERT_HANDLIFIED(false, JSArray);
|
||||
}
|
||||
|
||||
Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
|
||||
result->set(0, *factory->NewStringFromAsciiChecked("[[IteratorHasMore]]"));
|
||||
result->set(1, isolate->heap()->ToBoolean(iterator->HasMore()));
|
||||
|
||||
result->set(2, *factory->NewStringFromAsciiChecked("[[IteratorIndex]]"));
|
||||
result->set(3, iterator->index());
|
||||
|
||||
result->set(4, *factory->NewStringFromAsciiChecked("[[IteratorKind]]"));
|
||||
result->set(5, *factory->NewStringFromAsciiChecked(kind));
|
||||
return factory->NewJSArrayWithElements(result);
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
|
||||
Handle<Object> object) {
|
||||
Factory* factory = isolate->factory();
|
||||
if (object->IsJSFunction()) {
|
||||
Handle<JSFunction> function = Handle<JSFunction>::cast(object);
|
||||
if (function->shared()->bound()) {
|
||||
RUNTIME_ASSERT_HANDLIFIED(function->function_bindings()->IsFixedArray(),
|
||||
JSArray);
|
||||
|
||||
Handle<FixedArray> bindings(function->function_bindings());
|
||||
|
||||
Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
|
||||
result->set(0, *factory->NewStringFromAsciiChecked("[[TargetFunction]]"));
|
||||
result->set(1, bindings->get(JSFunction::kBoundFunctionIndex));
|
||||
|
||||
result->set(2, *factory->NewStringFromAsciiChecked("[[BoundThis]]"));
|
||||
result->set(3, bindings->get(JSFunction::kBoundThisIndex));
|
||||
|
||||
Handle<FixedArray> arguments = factory->NewFixedArray(
|
||||
bindings->length() - JSFunction::kBoundArgumentsStartIndex);
|
||||
bindings->CopyTo(
|
||||
JSFunction::kBoundArgumentsStartIndex, *arguments, 0,
|
||||
bindings->length() - JSFunction::kBoundArgumentsStartIndex);
|
||||
result->set(4, *factory->NewStringFromAsciiChecked("[[BoundArgs]]"));
|
||||
result->set(5, *factory->NewJSArrayWithElements(arguments));
|
||||
return factory->NewJSArrayWithElements(result);
|
||||
}
|
||||
} else if (object->IsJSMapIterator()) {
|
||||
Handle<JSMapIterator> iterator = Handle<JSMapIterator>::cast(object);
|
||||
return GetIteratorInternalProperties(isolate, iterator);
|
||||
} else if (object->IsJSSetIterator()) {
|
||||
Handle<JSSetIterator> iterator = Handle<JSSetIterator>::cast(object);
|
||||
return GetIteratorInternalProperties(isolate, iterator);
|
||||
} else if (object->IsJSGeneratorObject()) {
|
||||
Handle<JSGeneratorObject> generator =
|
||||
Handle<JSGeneratorObject>::cast(object);
|
||||
|
||||
const char* status = "suspended";
|
||||
if (generator->is_closed()) {
|
||||
status = "closed";
|
||||
} else if (generator->is_executing()) {
|
||||
status = "running";
|
||||
} else {
|
||||
DCHECK(generator->is_suspended());
|
||||
}
|
||||
|
||||
Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
|
||||
result->set(0, *factory->NewStringFromAsciiChecked("[[GeneratorStatus]]"));
|
||||
result->set(1, *factory->NewStringFromAsciiChecked(status));
|
||||
|
||||
result->set(2,
|
||||
*factory->NewStringFromAsciiChecked("[[GeneratorFunction]]"));
|
||||
result->set(3, generator->function());
|
||||
|
||||
result->set(4,
|
||||
*factory->NewStringFromAsciiChecked("[[GeneratorReceiver]]"));
|
||||
result->set(5, generator->receiver());
|
||||
return factory->NewJSArrayWithElements(result);
|
||||
} else if (Object::IsPromise(object)) {
|
||||
Handle<JSObject> promise = Handle<JSObject>::cast(object);
|
||||
|
||||
Handle<Object> status_obj =
|
||||
DebugGetProperty(promise, isolate->promise_status());
|
||||
RUNTIME_ASSERT_HANDLIFIED(status_obj->IsSmi(), JSArray);
|
||||
const char* status = "rejected";
|
||||
int status_val = Handle<Smi>::cast(status_obj)->value();
|
||||
switch (status_val) {
|
||||
case +1:
|
||||
status = "resolved";
|
||||
break;
|
||||
case 0:
|
||||
status = "pending";
|
||||
break;
|
||||
default:
|
||||
DCHECK_EQ(-1, status_val);
|
||||
}
|
||||
|
||||
Handle<FixedArray> result = factory->NewFixedArray(2 * 2);
|
||||
result->set(0, *factory->NewStringFromAsciiChecked("[[PromiseStatus]]"));
|
||||
result->set(1, *factory->NewStringFromAsciiChecked(status));
|
||||
|
||||
Handle<Object> value_obj =
|
||||
DebugGetProperty(promise, isolate->promise_value());
|
||||
result->set(2, *factory->NewStringFromAsciiChecked("[[PromiseValue]]"));
|
||||
result->set(3, *value_obj);
|
||||
return factory->NewJSArrayWithElements(result);
|
||||
} else if (object->IsJSValue()) {
|
||||
Handle<JSValue> js_value = Handle<JSValue>::cast(object);
|
||||
|
||||
Handle<FixedArray> result = factory->NewFixedArray(2);
|
||||
result->set(0, *factory->NewStringFromAsciiChecked("[[PrimitiveValue]]"));
|
||||
result->set(1, js_value->value());
|
||||
return factory->NewJSArrayWithElements(result);
|
||||
}
|
||||
return factory->NewJSArray(0);
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
|
||||
Handle<JSArray> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result, Runtime::GetInternalProperties(isolate, obj));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
// Get debugger related details for an object property, in the following format:
|
||||
// 0: Property value
|
||||
// 1: Property details
|
||||
|
@ -134,7 +134,6 @@ namespace internal {
|
||||
F(DebugBreak, 0, 1) \
|
||||
F(SetDebugEventListener, 2, 1) \
|
||||
F(ScheduleBreak, 0, 1) \
|
||||
F(DebugGetInternalProperties, 1, 1) \
|
||||
F(DebugGetPropertyDetails, 2, 1) \
|
||||
F(DebugGetProperty, 2, 1) \
|
||||
F(DebugPropertyTypeFromDetails, 1, 1) \
|
||||
@ -855,9 +854,6 @@ class Runtime : public AllStatic {
|
||||
Handle<Object> key, Handle<Object> value);
|
||||
static bool WeakCollectionDelete(Handle<JSWeakCollection> weak_collection,
|
||||
Handle<Object> key);
|
||||
|
||||
static MaybeHandle<JSArray> GetInternalProperties(Isolate* isolate,
|
||||
Handle<Object>);
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user