Chromium Code Reviews| 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 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 207 InjectedScript.closureTypes["local"] = "Local"; | 207 InjectedScript.closureTypes["local"] = "Local"; |
| 208 InjectedScript.closureTypes["closure"] = "Closure"; | 208 InjectedScript.closureTypes["closure"] = "Closure"; |
| 209 InjectedScript.closureTypes["catch"] = "Catch"; | 209 InjectedScript.closureTypes["catch"] = "Catch"; |
| 210 InjectedScript.closureTypes["block"] = "Block"; | 210 InjectedScript.closureTypes["block"] = "Block"; |
| 211 InjectedScript.closureTypes["script"] = "Script"; | 211 InjectedScript.closureTypes["script"] = "Script"; |
| 212 InjectedScript.closureTypes["with"] = "With Block"; | 212 InjectedScript.closureTypes["with"] = "With Block"; |
| 213 InjectedScript.closureTypes["global"] = "Global"; | 213 InjectedScript.closureTypes["global"] = "Global"; |
| 214 InjectedScript.closureTypes["eval"] = "Eval"; | 214 InjectedScript.closureTypes["eval"] = "Eval"; |
| 215 InjectedScript.closureTypes["module"] = "Module"; | 215 InjectedScript.closureTypes["module"] = "Module"; |
| 216 | 216 |
| 217 /** | |
| 218 * @interface | |
| 219 */ | |
| 220 InjectedScript.AdderWithThreshold = function () {}; | |
| 221 InjectedScript.AdderWithThreshold.prototype = { | |
| 222 /** | |
| 223 * @param {!Array<!Object>} descriptors | |
| 224 * @param {!Object} descriptor | |
| 225 */ | |
| 226 add: function (descriptors, descriptor) {}, | |
| 227 | |
| 228 /** | |
| 229 * @return {boolean} | |
| 230 */ | |
| 231 isSpaceAvailable: function () {} | |
| 232 }; | |
| 233 | |
| 234 /** | |
| 235 * @implements {InjectedScript.AdderWithThreshold} | |
| 236 * @constructor | |
| 237 */ | |
| 238 InjectedScript.defaultPropertyAdder = function () {}; | |
| 239 InjectedScript.defaultPropertyAdder.prototype = { | |
|
kozy
2017/02/21 19:01:55
We try to avoid using any complex JS construction
luoe
2017/02/21 21:53:51
Yes, I think a customPush() will also need to be p
| |
| 240 /** | |
| 241 * @override | |
| 242 * @param {!Array<!Object>} descriptors | |
| 243 * @param {!Object} descriptor | |
| 244 */ | |
| 245 add: function (descriptors, descriptor) { | |
| 246 push(descriptors, descriptor); | |
| 247 }, | |
| 248 | |
| 249 /** | |
| 250 * @override | |
| 251 * @return {boolean} | |
| 252 */ | |
| 253 isSpaceAvailable: function () { | |
| 254 return true; | |
| 255 } | |
| 256 }; | |
| 257 | |
| 217 InjectedScript.prototype = { | 258 InjectedScript.prototype = { |
| 218 /** | 259 /** |
| 219 * @param {*} object | 260 * @param {*} object |
| 220 * @return {boolean} | 261 * @return {boolean} |
| 221 */ | 262 */ |
| 222 isPrimitiveValue: function(object) | 263 isPrimitiveValue: function(object) |
| 223 { | 264 { |
| 224 // FIXME(33716): typeof document.all is always 'undefined'. | 265 // FIXME(33716): typeof document.all is always 'undefined'. |
| 225 return InjectedScript.primitiveTypes[typeof object] && !this._isHTMLAllC ollection(object); | 266 return InjectedScript.primitiveTypes[typeof object] && !this._isHTMLAllC ollection(object); |
| 226 }, | 267 }, |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 getProperties: function(object, objectGroupName, ownProperties, accessorProp ertiesOnly, generatePreview) | 369 getProperties: function(object, objectGroupName, ownProperties, accessorProp ertiesOnly, generatePreview) |
| 329 { | 370 { |
| 330 var subtype = this._subtype(object); | 371 var subtype = this._subtype(object); |
| 331 if (subtype === "internal#scope") { | 372 if (subtype === "internal#scope") { |
| 332 // Internally, scope contains object with scope variables and additi onal information like type, | 373 // 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 | 374 // we use additional information for preview and would like to repor t variables as scope |
| 334 // properties. | 375 // properties. |
| 335 object = object.object; | 376 object = object.object; |
| 336 } | 377 } |
| 337 | 378 |
| 338 var descriptors = []; | |
| 339 var iter = this._propertyDescriptors(object, ownProperties, accessorProp ertiesOnly, undefined); | |
| 340 // Go over properties, wrap object values. | 379 // Go over properties, wrap object values. |
| 341 for (var descriptor of iter) { | 380 var adder = new InjectedScript.defaultPropertyAdder(); |
| 381 var descriptors = this._propertyDescriptors(object, ownProperties, acces sorPropertiesOnly, undefined, adder, false); | |
| 382 for (var i = 0; i < descriptors.length; ++i) { | |
| 383 var descriptor = descriptors[i]; | |
| 342 if ("get" in descriptor) | 384 if ("get" in descriptor) |
| 343 descriptor.get = this._wrapObject(descriptor.get, objectGroupNam e); | 385 descriptor.get = this._wrapObject(descriptor.get, objectGroupNam e); |
| 344 if ("set" in descriptor) | 386 if ("set" in descriptor) |
| 345 descriptor.set = this._wrapObject(descriptor.set, objectGroupNam e); | 387 descriptor.set = this._wrapObject(descriptor.set, objectGroupNam e); |
| 346 if ("value" in descriptor) | 388 if ("value" in descriptor) |
| 347 descriptor.value = this._wrapObject(descriptor.value, objectGrou pName, false, generatePreview); | 389 descriptor.value = this._wrapObject(descriptor.value, objectGrou pName, false, generatePreview); |
| 348 if (!("configurable" in descriptor)) | 390 if (!("configurable" in descriptor)) |
| 349 descriptor.configurable = false; | 391 descriptor.configurable = false; |
| 350 if (!("enumerable" in descriptor)) | 392 if (!("enumerable" in descriptor)) |
| 351 descriptor.enumerable = false; | 393 descriptor.enumerable = false; |
| 352 if ("symbol" in descriptor) | 394 if ("symbol" in descriptor) |
| 353 descriptor.symbol = this._wrapObject(descriptor.symbol, objectGr oupName); | 395 descriptor.symbol = this._wrapObject(descriptor.symbol, objectGr oupName); |
| 354 push(descriptors, descriptor); | |
| 355 } | 396 } |
| 356 return descriptors; | 397 return descriptors; |
| 357 }, | 398 }, |
| 358 | 399 |
| 359 /** | 400 /** |
| 360 * @param {!Object} object | 401 * @param {!Object} object |
| 361 * @return {?Object} | 402 * @return {?Object} |
| 362 */ | 403 */ |
| 363 _objectPrototype: function(object) | 404 _objectPrototype: function(object) |
| 364 { | 405 { |
| 365 if (InjectedScriptHost.subtype(object) === "proxy") | 406 if (InjectedScriptHost.subtype(object) === "proxy") |
| 366 return null; | 407 return null; |
| 367 try { | 408 try { |
| 368 return Object.getPrototypeOf(object); | 409 return Object.getPrototypeOf(object); |
| 369 } catch (e) { | 410 } catch (e) { |
| 370 return null; | 411 return null; |
| 371 } | 412 } |
| 372 }, | 413 }, |
| 373 | 414 |
| 374 /** | 415 /** |
| 375 * @param {!Object} object | 416 * @param {!Object} object |
| 376 * @param {boolean=} ownProperties | 417 * @param {boolean=} ownProperties |
| 377 * @param {boolean=} accessorPropertiesOnly | 418 * @param {boolean=} accessorPropertiesOnly |
| 378 * @param {?Array.<string>=} propertyNamesOnly | 419 * @param {?Array<string>=} propertyNamesOnly |
| 420 * @param {!InjectedScript.AdderWithThreshold=} adder | |
| 421 * @param {boolean=} forPreview | |
| 422 * @return {!Array} | |
| 379 */ | 423 */ |
| 380 _propertyDescriptors: function*(object, ownProperties, accessorPropertiesOnl y, propertyNamesOnly) | 424 _propertyDescriptors: function(object, ownProperties, accessorPropertiesOnly , propertyNamesOnly, adder, forPreview) |
| 381 { | 425 { |
| 426 var descriptors = []; | |
|
kozy
2017/02/21 19:01:55
descriptors.__proto__ = null;
and then we will be
luoe
2017/02/21 21:53:51
Done.
| |
| 427 if (!adder.isSpaceAvailable()) | |
| 428 return descriptors; | |
| 382 var propertyProcessed = { __proto__: null }; | 429 var propertyProcessed = { __proto__: null }; |
| 383 var subtype = InjectedScriptHost.subtype(object); | 430 var subtype = InjectedScriptHost.subtype(object); |
| 384 | 431 |
| 385 /** | 432 /** |
| 386 * @param {!Object} o | 433 * @param {!Object} o |
| 387 * @param {!Iterable<string|symbol|number>|!Array<string|number|symbol>} properties | 434 * @param {!Iterable<string|symbol|number>|!Array<string|number|symbol>= } properties |
| 388 */ | 435 */ |
| 389 function* process(o, properties) | 436 function process(o, properties) |
| 390 { | 437 { |
| 391 for (var property of properties) { | 438 // When properties is not provided, iterate over the object's indice s. |
| 439 var length = properties ? properties.length : (o.length || 0); | |
|
kozy
2017/02/21 19:01:55
o.length can throw.
luoe
2017/02/21 21:53:51
I'll pass in objectLength
| |
| 440 for (var i = 0; i < length; ++i) { | |
| 441 if (!adder.isSpaceAvailable()) | |
| 442 return; | |
| 443 var property = properties ? properties[i] : ("" + i); | |
| 392 if (propertyProcessed[property]) | 444 if (propertyProcessed[property]) |
| 393 continue; | 445 continue; |
| 394 propertyProcessed[property] = true; | 446 propertyProcessed[property] = true; |
| 395 | |
| 396 var name; | 447 var name; |
| 397 if (isSymbol(property)) | 448 if (isSymbol(property)) |
| 398 name = /** @type {string} */ (injectedScript._describe(prope rty)); | 449 name = /** @type {string} */ (injectedScript._describe(prope rty)); |
| 399 else | 450 else |
| 400 name = typeof property === "number" ? ("" + property) : /** @type {string} */(property); | 451 name = typeof property === "number" ? ("" + property) : /** @type {string} */(property); |
| 401 | 452 |
| 402 if (subtype === "internal#scopeList" && name === "length") | 453 if (subtype === "internal#scopeList" && name === "length") |
| 403 continue; | 454 continue; |
| 404 | 455 |
| 405 var descriptor; | 456 var descriptor; |
| 406 try { | 457 try { |
| 407 descriptor = Object.getOwnPropertyDescriptor(o, property); | 458 descriptor = Object.getOwnPropertyDescriptor(o, property); |
| 408 var isAccessorProperty = descriptor && ("get" in descriptor || "set" in descriptor); | 459 var isAccessorProperty = descriptor && ("get" in descriptor || "set" in descriptor); |
| 409 if (accessorPropertiesOnly && !isAccessorProperty) | 460 if (accessorPropertiesOnly && !isAccessorProperty) |
| 410 continue; | 461 continue; |
| 411 if (descriptor && "get" in descriptor && "set" in descriptor && name !== "__proto__" && | 462 if (descriptor && "get" in descriptor && "set" in descriptor && name !== "__proto__" && |
| 412 InjectedScriptHost.formatAccessorsAsProperties(objec t, descriptor.get) && | 463 InjectedScriptHost.formatAccessorsAsProperties(objec t, descriptor.get) && |
| 413 !doesAttributeHaveObservableSideEffectOnGet(object, name)) { | 464 !doesAttributeHaveObservableSideEffectOnGet(object, name)) { |
| 414 descriptor.value = object[property]; | 465 descriptor.value = object[property]; |
| 415 descriptor.isOwn = true; | 466 descriptor.isOwn = true; |
| 416 delete descriptor.get; | 467 delete descriptor.get; |
| 417 delete descriptor.set; | 468 delete descriptor.set; |
| 418 } | 469 } |
| 419 } catch (e) { | 470 } catch (e) { |
| 420 if (accessorPropertiesOnly) | 471 if (accessorPropertiesOnly || forPreview) |
| 421 continue; | 472 continue; |
| 422 descriptor = { value: e, wasThrown: true }; | 473 descriptor = { value: e, wasThrown: true }; |
| 423 } | 474 } |
| 424 | 475 |
| 425 // Not all bindings provide proper descriptors. Fall back to the non-configurable, non-enumerable, | 476 // Not all bindings provide proper descriptors. Fall back to the non-configurable, non-enumerable, |
| 426 // non-writable property. | 477 // non-writable property. |
| 427 if (!descriptor) { | 478 if (!descriptor) { |
| 428 try { | 479 try { |
| 429 descriptor = { value: o[property], writable: false }; | 480 descriptor = { value: o[property], writable: false }; |
| 430 } catch (e) { | 481 } catch (e) { |
| 431 // Silent catch. | 482 // Silent catch. |
| 432 continue; | 483 continue; |
| 433 } | 484 } |
| 434 } | 485 } |
| 435 | 486 |
| 436 descriptor.name = name; | 487 descriptor.name = name; |
| 437 if (o === object) | 488 if (o === object) |
| 438 descriptor.isOwn = true; | 489 descriptor.isOwn = true; |
| 439 if (isSymbol(property)) | 490 if (isSymbol(property)) |
| 440 descriptor.symbol = property; | 491 descriptor.symbol = property; |
| 441 yield nullifyObjectProto(descriptor); | 492 if (forPreview) { |
| 493 // Ignore __proto__ property. | |
| 494 if (name === "__proto__") | |
| 495 continue; | |
| 496 | |
| 497 // Ignore length property of array. | |
| 498 if ((subtype === "array" || subtype === "typedarray") && nam e === "length") | |
| 499 continue; | |
| 500 | |
| 501 // Ignore size property of map, set. | |
| 502 if ((subtype === "map" || subtype === "set") && name === "si ze") | |
| 503 continue; | |
| 504 | |
| 505 // Never preview prototype properties. | |
| 506 if (!descriptor.isOwn) | |
| 507 continue; | |
| 508 | |
| 509 // Ignore computed properties unless they have getters. | |
| 510 if (!("value" in descriptor) && !descriptor.get) | |
| 511 continue; | |
| 512 } | |
| 513 adder.add(descriptors, nullifyObjectProto(descriptor)); | |
| 442 } | 514 } |
| 443 } | 515 } |
| 444 | 516 |
| 445 if (propertyNamesOnly) { | 517 if (propertyNamesOnly) { |
| 446 for (var i = 0; i < propertyNamesOnly.length; ++i) { | 518 for (var i = 0; i < propertyNamesOnly.length; ++i) { |
| 447 var name = propertyNamesOnly[i]; | 519 var name = propertyNamesOnly[i]; |
| 448 for (var o = object; this._isDefined(o); o = this._objectPrototy pe(o)) { | 520 for (var o = object; this._isDefined(o); o = this._objectPrototy pe(/** @type {!Object} */ (o))) { |
| 521 o = /** @type {!Object} */ (o); | |
| 449 if (InjectedScriptHost.objectHasOwnProperty(o, name)) { | 522 if (InjectedScriptHost.objectHasOwnProperty(o, name)) { |
| 450 for (var descriptor of process(/** @type {!Object} */ (o ), [name])) | 523 process(o, [name]); |
| 451 yield descriptor; | 524 if (!adder.isSpaceAvailable()) |
| 525 return descriptors; | |
| 452 break; | 526 break; |
| 453 } | 527 } |
| 454 if (ownProperties) | 528 if (ownProperties || forPreview) |
| 455 break; | 529 break; |
| 456 } | 530 } |
| 457 } | 531 } |
| 458 return; | 532 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 } | 533 } |
| 469 | 534 |
| 470 var skipGetOwnPropertyNames; | 535 var skipGetOwnPropertyNames; |
| 471 try { | 536 try { |
| 472 skipGetOwnPropertyNames = subtype === "typedarray" && object.length > 500000; | 537 skipGetOwnPropertyNames = subtype === "typedarray" && object.length > 500000; |
| 473 } catch (e) { | 538 } catch (e) { |
| 474 } | 539 } |
| 475 | 540 |
| 476 for (var o = object; this._isDefined(o); o = this._objectPrototype(o)) { | 541 for (var o = object; this._isDefined(o); o = this._objectPrototype(/** @ type {!Object} */ (o))) { |
| 477 /** @type {!Object} */ (o); | 542 o = /** @type {!Object} */ (o); |
| 478 if (InjectedScriptHost.subtype(o) === "proxy") | 543 if (InjectedScriptHost.subtype(o) === "proxy") |
| 479 continue; | 544 continue; |
| 480 if (skipGetOwnPropertyNames && o === object) { | 545 if (skipGetOwnPropertyNames && o === object) { |
| 481 // Avoid OOM crashes from getting all own property names of a la rge TypedArray. | 546 process(o, undefined); |
| 482 for (var descriptor of process(o, arrayIndexNames(o.length))) | |
| 483 yield descriptor; | |
| 484 } else { | 547 } else { |
| 485 // First call Object.keys() to enforce ordering of the property descriptors. | 548 // First call Object.keys() to enforce ordering of the property descriptors. |
| 486 for (var descriptor of process(o, Object.keys(o))) | 549 process(o, Object.keys(o)); |
|
kozy
2017/02/21 19:01:55
All Object.* can throw, can we wrap it with try ca
luoe
2017/02/21 21:53:51
Done.
| |
| 487 yield descriptor; | 550 if (adder.isSpaceAvailable()) |
| 488 for (var descriptor of process(o, Object.getOwnPropertyNames(o)) ) | 551 process(o, Object.getOwnPropertyNames(o)); |
| 489 yield descriptor; | |
| 490 } | 552 } |
| 491 if (Object.getOwnPropertySymbols) { | 553 if (adder.isSpaceAvailable() && Object.getOwnPropertySymbols) |
| 492 for (var descriptor of process(o, Object.getOwnPropertySymbols(o ))) | 554 process(o, Object.getOwnPropertySymbols(o)); |
| 493 yield descriptor; | |
| 494 } | |
| 495 if (ownProperties) { | 555 if (ownProperties) { |
| 496 var proto = this._objectPrototype(o); | 556 var proto = this._objectPrototype(o); |
| 497 if (proto && !accessorPropertiesOnly) | 557 if (adder.isSpaceAvailable() && proto && !accessorPropertiesOnly ) { |
| 498 yield { name: "__proto__", value: proto, writable: true, con figurable: true, enumerable: false, isOwn: true, __proto__: null }; | 558 var descriptor = { name: "__proto__", value: proto, writable : true, configurable: true, enumerable: false, isOwn: true, __proto__: null }; |
| 559 adder.add(descriptors, descriptor); | |
| 560 } | |
| 561 } | |
| 562 if (ownProperties || forPreview) | |
| 499 break; | 563 break; |
| 500 } | |
| 501 } | 564 } |
| 565 return descriptors; | |
| 502 }, | 566 }, |
| 503 | 567 |
| 504 /** | 568 /** |
| 505 * @param {string|undefined} objectGroupName | 569 * @param {string|undefined} objectGroupName |
| 506 * @param {*} jsonMLObject | 570 * @param {*} jsonMLObject |
| 507 * @throws {string} error message | 571 * @throws {string} error message |
| 508 */ | 572 */ |
| 509 _substituteObjectTagsInCustomPreview: function(objectGroupName, jsonMLObject ) | 573 _substituteObjectTagsInCustomPreview: function(objectGroupName, jsonMLObject ) |
| 510 { | 574 { |
| 511 var maxCustomPreviewRecursionDepth = 20; | 575 var maxCustomPreviewRecursionDepth = 20; |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 770 this.preview = this._generatePreview(object, undefined, columnNames, isTable, skipEntriesPreview); | 834 this.preview = this._generatePreview(object, undefined, columnNames, isTable, skipEntriesPreview); |
| 771 } | 835 } |
| 772 | 836 |
| 773 if (injectedScript._customObjectFormatterEnabled) { | 837 if (injectedScript._customObjectFormatterEnabled) { |
| 774 var customPreview = this._customPreview(object, objectGroupName, customO bjectConfig); | 838 var customPreview = this._customPreview(object, objectGroupName, customO bjectConfig); |
| 775 if (customPreview) | 839 if (customPreview) |
| 776 this.customPreview = customPreview; | 840 this.customPreview = customPreview; |
| 777 } | 841 } |
| 778 } | 842 } |
| 779 | 843 |
| 844 /** | |
| 845 * @implements {InjectedScript.AdderWithThreshold} | |
| 846 * @constructor | |
| 847 * @param {boolean} isTable | |
| 848 * @param {number} firstLevelKeysCount | |
| 849 */ | |
| 850 InjectedScript.PreviewPropertyAdder = function (isTable, firstLevelKeysCount) { | |
| 851 this._propertiesThreshold = { | |
| 852 properties: isTable ? 1000 : max(5, firstLevelKeysCount), | |
| 853 indexes: isTable ? 1000 : max(100, firstLevelKeysCount), | |
| 854 __proto__: null | |
| 855 }; | |
| 856 this._overflow = false; | |
| 857 }; | |
| 858 | |
| 859 InjectedScript.PreviewPropertyAdder.prototype = { | |
| 860 /** | |
| 861 * @override | |
| 862 * @param {!Array<!Object>} descriptors | |
| 863 * @param {!Object} descriptor | |
| 864 */ | |
| 865 add: function (descriptors, descriptor) { | |
| 866 if (toString(descriptor.name >>> 0) === descriptor.name) | |
| 867 this._propertiesThreshold.indexes--; | |
| 868 else | |
| 869 this._propertiesThreshold.properties--; | |
| 870 if (!this.isSpaceAvailable()) | |
| 871 this._overflow = true; | |
| 872 else | |
| 873 push(descriptors, descriptor); | |
| 874 }, | |
| 875 | |
| 876 /** | |
| 877 * @override | |
| 878 * @return {boolean} | |
| 879 */ | |
| 880 isSpaceAvailable: function () { | |
| 881 return this._propertiesThreshold.indexes >= 0 && this._propertiesThresho ld.properties >= 0; | |
| 882 }, | |
| 883 | |
| 884 /** | |
| 885 * @return {boolean} | |
| 886 */ | |
| 887 overflows: function() { | |
| 888 return this._overflow; | |
| 889 } | |
| 890 }; | |
| 891 | |
| 780 InjectedScript.RemoteObject.prototype = { | 892 InjectedScript.RemoteObject.prototype = { |
| 781 | 893 |
| 782 /** | 894 /** |
| 783 * @param {*} object | 895 * @param {*} object |
| 784 * @param {string=} objectGroupName | 896 * @param {string=} objectGroupName |
| 785 * @param {*=} customObjectConfig | 897 * @param {*=} customObjectConfig |
| 786 * @return {?RuntimeAgent.CustomPreview} | 898 * @return {?RuntimeAgent.CustomPreview} |
| 787 */ | 899 */ |
| 788 _customPreview: function(object, objectGroupName, customObjectConfig) | 900 _customPreview: function(object, objectGroupName, customObjectConfig) |
| 789 { | 901 { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 857 * @param {?Array.<string>=} firstLevelKeys | 969 * @param {?Array.<string>=} firstLevelKeys |
| 858 * @param {?Array.<string>=} secondLevelKeys | 970 * @param {?Array.<string>=} secondLevelKeys |
| 859 * @param {boolean=} isTable | 971 * @param {boolean=} isTable |
| 860 * @param {boolean=} skipEntriesPreview | 972 * @param {boolean=} skipEntriesPreview |
| 861 * @return {!RuntimeAgent.ObjectPreview} preview | 973 * @return {!RuntimeAgent.ObjectPreview} preview |
| 862 */ | 974 */ |
| 863 _generatePreview: function(object, firstLevelKeys, secondLevelKeys, isTable, skipEntriesPreview) | 975 _generatePreview: function(object, firstLevelKeys, secondLevelKeys, isTable, skipEntriesPreview) |
| 864 { | 976 { |
| 865 var preview = this._createEmptyPreview(); | 977 var preview = this._createEmptyPreview(); |
| 866 var firstLevelKeysCount = firstLevelKeys ? firstLevelKeys.length : 0; | 978 var firstLevelKeysCount = firstLevelKeys ? firstLevelKeys.length : 0; |
| 867 | 979 var adder = new InjectedScript.PreviewPropertyAdder(!!isTable, firstLeve lKeysCount); |
| 868 var propertiesThreshold = { | |
| 869 properties: isTable ? 1000 : max(5, firstLevelKeysCount), | |
| 870 indexes: isTable ? 1000 : max(100, firstLevelKeysCount), | |
| 871 __proto__: null | |
| 872 }; | |
| 873 | |
| 874 try { | 980 try { |
| 875 var descriptors = injectedScript._propertyDescriptors(object, undefi ned, undefined, firstLevelKeys); | 981 var descriptors = injectedScript._propertyDescriptors(object, undefi ned, undefined, firstLevelKeys, adder, true); |
| 876 | |
| 877 this._appendPropertyDescriptors(preview, descriptors, propertiesThre shold, secondLevelKeys, isTable); | |
| 878 if (propertiesThreshold.indexes < 0 || propertiesThreshold.propertie s < 0) | |
| 879 return preview; | |
| 880 | 982 |
| 881 // Add internal properties to preview. | 983 // Add internal properties to preview. |
| 882 var rawInternalProperties = InjectedScriptHost.getInternalProperties (object) || []; | 984 var rawInternalProperties = InjectedScriptHost.getInternalProperties (object) || []; |
| 883 var internalProperties = []; | 985 var internalProperties = []; |
| 884 var entries = null; | 986 var entries = null; |
| 885 for (var i = 0; i < rawInternalProperties.length; i += 2) { | 987 for (var i = 0; i < rawInternalProperties.length; i += 2) { |
| 886 if (rawInternalProperties[i] === "[[Entries]]") { | 988 if (rawInternalProperties[i] === "[[Entries]]") { |
| 887 entries = /** @type {!Array<*>} */(rawInternalProperties[i + 1]); | 989 entries = /** @type {!Array<*>} */(rawInternalProperties[i + 1]); |
| 888 continue; | 990 continue; |
| 889 } | 991 } |
| 890 push(internalProperties, { | 992 var internalPropertyDescriptor = { |
| 891 name: rawInternalProperties[i], | 993 name: rawInternalProperties[i], |
| 892 value: rawInternalProperties[i + 1], | 994 value: rawInternalProperties[i + 1], |
| 893 isOwn: true, | 995 isOwn: true, |
| 894 enumerable: true, | 996 enumerable: true, |
| 895 __proto__: null | 997 __proto__: null |
| 896 }); | 998 }; |
| 999 adder.add(descriptors, internalPropertyDescriptor); | |
|
kozy
2017/02/21 19:01:55
Our push safer.
luoe
2017/02/21 21:53:51
Replaced with a customPush() that calls push() int
| |
| 897 } | 1000 } |
| 898 this._appendPropertyDescriptors(preview, internalProperties, propert iesThreshold, secondLevelKeys, isTable); | 1001 this._appendPropertyPreviewDescriptors(preview, descriptors, secondL evelKeys, isTable); |
| 899 | 1002 |
| 900 if (this.subtype === "map" || this.subtype === "set" || this.subtype === "iterator") | 1003 if (this.subtype === "map" || this.subtype === "set" || this.subtype === "iterator") |
| 901 this._appendEntriesPreview(entries, preview, skipEntriesPreview) ; | 1004 this._appendEntriesPreview(entries, preview, skipEntriesPreview) ; |
| 902 | 1005 |
| 903 } catch (e) {} | 1006 } catch (e) {} |
| 1007 preview.overflow = preview.overflow || adder.overflows(); | |
| 904 | 1008 |
| 905 return preview; | 1009 return preview; |
| 906 }, | 1010 }, |
| 907 | 1011 |
| 908 /** | 1012 /** |
| 909 * @param {!RuntimeAgent.ObjectPreview} preview | 1013 * @param {!RuntimeAgent.ObjectPreview} preview |
| 910 * @param {!Array.<*>|!Iterable.<*>} descriptors | 1014 * @param {!Array.<*>|!Iterable.<*>} descriptors |
| 911 * @param {!Object} propertiesThreshold | |
| 912 * @param {?Array.<string>=} secondLevelKeys | 1015 * @param {?Array.<string>=} secondLevelKeys |
| 913 * @param {boolean=} isTable | 1016 * @param {boolean=} isTable |
| 914 */ | 1017 */ |
| 915 _appendPropertyDescriptors: function(preview, descriptors, propertiesThresho ld, secondLevelKeys, isTable) | 1018 _appendPropertyPreviewDescriptors: function(preview, descriptors, secondLeve lKeys, isTable) |
| 916 { | 1019 { |
| 917 for (var descriptor of descriptors) { | 1020 for (var i = 0; i < descriptors.length; ++i) { |
| 918 if (propertiesThreshold.indexes < 0 || propertiesThreshold.propertie s < 0) | 1021 var descriptor = descriptors[i]; |
| 919 break; | |
| 920 if (!descriptor || descriptor.wasThrown) | |
| 921 continue; | |
| 922 | |
| 923 var name = descriptor.name; | 1022 var name = descriptor.name; |
| 924 | |
| 925 // Ignore __proto__ property. | |
| 926 if (name === "__proto__") | |
| 927 continue; | |
| 928 | |
| 929 // Ignore length property of array. | |
| 930 if ((this.subtype === "array" || this.subtype === "typedarray") && n ame === "length") | |
| 931 continue; | |
| 932 | |
| 933 // Ignore size property of map, set. | |
| 934 if ((this.subtype === "map" || this.subtype === "set") && name === " size") | |
| 935 continue; | |
| 936 | |
| 937 // Never preview prototype properties. | |
| 938 if (!descriptor.isOwn) | |
| 939 continue; | |
| 940 | |
| 941 // Ignore computed properties unless they have getters. | |
| 942 if (!("value" in descriptor)) { | |
| 943 if (descriptor.get) | |
| 944 this._appendPropertyPreview(preview, { name: name, type: "ac cessor", __proto__: null }, propertiesThreshold); | |
| 945 continue; | |
| 946 } | |
| 947 | |
| 948 var value = descriptor.value; | 1023 var value = descriptor.value; |
| 949 var type = typeof value; | 1024 var type = typeof value; |
| 950 | 1025 |
| 951 // Special-case HTMLAll. | 1026 // Special-case HTMLAll. |
| 952 if (type === "undefined" && injectedScript._isHTMLAllCollection(valu e)) | 1027 if (type === "undefined" && injectedScript._isHTMLAllCollection(valu e)) |
| 953 type = "object"; | 1028 type = "object"; |
| 954 | 1029 |
| 955 // Render own properties. | 1030 // Ignore computed properties unless they have getters. |
| 956 if (value === null) { | 1031 if (descriptor.get && !("value" in descriptor)) { |
| 957 this._appendPropertyPreview(preview, { name: name, type: "object ", subtype: "null", value: "null", __proto__: null }, propertiesThreshold); | 1032 push(preview.properties, { name: name, type: "accessor", __proto __: null }); |
| 958 continue; | 1033 continue; |
| 959 } | 1034 } |
| 960 | 1035 |
| 1036 // Render own properties. | |
| 1037 if (value === null) { | |
| 1038 push(preview.properties, { name: name, type: "object", subtype: "null", value: "null", __proto__: null }); | |
| 1039 continue; | |
| 1040 } | |
| 1041 | |
| 961 var maxLength = 100; | 1042 var maxLength = 100; |
| 962 if (InjectedScript.primitiveTypes[type]) { | 1043 if (InjectedScript.primitiveTypes[type]) { |
| 963 if (type === "string" && value.length > maxLength) | 1044 if (type === "string" && value.length > maxLength) |
| 964 value = this._abbreviateString(value, maxLength, true); | 1045 value = this._abbreviateString(value, maxLength, true); |
| 965 this._appendPropertyPreview(preview, { name: name, type: type, v alue: toStringDescription(value), __proto__: null }, propertiesThreshold); | 1046 push(preview.properties, { name: name, type: type, value: toStri ngDescription(value), __proto__: null }); |
| 966 continue; | 1047 continue; |
| 967 } | 1048 } |
| 968 | 1049 |
| 969 var property = { name: name, type: type, __proto__: null }; | 1050 var property = { name: name, type: type, __proto__: null }; |
| 970 var subtype = injectedScript._subtype(value); | 1051 var subtype = injectedScript._subtype(value); |
| 971 if (subtype) | 1052 if (subtype) |
| 972 property.subtype = subtype; | 1053 property.subtype = subtype; |
| 973 | 1054 |
| 974 if (secondLevelKeys === null || secondLevelKeys) { | 1055 if (secondLevelKeys === null || secondLevelKeys) { |
| 975 var subPreview = this._generatePreview(value, secondLevelKeys || undefined, undefined, isTable); | 1056 var subPreview = this._generatePreview(value, secondLevelKeys || undefined, undefined, isTable); |
| 976 property.valuePreview = subPreview; | 1057 property.valuePreview = subPreview; |
| 977 if (subPreview.overflow) | 1058 if (subPreview.overflow) |
| 978 preview.overflow = true; | 1059 preview.overflow = true; |
| 979 } else { | 1060 } else { |
| 980 var description = ""; | 1061 var description = ""; |
| 981 if (type !== "function") | 1062 if (type !== "function") |
| 982 description = this._abbreviateString(/** @type {string} */ ( injectedScript._describe(value)), maxLength, subtype === "regexp"); | 1063 description = this._abbreviateString(/** @type {string} */ ( injectedScript._describe(value)), maxLength, subtype === "regexp"); |
| 983 property.value = description; | 1064 property.value = description; |
| 984 } | 1065 } |
| 985 this._appendPropertyPreview(preview, property, propertiesThreshold); | |
| 986 } | |
| 987 }, | |
| 988 | |
| 989 /** | |
| 990 * @param {!RuntimeAgent.ObjectPreview} preview | |
| 991 * @param {!Object} property | |
| 992 * @param {!Object} propertiesThreshold | |
| 993 */ | |
| 994 _appendPropertyPreview: function(preview, property, propertiesThreshold) | |
| 995 { | |
| 996 if (toString(property.name >>> 0) === property.name) | |
| 997 propertiesThreshold.indexes--; | |
| 998 else | |
| 999 propertiesThreshold.properties--; | |
| 1000 if (propertiesThreshold.indexes < 0 || propertiesThreshold.properties < 0) { | |
| 1001 preview.overflow = true; | |
| 1002 } else { | |
| 1003 push(preview.properties, property); | 1066 push(preview.properties, property); |
| 1004 } | 1067 } |
| 1005 }, | 1068 }, |
| 1006 | 1069 |
| 1007 /** | 1070 /** |
| 1008 * @param {?Array<*>} entries | 1071 * @param {?Array<*>} entries |
| 1009 * @param {!RuntimeAgent.ObjectPreview} preview | 1072 * @param {!RuntimeAgent.ObjectPreview} preview |
| 1010 * @param {boolean=} skipEntriesPreview | 1073 * @param {boolean=} skipEntriesPreview |
| 1011 */ | 1074 */ |
| 1012 _appendEntriesPreview: function(entries, preview, skipEntriesPreview) | 1075 _appendEntriesPreview: function(entries, preview, skipEntriesPreview) |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1063 return string.substr(0, leftHalf) + "\u2026" + string.substr(string. length - rightHalf, rightHalf); | 1126 return string.substr(0, leftHalf) + "\u2026" + string.substr(string. length - rightHalf, rightHalf); |
| 1064 } | 1127 } |
| 1065 return string.substr(0, maxLength) + "\u2026"; | 1128 return string.substr(0, maxLength) + "\u2026"; |
| 1066 }, | 1129 }, |
| 1067 | 1130 |
| 1068 __proto__: null | 1131 __proto__: null |
| 1069 } | 1132 } |
| 1070 | 1133 |
| 1071 return injectedScript; | 1134 return injectedScript; |
| 1072 }) | 1135 }) |
| OLD | NEW |