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 |