Commit 8bfb7189 authored by cbruni's avatar cbruni Committed by Commit bot

[proxies] Better print for proxies in d8

Function proxies would not be printed so far since they ended up in Function.prototype.toString which only works with Function as a receiver but no Proxy. Additionally added support for more gracefully dealing with recursive __proto__ structures introduced by proxies.

BUG=v8:1543
LOG=n

Review URL: https://codereview.chromium.org/1530293004

Cr-Commit-Position: refs/heads/master@{#32985}
parent dcac1f14
...@@ -13,6 +13,9 @@ function Stringify(x, depth) { ...@@ -13,6 +13,9 @@ function Stringify(x, depth) {
depth = stringifyDepthLimit; depth = stringifyDepthLimit;
else if (depth === 0) else if (depth === 0)
return "*"; return "*";
if (IS_PROXY(x)) {
return StringifyProxy(x, depth);
}
switch (typeof x) { switch (typeof x) {
case "undefined": case "undefined":
return "undefined"; return "undefined";
...@@ -26,6 +29,17 @@ function Stringify(x, depth) { ...@@ -26,6 +29,17 @@ function Stringify(x, depth) {
return x.toString(); return x.toString();
case "object": case "object":
if (IS_NULL(x)) return "null"; if (IS_NULL(x)) return "null";
try {
return StringifyObject(x, depth);
} catch(RangeError) {
return "{*}"
}
default:
return "[crazy non-standard value]";
}
}
function StringifyObject(x, depth) {
if (x.constructor && x.constructor.name === "Array") { if (x.constructor && x.constructor.name === "Array") {
var elems = []; var elems = [];
for (var i = 0; i < x.length; ++i) { for (var i = 0; i < x.length; ++i) {
...@@ -59,7 +73,12 @@ function Stringify(x, depth) { ...@@ -59,7 +73,12 @@ function Stringify(x, depth) {
} }
} }
return "{" + props.join(", ") + "}"; return "{" + props.join(", ") + "}";
default: }
return "[crazy non-standard value]";
} function StringifyProxy(proxy, depth) {
var proxy_type = typeof proxy;
return '[' + proxy_type + ' Proxy ' + Stringify({
target: %JSProxyGetTarget(proxy),
handler: %JSProxyGetHandler(proxy)
}, depth-1) + ']';
} }
...@@ -100,7 +100,7 @@ function GetExistingHash(key) { ...@@ -100,7 +100,7 @@ function GetExistingHash(key) {
if ((field & 1 /* Name::kHashNotComputedMask */) === 0) { if ((field & 1 /* Name::kHashNotComputedMask */) === 0) {
return field >>> 2 /* Name::kHashShift */; return field >>> 2 /* Name::kHashShift */;
} }
} else if (IS_RECEIVER(key) && !%_IsJSProxy(key) && !IS_GLOBAL(key)) { } else if (IS_RECEIVER(key) && !IS_PROXY(key) && !IS_GLOBAL(key)) {
var hash = GET_PRIVATE(key, hashCodeSymbol); var hash = GET_PRIVATE(key, hashCodeSymbol);
return hash; return hash;
} }
......
...@@ -188,7 +188,7 @@ function JSONSerialize(key, holder, replacer, stack, indent, gap) { ...@@ -188,7 +188,7 @@ function JSONSerialize(key, holder, replacer, stack, indent, gap) {
function JSONStringify(value, replacer, space) { function JSONStringify(value, replacer, space) {
if (%_ArgumentsLength() == 1 && !%_IsJSProxy(value)) { if (%_ArgumentsLength() == 1 && !IS_PROXY(value)) {
return %BasicJSONStringify(value); return %BasicJSONStringify(value);
} }
if (!IS_CALLABLE(replacer) && %is_arraylike(replacer)) { if (!IS_CALLABLE(replacer) && %is_arraylike(replacer)) {
......
...@@ -88,37 +88,38 @@ define STRING_TO_REGEXP_CACHE_ID = 0; ...@@ -88,37 +88,38 @@ define STRING_TO_REGEXP_CACHE_ID = 0;
# Note: We have special support for typeof(foo) === 'bar' in the compiler. # Note: We have special support for typeof(foo) === 'bar' in the compiler.
# It will *not* generate a runtime typeof call for the most important # It will *not* generate a runtime typeof call for the most important
# values of 'bar'. # values of 'bar'.
macro IS_NULL(arg) = (arg === null);
macro IS_NULL_OR_UNDEFINED(arg) = (arg == null);
macro IS_UNDEFINED(arg) = (arg === (void 0));
macro IS_NUMBER(arg) = (typeof(arg) === 'number');
macro IS_STRING(arg) = (typeof(arg) === 'string');
macro IS_BOOLEAN(arg) = (typeof(arg) === 'boolean');
macro IS_SYMBOL(arg) = (typeof(arg) === 'symbol');
macro IS_OBJECT(arg) = (typeof(arg) === 'object');
macro IS_ARRAY(arg) = (%_IsArray(arg)); macro IS_ARRAY(arg) = (%_IsArray(arg));
macro IS_ARRAYBUFFER(arg) = (%_ClassOf(arg) === 'ArrayBuffer');
macro IS_BOOLEAN(arg) = (typeof(arg) === 'boolean');
macro IS_BOOLEAN_WRAPPER(arg) = (%_ClassOf(arg) === 'Boolean');
macro IS_DATAVIEW(arg) = (%_ClassOf(arg) === 'DataView');
macro IS_DATE(arg) = (%_IsDate(arg)); macro IS_DATE(arg) = (%_IsDate(arg));
macro IS_ERROR(arg) = (%_ClassOf(arg) === 'Error');
macro IS_FUNCTION(arg) = (%_IsFunction(arg)); macro IS_FUNCTION(arg) = (%_IsFunction(arg));
macro IS_REGEXP(arg) = (%_IsRegExp(arg)); macro IS_GENERATOR(arg) = (%_ClassOf(arg) === 'Generator');
macro IS_SIMD_VALUE(arg) = (%_IsSimdValue(arg)); macro IS_GLOBAL(arg) = (%_ClassOf(arg) === 'global');
macro IS_SET(arg) = (%_ClassOf(arg) === 'Set');
macro IS_MAP(arg) = (%_ClassOf(arg) === 'Map'); macro IS_MAP(arg) = (%_ClassOf(arg) === 'Map');
macro IS_WEAKMAP(arg) = (%_ClassOf(arg) === 'WeakMap'); macro IS_MAP_ITERATOR(arg) = (%_ClassOf(arg) === 'Map Iterator');
macro IS_WEAKSET(arg) = (%_ClassOf(arg) === 'WeakSet'); macro IS_NULL(arg) = (arg === null);
macro IS_NULL_OR_UNDEFINED(arg) = (arg == null);
macro IS_NUMBER(arg) = (typeof(arg) === 'number');
macro IS_NUMBER_WRAPPER(arg) = (%_ClassOf(arg) === 'Number'); macro IS_NUMBER_WRAPPER(arg) = (%_ClassOf(arg) === 'Number');
macro IS_STRING_WRAPPER(arg) = (%_ClassOf(arg) === 'String'); macro IS_OBJECT(arg) = (typeof(arg) === 'object');
macro IS_SYMBOL_WRAPPER(arg) = (%_ClassOf(arg) === 'Symbol'); macro IS_PROXY(arg) = (%_IsJSProxy(arg));
macro IS_BOOLEAN_WRAPPER(arg) = (%_ClassOf(arg) === 'Boolean'); macro IS_REGEXP(arg) = (%_IsRegExp(arg));
macro IS_ERROR(arg) = (%_ClassOf(arg) === 'Error');
macro IS_SCRIPT(arg) = (%_ClassOf(arg) === 'Script'); macro IS_SCRIPT(arg) = (%_ClassOf(arg) === 'Script');
macro IS_GLOBAL(arg) = (%_ClassOf(arg) === 'global'); macro IS_SET(arg) = (%_ClassOf(arg) === 'Set');
macro IS_ARRAYBUFFER(arg) = (%_ClassOf(arg) === 'ArrayBuffer');
macro IS_DATAVIEW(arg) = (%_ClassOf(arg) === 'DataView');
macro IS_SHAREDARRAYBUFFER(arg) = (%_ClassOf(arg) === 'SharedArrayBuffer');
macro IS_GENERATOR(arg) = (%_ClassOf(arg) === 'Generator');
macro IS_SET_ITERATOR(arg) = (%_ClassOf(arg) === 'Set Iterator'); macro IS_SET_ITERATOR(arg) = (%_ClassOf(arg) === 'Set Iterator');
macro IS_MAP_ITERATOR(arg) = (%_ClassOf(arg) === 'Map Iterator'); macro IS_SHAREDARRAYBUFFER(arg) = (%_ClassOf(arg) === 'SharedArrayBuffer');
macro IS_SIMD_VALUE(arg) = (%_IsSimdValue(arg));
macro IS_STRING(arg) = (typeof(arg) === 'string');
macro IS_STRING_WRAPPER(arg) = (%_ClassOf(arg) === 'String');
macro IS_STRONG(arg) = (%IsStrong(arg)); macro IS_STRONG(arg) = (%IsStrong(arg));
macro IS_SYMBOL(arg) = (typeof(arg) === 'symbol');
macro IS_SYMBOL_WRAPPER(arg) = (%_ClassOf(arg) === 'Symbol');
macro IS_UNDEFINED(arg) = (arg === (void 0));
macro IS_WEAKMAP(arg) = (%_ClassOf(arg) === 'WeakMap');
macro IS_WEAKSET(arg) = (%_ClassOf(arg) === 'WeakSet');
# Macro for ES queries of the type: "Type(O) is Object." # Macro for ES queries of the type: "Type(O) is Object."
macro IS_RECEIVER(arg) = (%_IsJSReceiver(arg)); macro IS_RECEIVER(arg) = (%_IsJSReceiver(arg));
......
...@@ -843,7 +843,7 @@ function FormatStackTrace(obj, raw_stack) { ...@@ -843,7 +843,7 @@ function FormatStackTrace(obj, raw_stack) {
function GetTypeName(receiver, requireConstructor) { function GetTypeName(receiver, requireConstructor) {
if (IS_NULL_OR_UNDEFINED(receiver)) return null; if (IS_NULL_OR_UNDEFINED(receiver)) return null;
if (%_IsJSProxy(receiver)) return "Proxy"; if (IS_PROXY(receiver)) return "Proxy";
var constructor = %GetDataProperty(TO_OBJECT(receiver), "constructor"); var constructor = %GetDataProperty(TO_OBJECT(receiver), "constructor");
if (!IS_FUNCTION(constructor)) { if (!IS_FUNCTION(constructor)) {
......
...@@ -192,7 +192,7 @@ function ObserverIsActive(observer, objectInfo) { ...@@ -192,7 +192,7 @@ function ObserverIsActive(observer, objectInfo) {
function ObjectInfoGetOrCreate(object) { function ObjectInfoGetOrCreate(object) {
var objectInfo = ObjectInfoGet(object); var objectInfo = ObjectInfoGet(object);
if (IS_UNDEFINED(objectInfo)) { if (IS_UNDEFINED(objectInfo)) {
if (!%_IsJSProxy(object)) { if (!IS_PROXY(object)) {
%SetIsObserved(object); %SetIsObserved(object);
} }
objectInfo = { objectInfo = {
......
...@@ -22,7 +22,7 @@ utils.Import(function(from) { ...@@ -22,7 +22,7 @@ utils.Import(function(from) {
function ProxyCreateRevocable(target, handler) { function ProxyCreateRevocable(target, handler) {
var p = new GlobalProxy(target, handler); var p = new GlobalProxy(target, handler);
return {proxy: p, revoke: () => %RevokeProxy(p)}; return {proxy: p, revoke: () => %JSProxyRevoke(p)};
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
......
...@@ -500,11 +500,11 @@ function CallTrap2(handler, name, defaultTrap, x, y) { ...@@ -500,11 +500,11 @@ function CallTrap2(handler, name, defaultTrap, x, y) {
// ObjectGetOwnPropertyDescriptor and delete this. // ObjectGetOwnPropertyDescriptor and delete this.
function GetOwnPropertyJS(obj, v) { function GetOwnPropertyJS(obj, v) {
var p = TO_NAME(v); var p = TO_NAME(v);
if (%_IsJSProxy(obj)) { if (IS_PROXY(obj)) {
// TODO(rossberg): adjust once there is a story for symbols vs proxies. // TODO(rossberg): adjust once there is a story for symbols vs proxies.
if (IS_SYMBOL(v)) return UNDEFINED; if (IS_SYMBOL(v)) return UNDEFINED;
var handler = %GetHandler(obj); var handler = %JSProxyGetHandler(obj);
var descriptor = CallTrap1( var descriptor = CallTrap1(
handler, "getOwnPropertyDescriptor", UNDEFINED, p); handler, "getOwnPropertyDescriptor", UNDEFINED, p);
if (IS_UNDEFINED(descriptor)) return descriptor; if (IS_UNDEFINED(descriptor)) return descriptor;
...@@ -538,7 +538,7 @@ function DefineProxyProperty(obj, p, attributes, should_throw) { ...@@ -538,7 +538,7 @@ function DefineProxyProperty(obj, p, attributes, should_throw) {
// TODO(rossberg): adjust once there is a story for symbols vs proxies. // TODO(rossberg): adjust once there is a story for symbols vs proxies.
if (IS_SYMBOL(p)) return false; if (IS_SYMBOL(p)) return false;
var handler = %GetHandler(obj); var handler = %JSProxyGetHandler(obj);
var result = CallTrap2(handler, "defineProperty", UNDEFINED, p, attributes); var result = CallTrap2(handler, "defineProperty", UNDEFINED, p, attributes);
if (!result) { if (!result) {
if (should_throw) { if (should_throw) {
...@@ -761,7 +761,7 @@ function DefineArrayProperty(obj, p, desc, should_throw) { ...@@ -761,7 +761,7 @@ function DefineArrayProperty(obj, p, desc, should_throw) {
// ES5 section 8.12.9, ES5 section 15.4.5.1 and Harmony proxies. // ES5 section 8.12.9, ES5 section 15.4.5.1 and Harmony proxies.
function DefineOwnProperty(obj, p, desc, should_throw) { function DefineOwnProperty(obj, p, desc, should_throw) {
if (%_IsJSProxy(obj)) { if (IS_PROXY(obj)) {
// TODO(rossberg): adjust once there is a story for symbols vs proxies. // TODO(rossberg): adjust once there is a story for symbols vs proxies.
if (IS_SYMBOL(p)) return false; if (IS_SYMBOL(p)) return false;
......
...@@ -149,7 +149,7 @@ RUNTIME_FUNCTION(Runtime_IsJSProxy) { ...@@ -149,7 +149,7 @@ RUNTIME_FUNCTION(Runtime_IsJSProxy) {
} }
RUNTIME_FUNCTION(Runtime_GetHandler) { RUNTIME_FUNCTION(Runtime_JSProxyGetHandler) {
SealHandleScope shs(isolate); SealHandleScope shs(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
CONVERT_ARG_CHECKED(JSProxy, proxy, 0); CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
...@@ -157,7 +157,15 @@ RUNTIME_FUNCTION(Runtime_GetHandler) { ...@@ -157,7 +157,15 @@ RUNTIME_FUNCTION(Runtime_GetHandler) {
} }
RUNTIME_FUNCTION(Runtime_RevokeProxy) { RUNTIME_FUNCTION(Runtime_JSProxyGetTarget) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
return proxy->target();
}
RUNTIME_FUNCTION(Runtime_JSProxyRevoke) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0); CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0);
......
...@@ -543,8 +543,9 @@ namespace internal { ...@@ -543,8 +543,9 @@ namespace internal {
F(IsJSProxy, 1, 1) \ F(IsJSProxy, 1, 1) \
F(JSProxyCall, -1 /* >= 2 */, 1) \ F(JSProxyCall, -1 /* >= 2 */, 1) \
F(JSProxyConstruct, -1 /* >= 3 */, 1) \ F(JSProxyConstruct, -1 /* >= 3 */, 1) \
F(GetHandler, 1, 1) \ F(JSProxyGetTarget, 1, 1) \
F(RevokeProxy, 1, 1) F(JSProxyGetHandler, 1, 1) \
F(JSProxyRevoke, 1, 1)
#define FOR_EACH_INTRINSIC_REGEXP(F) \ #define FOR_EACH_INTRINSIC_REGEXP(F) \
F(StringReplaceGlobalRegExpWithString, 4, 1) \ F(StringReplaceGlobalRegExpWithString, 4, 1) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment