| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2013 Google Inc. All rights reserved. | 3 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * | 8 * |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 getProperties: function(object, objectGroupName, ownProperties, accessorProp
ertiesOnly, generatePreview) | 328 getProperties: function(object, objectGroupName, ownProperties, accessorProp
ertiesOnly, generatePreview) |
| 329 { | 329 { |
| 330 var subtype = this._subtype(object); | 330 var subtype = this._subtype(object); |
| 331 if (subtype === "internal#scope") { | 331 if (subtype === "internal#scope") { |
| 332 // Internally, scope contains object with scope variables and additi
onal information like type, | 332 // Internally, scope contains object with scope variables and additi
onal information like type, |
| 333 // we use additional information for preview and would like to repor
t variables as scope | 333 // we use additional information for preview and would like to repor
t variables as scope |
| 334 // properties. | 334 // properties. |
| 335 object = object.object; | 335 object = object.object; |
| 336 } | 336 } |
| 337 | 337 |
| 338 var descriptors = []; | |
| 339 var iter = this._propertyDescriptors(object, ownProperties, accessorProp
ertiesOnly, undefined); | |
| 340 // Go over properties, wrap object values. | 338 // Go over properties, wrap object values. |
| 341 for (var descriptor of iter) { | 339 var descriptors = this._propertyDescriptors(object, addPropertyIfNeeded,
ownProperties, accessorPropertiesOnly); |
| 342 if (subtype === "internal#scopeList" && descriptor.name === "length"
) | 340 for (var i = 0; i < descriptors.length; ++i) { |
| 343 continue; | 341 var descriptor = descriptors[i]; |
| 344 if ("get" in descriptor) | 342 if ("get" in descriptor) |
| 345 descriptor.get = this._wrapObject(descriptor.get, objectGroupNam
e); | 343 descriptor.get = this._wrapObject(descriptor.get, objectGroupNam
e); |
| 346 if ("set" in descriptor) | 344 if ("set" in descriptor) |
| 347 descriptor.set = this._wrapObject(descriptor.set, objectGroupNam
e); | 345 descriptor.set = this._wrapObject(descriptor.set, objectGroupNam
e); |
| 348 if ("value" in descriptor) | 346 if ("value" in descriptor) |
| 349 descriptor.value = this._wrapObject(descriptor.value, objectGrou
pName, false, generatePreview); | 347 descriptor.value = this._wrapObject(descriptor.value, objectGrou
pName, false, generatePreview); |
| 350 if (!("configurable" in descriptor)) | 348 if (!("configurable" in descriptor)) |
| 351 descriptor.configurable = false; | 349 descriptor.configurable = false; |
| 352 if (!("enumerable" in descriptor)) | 350 if (!("enumerable" in descriptor)) |
| 353 descriptor.enumerable = false; | 351 descriptor.enumerable = false; |
| 354 if ("symbol" in descriptor) | 352 if ("symbol" in descriptor) |
| 355 descriptor.symbol = this._wrapObject(descriptor.symbol, objectGr
oupName); | 353 descriptor.symbol = this._wrapObject(descriptor.symbol, objectGr
oupName); |
| 356 push(descriptors, descriptor); | |
| 357 } | 354 } |
| 358 return descriptors; | 355 return descriptors; |
| 356 |
| 357 /** |
| 358 * @param {!Array<!Object>} descriptors |
| 359 * @param {!Object} descriptor |
| 360 * @return {boolean} |
| 361 */ |
| 362 function addPropertyIfNeeded(descriptors, descriptor) { |
| 363 push(descriptors, descriptor); |
| 364 return true; |
| 365 } |
| 359 }, | 366 }, |
| 360 | 367 |
| 361 /** | 368 /** |
| 362 * @param {!Object} object | 369 * @param {!Object} object |
| 363 * @return {?Object} | 370 * @return {?Object} |
| 364 */ | 371 */ |
| 365 _objectPrototype: function(object) | 372 _objectPrototype: function(object) |
| 366 { | 373 { |
| 367 if (InjectedScriptHost.subtype(object) === "proxy") | 374 if (InjectedScriptHost.subtype(object) === "proxy") |
| 368 return null; | 375 return null; |
| 369 try { | 376 try { |
| 370 return Object.getPrototypeOf(object); | 377 return Object.getPrototypeOf(object); |
| 371 } catch (e) { | 378 } catch (e) { |
| 372 return null; | 379 return null; |
| 373 } | 380 } |
| 374 }, | 381 }, |
| 375 | 382 |
| 376 /** | 383 /** |
| 377 * @param {!Object} object | 384 * @param {!Object} object |
| 385 * @param {!function(!Array<!Object>, !Object)} addPropertyIfNeeded |
| 378 * @param {boolean=} ownProperties | 386 * @param {boolean=} ownProperties |
| 379 * @param {boolean=} accessorPropertiesOnly | 387 * @param {boolean=} accessorPropertiesOnly |
| 380 * @param {?Array.<string>=} propertyNamesOnly | 388 * @param {?Array<string>=} propertyNamesOnly |
| 389 * @return {!Array<!Object>} |
| 381 */ | 390 */ |
| 382 _propertyDescriptors: function*(object, ownProperties, accessorPropertiesOnl
y, propertyNamesOnly) | 391 _propertyDescriptors: function(object, addPropertyIfNeeded, ownProperties, a
ccessorPropertiesOnly, propertyNamesOnly) |
| 383 { | 392 { |
| 393 var descriptors = []; |
| 394 descriptors.__proto__ = null; |
| 384 var propertyProcessed = { __proto__: null }; | 395 var propertyProcessed = { __proto__: null }; |
| 396 var subtype = InjectedScriptHost.subtype(object); |
| 385 | 397 |
| 386 /** | 398 /** |
| 387 * @param {?Object} o | 399 * @param {!Object} o |
| 388 * @param {!Iterable<string|symbol|number>|!Array<string|number|symbol>}
properties | 400 * @param {!Array<string|number|symbol>=} properties |
| 401 * @param {number=} objectLength |
| 402 * @return {boolean} |
| 389 */ | 403 */ |
| 390 function* process(o, properties) | 404 function process(o, properties, objectLength) |
| 391 { | 405 { |
| 392 for (var property of properties) { | 406 // When properties is not provided, iterate over the object's indice
s. |
| 407 var length = properties ? properties.length : objectLength; |
| 408 for (var i = 0; i < length; ++i) { |
| 409 var property = properties ? properties[i] : ("" + i); |
| 410 if (propertyProcessed[property]) |
| 411 continue; |
| 412 propertyProcessed[property] = true; |
| 393 var name; | 413 var name; |
| 394 if (isSymbol(property)) | 414 if (isSymbol(property)) |
| 395 name = /** @type {string} */ (injectedScript._describe(prope
rty)); | 415 name = /** @type {string} */ (injectedScript._describe(prope
rty)); |
| 396 else | 416 else |
| 397 name = typeof property === "number" ? ("" + property) : /**
@type {string} */(property); | 417 name = typeof property === "number" ? ("" + property) : /**
@type {string} */(property); |
| 398 | 418 |
| 399 if (propertyProcessed[property]) | 419 if (subtype === "internal#scopeList" && name === "length") |
| 400 continue; | 420 continue; |
| 401 | 421 |
| 422 var descriptor; |
| 402 try { | 423 try { |
| 403 propertyProcessed[property] = true; | 424 descriptor = Object.getOwnPropertyDescriptor(o, property); |
| 404 var descriptor = nullifyObjectProto(Object.getOwnPropertyDes
criptor(o, property)); | 425 var isAccessorProperty = descriptor && ("get" in descriptor
|| "set" in descriptor); |
| 405 if (descriptor) { | 426 if (accessorPropertiesOnly && !isAccessorProperty) |
| 406 if (accessorPropertiesOnly && !("get" in descriptor || "
set" in descriptor)) | |
| 407 continue; | |
| 408 if ("get" in descriptor && "set" in descriptor && name !
= "__proto__" && InjectedScriptHost.formatAccessorsAsProperties(object, descript
or.get) && !doesAttributeHaveObservableSideEffectOnGet(object, name)) { | |
| 409 descriptor.value = object[property]; | |
| 410 descriptor.isOwn = true; | |
| 411 delete descriptor.get; | |
| 412 delete descriptor.set; | |
| 413 } | |
| 414 } else { | |
| 415 // Not all bindings provide proper descriptors. Fall bac
k to the writable, configurable property. | |
| 416 if (accessorPropertiesOnly) | |
| 417 continue; | |
| 418 try { | |
| 419 descriptor = { name: name, value: o[property], writa
ble: false, configurable: false, enumerable: false, __proto__: null }; | |
| 420 if (o === object) | |
| 421 descriptor.isOwn = true; | |
| 422 yield descriptor; | |
| 423 } catch (e) { | |
| 424 // Silent catch. | |
| 425 } | |
| 426 continue; | 427 continue; |
| 428 if (descriptor && "get" in descriptor && "set" in descriptor
&& name !== "__proto__" && |
| 429 InjectedScriptHost.formatAccessorsAsProperties(objec
t, descriptor.get) && |
| 430 !doesAttributeHaveObservableSideEffectOnGet(object,
name)) { |
| 431 descriptor.value = object[property]; |
| 432 descriptor.isOwn = true; |
| 433 delete descriptor.get; |
| 434 delete descriptor.set; |
| 427 } | 435 } |
| 428 } catch (e) { | 436 } catch (e) { |
| 429 if (accessorPropertiesOnly) | 437 if (accessorPropertiesOnly) |
| 430 continue; | 438 continue; |
| 431 var descriptor = { __proto__: null }; | 439 descriptor = { value: e, wasThrown: true }; |
| 432 descriptor.value = e; | 440 } |
| 433 descriptor.wasThrown = true; | 441 |
| 442 // Not all bindings provide proper descriptors. Fall back to the
non-configurable, non-enumerable, |
| 443 // non-writable property. |
| 444 if (!descriptor) { |
| 445 try { |
| 446 descriptor = { value: o[property], writable: false }; |
| 447 } catch (e) { |
| 448 // Silent catch. |
| 449 continue; |
| 450 } |
| 434 } | 451 } |
| 435 | 452 |
| 436 descriptor.name = name; | 453 descriptor.name = name; |
| 437 if (o === object) | 454 if (o === object) |
| 438 descriptor.isOwn = true; | 455 descriptor.isOwn = true; |
| 439 if (isSymbol(property)) | 456 if (isSymbol(property)) |
| 440 descriptor.symbol = property; | 457 descriptor.symbol = property; |
| 441 yield descriptor; | 458 descriptor = nullifyObjectProto(descriptor); |
| 459 if (!addPropertyIfNeeded(descriptors, descriptor)) |
| 460 return false; |
| 442 } | 461 } |
| 462 return true; |
| 443 } | 463 } |
| 444 | 464 |
| 445 if (propertyNamesOnly) { | 465 if (propertyNamesOnly) { |
| 446 for (var i = 0; i < propertyNamesOnly.length; ++i) { | 466 for (var i = 0; i < propertyNamesOnly.length; ++i) { |
| 447 var name = propertyNamesOnly[i]; | 467 var name = propertyNamesOnly[i]; |
| 448 for (var o = object; this._isDefined(o); o = this._objectPrototy
pe(o)) { | 468 for (var o = object; this._isDefined(o); o = this._objectPrototy
pe(/** @type {!Object} */ (o))) { |
| 469 o = /** @type {!Object} */ (o); |
| 449 if (InjectedScriptHost.objectHasOwnProperty(o, name)) { | 470 if (InjectedScriptHost.objectHasOwnProperty(o, name)) { |
| 450 for (var descriptor of process(o, [name])) | 471 if (!process(o, [name])) |
| 451 yield descriptor; | 472 return descriptors; |
| 452 break; | 473 break; |
| 453 } | 474 } |
| 454 if (ownProperties) | 475 if (ownProperties) |
| 455 break; | 476 break; |
| 456 } | 477 } |
| 457 } | 478 } |
| 458 return; | 479 return descriptors; |
| 459 } | |
| 460 | |
| 461 /** | |
| 462 * @param {number} length | |
| 463 */ | |
| 464 function* arrayIndexNames(length) | |
| 465 { | |
| 466 for (var i = 0; i < length; ++i) | |
| 467 yield "" + i; | |
| 468 } | 480 } |
| 469 | 481 |
| 470 var skipGetOwnPropertyNames; | 482 var skipGetOwnPropertyNames; |
| 471 try { | 483 try { |
| 472 skipGetOwnPropertyNames = InjectedScriptHost.subtype(object) === "ty
pedarray" && object.length > 500000; | 484 skipGetOwnPropertyNames = subtype === "typedarray" && object.length
> 500000; |
| 473 } catch (e) { | 485 } catch (e) { |
| 474 } | 486 } |
| 475 | 487 |
| 476 for (var o = object; this._isDefined(o); o = this._objectPrototype(o)) { | 488 for (var o = object; this._isDefined(o); o = this._objectPrototype(/** @
type {!Object} */ (o))) { |
| 489 o = /** @type {!Object} */ (o); |
| 477 if (InjectedScriptHost.subtype(o) === "proxy") | 490 if (InjectedScriptHost.subtype(o) === "proxy") |
| 478 continue; | 491 continue; |
| 479 if (skipGetOwnPropertyNames && o === object) { | 492 |
| 480 // Avoid OOM crashes from getting all own property names of a la
rge TypedArray. | 493 try { |
| 481 for (var descriptor of process(o, arrayIndexNames(o.length))) | 494 if (skipGetOwnPropertyNames && o === object) { |
| 482 yield descriptor; | 495 if (!process(o, undefined, o.length)) |
| 483 } else { | 496 return descriptors; |
| 484 // First call Object.keys() to enforce ordering of the property
descriptors. | 497 } else { |
| 485 for (var descriptor of process(o, Object.keys(/** @type {!Object
} */ (o)))) | 498 // First call Object.keys() to enforce ordering of the prope
rty descriptors. |
| 486 yield descriptor; | 499 if (!process(o, Object.keys(o))) |
| 487 for (var descriptor of process(o, Object.getOwnPropertyNames(/**
@type {!Object} */ (o)))) | 500 return descriptors; |
| 488 yield descriptor; | 501 if (!process(o, Object.getOwnPropertyNames(o))) |
| 502 return descriptors; |
| 503 } |
| 504 if (Object.getOwnPropertySymbols) { |
| 505 if (!process(o, Object.getOwnPropertySymbols(o))) |
| 506 return descriptors; |
| 507 } |
| 508 |
| 509 if (ownProperties) { |
| 510 var proto = this._objectPrototype(o); |
| 511 if (proto && !accessorPropertiesOnly) { |
| 512 var descriptor = { name: "__proto__", value: proto, writ
able: true, configurable: true, enumerable: false, isOwn: true, __proto__: null
}; |
| 513 if (!addPropertyIfNeeded(descriptors, descriptor)) |
| 514 return descriptors; |
| 515 } |
| 516 } |
| 517 } catch (e) { |
| 489 } | 518 } |
| 490 if (Object.getOwnPropertySymbols) { | 519 |
| 491 for (var descriptor of process(o, Object.getOwnPropertySymbols(/
** @type {!Object} */ (o)))) | 520 if (ownProperties) |
| 492 yield descriptor; | |
| 493 } | |
| 494 if (ownProperties) { | |
| 495 var proto = this._objectPrototype(o); | |
| 496 if (proto && !accessorPropertiesOnly) | |
| 497 yield { name: "__proto__", value: proto, writable: true, con
figurable: true, enumerable: false, isOwn: true, __proto__: null }; | |
| 498 break; | 521 break; |
| 499 } | |
| 500 } | 522 } |
| 523 return descriptors; |
| 501 }, | 524 }, |
| 502 | 525 |
| 503 /** | 526 /** |
| 504 * @param {string|undefined} objectGroupName | 527 * @param {string|undefined} objectGroupName |
| 505 * @param {*} jsonMLObject | 528 * @param {*} jsonMLObject |
| 506 * @throws {string} error message | 529 * @throws {string} error message |
| 507 */ | 530 */ |
| 508 _substituteObjectTagsInCustomPreview: function(objectGroupName, jsonMLObject
) | 531 _substituteObjectTagsInCustomPreview: function(objectGroupName, jsonMLObject
) |
| 509 { | 532 { |
| 510 var maxCustomPreviewRecursionDepth = 20; | 533 var maxCustomPreviewRecursionDepth = 20; |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 * @param {?Array.<string>=} firstLevelKeys | 879 * @param {?Array.<string>=} firstLevelKeys |
| 857 * @param {?Array.<string>=} secondLevelKeys | 880 * @param {?Array.<string>=} secondLevelKeys |
| 858 * @param {boolean=} isTable | 881 * @param {boolean=} isTable |
| 859 * @param {boolean=} skipEntriesPreview | 882 * @param {boolean=} skipEntriesPreview |
| 860 * @return {!RuntimeAgent.ObjectPreview} preview | 883 * @return {!RuntimeAgent.ObjectPreview} preview |
| 861 */ | 884 */ |
| 862 _generatePreview: function(object, firstLevelKeys, secondLevelKeys, isTable,
skipEntriesPreview) | 885 _generatePreview: function(object, firstLevelKeys, secondLevelKeys, isTable,
skipEntriesPreview) |
| 863 { | 886 { |
| 864 var preview = this._createEmptyPreview(); | 887 var preview = this._createEmptyPreview(); |
| 865 var firstLevelKeysCount = firstLevelKeys ? firstLevelKeys.length : 0; | 888 var firstLevelKeysCount = firstLevelKeys ? firstLevelKeys.length : 0; |
| 866 | |
| 867 var propertiesThreshold = { | 889 var propertiesThreshold = { |
| 868 properties: isTable ? 1000 : max(5, firstLevelKeysCount), | 890 properties: isTable ? 1000 : max(5, firstLevelKeysCount), |
| 869 indexes: isTable ? 1000 : max(100, firstLevelKeysCount), | 891 indexes: isTable ? 1000 : max(100, firstLevelKeysCount), |
| 870 __proto__: null | 892 __proto__: null |
| 871 }; | 893 }; |
| 894 var subtype = this.subtype; |
| 872 | 895 |
| 873 try { | 896 try { |
| 874 var descriptors = injectedScript._propertyDescriptors(object, undefi
ned, undefined, firstLevelKeys); | 897 var descriptors = injectedScript._propertyDescriptors(object, addPro
pertyIfNeeded, false /* ownProperties */, undefined /* accessorPropertiesOnly */
, firstLevelKeys); |
| 875 | |
| 876 this._appendPropertyDescriptors(preview, descriptors, propertiesThre
shold, secondLevelKeys, isTable); | |
| 877 if (propertiesThreshold.indexes < 0 || propertiesThreshold.propertie
s < 0) | |
| 878 return preview; | |
| 879 | 898 |
| 880 // Add internal properties to preview. | 899 // Add internal properties to preview. |
| 881 var rawInternalProperties = InjectedScriptHost.getInternalProperties
(object) || []; | 900 var rawInternalProperties = InjectedScriptHost.getInternalProperties
(object) || []; |
| 882 var internalProperties = []; | 901 var internalProperties = []; |
| 883 var entries = null; | 902 var entries = null; |
| 884 for (var i = 0; i < rawInternalProperties.length; i += 2) { | 903 for (var i = 0; i < rawInternalProperties.length; i += 2) { |
| 885 if (rawInternalProperties[i] === "[[Entries]]") { | 904 if (rawInternalProperties[i] === "[[Entries]]") { |
| 886 entries = /** @type {!Array<*>} */(rawInternalProperties[i +
1]); | 905 entries = /** @type {!Array<*>} */(rawInternalProperties[i +
1]); |
| 887 continue; | 906 continue; |
| 888 } | 907 } |
| 889 push(internalProperties, { | 908 var internalPropertyDescriptor = { |
| 890 name: rawInternalProperties[i], | 909 name: rawInternalProperties[i], |
| 891 value: rawInternalProperties[i + 1], | 910 value: rawInternalProperties[i + 1], |
| 892 isOwn: true, | 911 isOwn: true, |
| 893 enumerable: true, | 912 enumerable: true, |
| 894 __proto__: null | 913 __proto__: null |
| 895 }); | 914 }; |
| 915 if (!addPropertyIfNeeded(descriptors, internalPropertyDescriptor
)) |
| 916 break; |
| 896 } | 917 } |
| 897 this._appendPropertyDescriptors(preview, internalProperties, propert
iesThreshold, secondLevelKeys, isTable); | 918 this._appendPropertyPreviewDescriptors(preview, descriptors, secondL
evelKeys, isTable); |
| 898 | 919 |
| 899 if (this.subtype === "map" || this.subtype === "set" || this.subtype
=== "iterator") | 920 if (subtype === "map" || subtype === "set" || subtype === "iterator"
) |
| 900 this._appendEntriesPreview(entries, preview, skipEntriesPreview)
; | 921 this._appendEntriesPreview(entries, preview, skipEntriesPreview)
; |
| 901 | 922 |
| 902 } catch (e) {} | 923 } catch (e) {} |
| 903 | 924 |
| 904 return preview; | 925 return preview; |
| 926 |
| 927 /** |
| 928 * @param {!Array<!Object>} descriptors |
| 929 * @param {!Object} descriptor |
| 930 * @return {boolean} |
| 931 */ |
| 932 function addPropertyIfNeeded(descriptors, descriptor) { |
| 933 if (descriptor.wasThrown) |
| 934 return true; |
| 935 |
| 936 // Ignore __proto__ property. |
| 937 if (descriptor.name === "__proto__") |
| 938 return true; |
| 939 |
| 940 // Ignore length property of array. |
| 941 if ((subtype === "array" || subtype === "typedarray") && descriptor.
name === "length") |
| 942 return true; |
| 943 |
| 944 // Ignore size property of map, set. |
| 945 if ((subtype === "map" || subtype === "set") && descriptor.name ===
"size") |
| 946 return true; |
| 947 |
| 948 // Never preview prototype properties. |
| 949 if (!descriptor.isOwn) |
| 950 return true; |
| 951 |
| 952 // Ignore computed properties unless they have getters. |
| 953 if (!("value" in descriptor) && !descriptor.get) |
| 954 return true; |
| 955 |
| 956 if (toString(descriptor.name >>> 0) === descriptor.name) |
| 957 propertiesThreshold.indexes--; |
| 958 else |
| 959 propertiesThreshold.properties--; |
| 960 |
| 961 var canContinue = propertiesThreshold.indexes >= 0 && propertiesThre
shold.properties >= 0; |
| 962 if (!canContinue) { |
| 963 preview.overflow = true; |
| 964 return false; |
| 965 } |
| 966 push(descriptors, descriptor); |
| 967 return true; |
| 968 } |
| 905 }, | 969 }, |
| 906 | 970 |
| 907 /** | 971 /** |
| 908 * @param {!RuntimeAgent.ObjectPreview} preview | 972 * @param {!RuntimeAgent.ObjectPreview} preview |
| 909 * @param {!Array.<*>|!Iterable.<*>} descriptors | 973 * @param {!Array.<*>|!Iterable.<*>} descriptors |
| 910 * @param {!Object} propertiesThreshold | |
| 911 * @param {?Array.<string>=} secondLevelKeys | 974 * @param {?Array.<string>=} secondLevelKeys |
| 912 * @param {boolean=} isTable | 975 * @param {boolean=} isTable |
| 913 */ | 976 */ |
| 914 _appendPropertyDescriptors: function(preview, descriptors, propertiesThresho
ld, secondLevelKeys, isTable) | 977 _appendPropertyPreviewDescriptors: function(preview, descriptors, secondLeve
lKeys, isTable) |
| 915 { | 978 { |
| 916 for (var descriptor of descriptors) { | 979 for (var i = 0; i < descriptors.length; ++i) { |
| 917 if (propertiesThreshold.indexes < 0 || propertiesThreshold.propertie
s < 0) | 980 var descriptor = descriptors[i]; |
| 918 break; | |
| 919 if (!descriptor || descriptor.wasThrown) | |
| 920 continue; | |
| 921 | |
| 922 var name = descriptor.name; | 981 var name = descriptor.name; |
| 923 | |
| 924 // Ignore __proto__ property. | |
| 925 if (name === "__proto__") | |
| 926 continue; | |
| 927 | |
| 928 // Ignore length property of array. | |
| 929 if ((this.subtype === "array" || this.subtype === "typedarray") && n
ame === "length") | |
| 930 continue; | |
| 931 | |
| 932 // Ignore size property of map, set. | |
| 933 if ((this.subtype === "map" || this.subtype === "set") && name === "
size") | |
| 934 continue; | |
| 935 | |
| 936 // Never preview prototype properties. | |
| 937 if (!descriptor.isOwn) | |
| 938 continue; | |
| 939 | |
| 940 // Ignore computed properties unless they have getters. | |
| 941 if (!("value" in descriptor)) { | |
| 942 if (descriptor.get) | |
| 943 this._appendPropertyPreview(preview, { name: name, type: "ac
cessor", __proto__: null }, propertiesThreshold); | |
| 944 continue; | |
| 945 } | |
| 946 | |
| 947 var value = descriptor.value; | 982 var value = descriptor.value; |
| 948 var type = typeof value; | 983 var type = typeof value; |
| 949 | 984 |
| 950 // Special-case HTMLAll. | 985 // Special-case HTMLAll. |
| 951 if (type === "undefined" && injectedScript._isHTMLAllCollection(valu
e)) | 986 if (type === "undefined" && injectedScript._isHTMLAllCollection(valu
e)) |
| 952 type = "object"; | 987 type = "object"; |
| 953 | 988 |
| 954 // Render own properties. | 989 // Ignore computed properties unless they have getters. |
| 955 if (value === null) { | 990 if (descriptor.get && !("value" in descriptor)) { |
| 956 this._appendPropertyPreview(preview, { name: name, type: "object
", subtype: "null", value: "null", __proto__: null }, propertiesThreshold); | 991 push(preview.properties, { name: name, type: "accessor", __proto
__: null }); |
| 957 continue; | 992 continue; |
| 958 } | 993 } |
| 959 | 994 |
| 995 // Render own properties. |
| 996 if (value === null) { |
| 997 push(preview.properties, { name: name, type: "object", subtype:
"null", value: "null", __proto__: null }); |
| 998 continue; |
| 999 } |
| 1000 |
| 960 var maxLength = 100; | 1001 var maxLength = 100; |
| 961 if (InjectedScript.primitiveTypes[type]) { | 1002 if (InjectedScript.primitiveTypes[type]) { |
| 962 if (type === "string" && value.length > maxLength) | 1003 if (type === "string" && value.length > maxLength) |
| 963 value = this._abbreviateString(value, maxLength, true); | 1004 value = this._abbreviateString(value, maxLength, true); |
| 964 this._appendPropertyPreview(preview, { name: name, type: type, v
alue: toStringDescription(value), __proto__: null }, propertiesThreshold); | 1005 push(preview.properties, { name: name, type: type, value: toStri
ngDescription(value), __proto__: null }); |
| 965 continue; | 1006 continue; |
| 966 } | 1007 } |
| 967 | 1008 |
| 968 var property = { name: name, type: type, __proto__: null }; | 1009 var property = { name: name, type: type, __proto__: null }; |
| 969 var subtype = injectedScript._subtype(value); | 1010 var subtype = injectedScript._subtype(value); |
| 970 if (subtype) | 1011 if (subtype) |
| 971 property.subtype = subtype; | 1012 property.subtype = subtype; |
| 972 | 1013 |
| 973 if (secondLevelKeys === null || secondLevelKeys) { | 1014 if (secondLevelKeys === null || secondLevelKeys) { |
| 974 var subPreview = this._generatePreview(value, secondLevelKeys ||
undefined, undefined, isTable); | 1015 var subPreview = this._generatePreview(value, secondLevelKeys ||
undefined, undefined, isTable); |
| 975 property.valuePreview = subPreview; | 1016 property.valuePreview = subPreview; |
| 976 if (subPreview.overflow) | 1017 if (subPreview.overflow) |
| 977 preview.overflow = true; | 1018 preview.overflow = true; |
| 978 } else { | 1019 } else { |
| 979 var description = ""; | 1020 var description = ""; |
| 980 if (type !== "function") | 1021 if (type !== "function") |
| 981 description = this._abbreviateString(/** @type {string} */ (
injectedScript._describe(value)), maxLength, subtype === "regexp"); | 1022 description = this._abbreviateString(/** @type {string} */ (
injectedScript._describe(value)), maxLength, subtype === "regexp"); |
| 982 property.value = description; | 1023 property.value = description; |
| 983 } | 1024 } |
| 984 this._appendPropertyPreview(preview, property, propertiesThreshold); | |
| 985 } | |
| 986 }, | |
| 987 | |
| 988 /** | |
| 989 * @param {!RuntimeAgent.ObjectPreview} preview | |
| 990 * @param {!Object} property | |
| 991 * @param {!Object} propertiesThreshold | |
| 992 */ | |
| 993 _appendPropertyPreview: function(preview, property, propertiesThreshold) | |
| 994 { | |
| 995 if (toString(property.name >>> 0) === property.name) | |
| 996 propertiesThreshold.indexes--; | |
| 997 else | |
| 998 propertiesThreshold.properties--; | |
| 999 if (propertiesThreshold.indexes < 0 || propertiesThreshold.properties <
0) { | |
| 1000 preview.overflow = true; | |
| 1001 } else { | |
| 1002 push(preview.properties, property); | 1025 push(preview.properties, property); |
| 1003 } | 1026 } |
| 1004 }, | 1027 }, |
| 1005 | 1028 |
| 1006 /** | 1029 /** |
| 1007 * @param {?Array<*>} entries | 1030 * @param {?Array<*>} entries |
| 1008 * @param {!RuntimeAgent.ObjectPreview} preview | 1031 * @param {!RuntimeAgent.ObjectPreview} preview |
| 1009 * @param {boolean=} skipEntriesPreview | 1032 * @param {boolean=} skipEntriesPreview |
| 1010 */ | 1033 */ |
| 1011 _appendEntriesPreview: function(entries, preview, skipEntriesPreview) | 1034 _appendEntriesPreview: function(entries, preview, skipEntriesPreview) |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1062 return string.substr(0, leftHalf) + "\u2026" + string.substr(string.
length - rightHalf, rightHalf); | 1085 return string.substr(0, leftHalf) + "\u2026" + string.substr(string.
length - rightHalf, rightHalf); |
| 1063 } | 1086 } |
| 1064 return string.substr(0, maxLength) + "\u2026"; | 1087 return string.substr(0, maxLength) + "\u2026"; |
| 1065 }, | 1088 }, |
| 1066 | 1089 |
| 1067 __proto__: null | 1090 __proto__: null |
| 1068 } | 1091 } |
| 1069 | 1092 |
| 1070 return injectedScript; | 1093 return injectedScript; |
| 1071 }) | 1094 }) |
| OLD | NEW |