+2015-03-06 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: ES6: Improved Support for Iterator Objects
+ https://bugs.webkit.org/show_bug.cgi?id=142420
+
+ Reviewed by Timothy Hatcher.
+
+ * inspector/model/remote-object.html:
+ Update tests to include iterator objects.
+
2015-03-06 Brent Fulgham <bfulgham@apple.com>
[Win] Mark svg/fonts/svg-font-horiz-orig.html as Image-only failing.
}
-----------------------------------------------------
+EXPRESSION: 'a'[Symbol.iterator]()
+{
+ "_type": "object",
+ "_subtype": "iterator",
+ "_objectId": "<filtered>",
+ "_description": "StringIterator",
+ "_preview": {
+ "_type": "object",
+ "_subtype": "iterator",
+ "_description": "StringIterator",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": [
+ {
+ "_name": "string",
+ "_type": "string",
+ "_value": "a",
+ "_internal": true
+ }
+ ],
+ "_entries": [
+ {
+ "_value": {
+ "_type": "string",
+ "_description": "a",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: 'long string'[Symbol.iterator]()
+{
+ "_type": "object",
+ "_subtype": "iterator",
+ "_objectId": "<filtered>",
+ "_description": "StringIterator",
+ "_preview": {
+ "_type": "object",
+ "_subtype": "iterator",
+ "_description": "StringIterator",
+ "_lossless": false,
+ "_overflow": true,
+ "_properties": [
+ {
+ "_name": "string",
+ "_type": "string",
+ "_value": "long string",
+ "_internal": true
+ }
+ ],
+ "_entries": [
+ {
+ "_value": {
+ "_type": "string",
+ "_description": "l",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "string",
+ "_description": "o",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "string",
+ "_description": "n",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "string",
+ "_description": "g",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "string",
+ "_description": " ",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: [][Symbol.iterator]()
+{
+ "_type": "object",
+ "_subtype": "iterator",
+ "_objectId": "<filtered>",
+ "_description": "ArrayIterator",
+ "_preview": {
+ "_type": "object",
+ "_subtype": "iterator",
+ "_description": "ArrayIterator",
+ "_lossless": false,
+ "_overflow": false,
+ "_properties": [
+ {
+ "_name": "array",
+ "_type": "object",
+ "_subtype": "array",
+ "_value": "Array",
+ "_internal": true
+ },
+ {
+ "_name": "kind",
+ "_type": "string",
+ "_value": "value",
+ "_internal": true
+ }
+ ],
+ "_entries": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: [1][Symbol.iterator]()
+{
+ "_type": "object",
+ "_subtype": "iterator",
+ "_objectId": "<filtered>",
+ "_description": "ArrayIterator",
+ "_preview": {
+ "_type": "object",
+ "_subtype": "iterator",
+ "_description": "ArrayIterator",
+ "_lossless": false,
+ "_overflow": false,
+ "_properties": [
+ {
+ "_name": "array",
+ "_type": "object",
+ "_subtype": "array",
+ "_value": "Array",
+ "_internal": true
+ },
+ {
+ "_name": "kind",
+ "_type": "string",
+ "_value": "value",
+ "_internal": true
+ }
+ ],
+ "_entries": [
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "1",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: [1, 'two', 3, 'four', 5, 'size'][Symbol.iterator]()
+{
+ "_type": "object",
+ "_subtype": "iterator",
+ "_objectId": "<filtered>",
+ "_description": "ArrayIterator",
+ "_preview": {
+ "_type": "object",
+ "_subtype": "iterator",
+ "_description": "ArrayIterator",
+ "_lossless": false,
+ "_overflow": true,
+ "_properties": [
+ {
+ "_name": "array",
+ "_type": "object",
+ "_subtype": "array",
+ "_value": "Array",
+ "_internal": true
+ },
+ {
+ "_name": "kind",
+ "_type": "string",
+ "_value": "value",
+ "_internal": true
+ }
+ ],
+ "_entries": [
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "1",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "string",
+ "_description": "two",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "3",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "string",
+ "_description": "four",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "5",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: [1, 'two', 3, 'four', 5, 'size'].keys()
+{
+ "_type": "object",
+ "_subtype": "iterator",
+ "_objectId": "<filtered>",
+ "_description": "ArrayIterator",
+ "_preview": {
+ "_type": "object",
+ "_subtype": "iterator",
+ "_description": "ArrayIterator",
+ "_lossless": false,
+ "_overflow": true,
+ "_properties": [
+ {
+ "_name": "array",
+ "_type": "object",
+ "_subtype": "array",
+ "_value": "Array",
+ "_internal": true
+ },
+ {
+ "_name": "kind",
+ "_type": "string",
+ "_value": "key",
+ "_internal": true
+ }
+ ],
+ "_entries": [
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "0",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "1",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "2",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "3",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "4",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: [1, 'two', 3, 'four', 5, 'size'].entries()
+{
+ "_type": "object",
+ "_subtype": "iterator",
+ "_objectId": "<filtered>",
+ "_description": "ArrayIterator",
+ "_preview": {
+ "_type": "object",
+ "_subtype": "iterator",
+ "_description": "ArrayIterator",
+ "_lossless": false,
+ "_overflow": true,
+ "_properties": [
+ {
+ "_name": "array",
+ "_type": "object",
+ "_subtype": "array",
+ "_value": "Array",
+ "_internal": true
+ },
+ {
+ "_name": "kind",
+ "_type": "string",
+ "_value": "key+value",
+ "_internal": true
+ }
+ ],
+ "_entries": [
+ {
+ "_value": {
+ "_type": "object",
+ "_subtype": "array",
+ "_description": "Array",
+ "_lossless": true,
+ "_overflow": false,
+ "_size": 2,
+ "_properties": [
+ {
+ "_name": "0",
+ "_type": "number",
+ "_value": "0"
+ },
+ {
+ "_name": "1",
+ "_type": "number",
+ "_value": "1"
+ }
+ ],
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "object",
+ "_subtype": "array",
+ "_description": "Array",
+ "_lossless": true,
+ "_overflow": false,
+ "_size": 2,
+ "_properties": [
+ {
+ "_name": "0",
+ "_type": "number",
+ "_value": "1"
+ },
+ {
+ "_name": "1",
+ "_type": "string",
+ "_value": "two"
+ }
+ ],
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "object",
+ "_subtype": "array",
+ "_description": "Array",
+ "_lossless": true,
+ "_overflow": false,
+ "_size": 2,
+ "_properties": [
+ {
+ "_name": "0",
+ "_type": "number",
+ "_value": "2"
+ },
+ {
+ "_name": "1",
+ "_type": "number",
+ "_value": "3"
+ }
+ ],
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "object",
+ "_subtype": "array",
+ "_description": "Array",
+ "_lossless": true,
+ "_overflow": false,
+ "_size": 2,
+ "_properties": [
+ {
+ "_name": "0",
+ "_type": "number",
+ "_value": "3"
+ },
+ {
+ "_name": "1",
+ "_type": "string",
+ "_value": "four"
+ }
+ ],
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "object",
+ "_subtype": "array",
+ "_description": "Array",
+ "_lossless": true,
+ "_overflow": false,
+ "_size": 2,
+ "_properties": [
+ {
+ "_name": "0",
+ "_type": "number",
+ "_value": "4"
+ },
+ {
+ "_name": "1",
+ "_type": "number",
+ "_value": "5"
+ }
+ ],
+ "_entries": null
+ }
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: map = new Map; map.set(1, 2); map.set('key', 'value'); map.values()
+{
+ "_type": "object",
+ "_subtype": "iterator",
+ "_objectId": "<filtered>",
+ "_description": "Map Iterator",
+ "_preview": {
+ "_type": "object",
+ "_subtype": "iterator",
+ "_description": "Map Iterator",
+ "_lossless": false,
+ "_overflow": false,
+ "_properties": [
+ {
+ "_name": "map",
+ "_type": "object",
+ "_subtype": "map",
+ "_value": "Map",
+ "_internal": true
+ },
+ {
+ "_name": "kind",
+ "_type": "string",
+ "_value": "value",
+ "_internal": true
+ }
+ ],
+ "_entries": [
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "2",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "string",
+ "_description": "value",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: map.keys()
+{
+ "_type": "object",
+ "_subtype": "iterator",
+ "_objectId": "<filtered>",
+ "_description": "Map Iterator",
+ "_preview": {
+ "_type": "object",
+ "_subtype": "iterator",
+ "_description": "Map Iterator",
+ "_lossless": false,
+ "_overflow": false,
+ "_properties": [
+ {
+ "_name": "map",
+ "_type": "object",
+ "_subtype": "map",
+ "_value": "Map",
+ "_internal": true
+ },
+ {
+ "_name": "kind",
+ "_type": "string",
+ "_value": "key",
+ "_internal": true
+ }
+ ],
+ "_entries": [
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "1",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "string",
+ "_description": "key",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: map.entries()
+{
+ "_type": "object",
+ "_subtype": "iterator",
+ "_objectId": "<filtered>",
+ "_description": "Map Iterator",
+ "_preview": {
+ "_type": "object",
+ "_subtype": "iterator",
+ "_description": "Map Iterator",
+ "_lossless": false,
+ "_overflow": false,
+ "_properties": [
+ {
+ "_name": "map",
+ "_type": "object",
+ "_subtype": "map",
+ "_value": "Map",
+ "_internal": true
+ },
+ {
+ "_name": "kind",
+ "_type": "string",
+ "_value": "key+value",
+ "_internal": true
+ }
+ ],
+ "_entries": [
+ {
+ "_value": {
+ "_type": "object",
+ "_subtype": "array",
+ "_description": "Array",
+ "_lossless": true,
+ "_overflow": false,
+ "_size": 2,
+ "_properties": [
+ {
+ "_name": "0",
+ "_type": "number",
+ "_value": "1"
+ },
+ {
+ "_name": "1",
+ "_type": "number",
+ "_value": "2"
+ }
+ ],
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "object",
+ "_subtype": "array",
+ "_description": "Array",
+ "_lossless": true,
+ "_overflow": false,
+ "_size": 2,
+ "_properties": [
+ {
+ "_name": "0",
+ "_type": "string",
+ "_value": "key"
+ },
+ {
+ "_name": "1",
+ "_type": "string",
+ "_value": "value"
+ }
+ ],
+ "_entries": null
+ }
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: set = new Set; for (var i = 0; i <= 100; i++) set.add(i); set.values()
+{
+ "_type": "object",
+ "_subtype": "iterator",
+ "_objectId": "<filtered>",
+ "_description": "Set Iterator",
+ "_preview": {
+ "_type": "object",
+ "_subtype": "iterator",
+ "_description": "Set Iterator",
+ "_lossless": false,
+ "_overflow": true,
+ "_properties": [
+ {
+ "_name": "set",
+ "_type": "object",
+ "_subtype": "set",
+ "_value": "Set",
+ "_internal": true
+ },
+ {
+ "_name": "kind",
+ "_type": "string",
+ "_value": "value",
+ "_internal": true
+ }
+ ],
+ "_entries": [
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "0",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "1",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "2",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "3",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "4",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: map.entries()
+{
+ "_type": "object",
+ "_subtype": "iterator",
+ "_objectId": "<filtered>",
+ "_description": "Map Iterator",
+ "_preview": {
+ "_type": "object",
+ "_subtype": "iterator",
+ "_description": "Map Iterator",
+ "_lossless": false,
+ "_overflow": false,
+ "_properties": [
+ {
+ "_name": "map",
+ "_type": "object",
+ "_subtype": "map",
+ "_value": "Map",
+ "_internal": true
+ },
+ {
+ "_name": "kind",
+ "_type": "string",
+ "_value": "key+value",
+ "_internal": true
+ }
+ ],
+ "_entries": [
+ {
+ "_value": {
+ "_type": "object",
+ "_subtype": "array",
+ "_description": "Array",
+ "_lossless": true,
+ "_overflow": false,
+ "_size": 2,
+ "_properties": [
+ {
+ "_name": "0",
+ "_type": "number",
+ "_value": "1"
+ },
+ {
+ "_name": "1",
+ "_type": "number",
+ "_value": "2"
+ }
+ ],
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "object",
+ "_subtype": "array",
+ "_description": "Array",
+ "_lossless": true,
+ "_overflow": false,
+ "_size": 2,
+ "_properties": [
+ {
+ "_name": "0",
+ "_type": "string",
+ "_value": "key"
+ },
+ {
+ "_name": "1",
+ "_type": "string",
+ "_value": "value"
+ }
+ ],
+ "_entries": null
+ }
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: x = undefined; (function() { x = arguments; })(1, 'two'); x[Symbol.iterator]()
+{
+ "_type": "object",
+ "_subtype": "iterator",
+ "_objectId": "<filtered>",
+ "_description": "ArgumentsIterator",
+ "_preview": {
+ "_type": "object",
+ "_subtype": "iterator",
+ "_description": "ArgumentsIterator",
+ "_lossless": false,
+ "_overflow": false,
+ "_properties": [
+ {
+ "_name": "arguments",
+ "_type": "object",
+ "_subtype": "array",
+ "_value": "Arguments",
+ "_internal": true
+ }
+ ],
+ "_entries": [
+ {
+ "_value": {
+ "_type": "number",
+ "_description": "1",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ },
+ {
+ "_value": {
+ "_type": "string",
+ "_description": "two",
+ "_lossless": true,
+ "_overflow": false,
+ "_properties": null,
+ "_entries": null
+ }
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
EXPRESSION: new Promise(function(){})
{
"_type": "object",
{expression: "set = new Set; set.add({a:1}); set.add(document.body); set.add([1,2]); set"},
{expression: "set = new Set; for (var i = 0; i <= 100; i++) set.add(i); set"},
+ // Iterators
+ {expression: "'a'[Symbol.iterator]()"},
+ {expression: "'long string'[Symbol.iterator]()"},
+ {expression: "[][Symbol.iterator]()"},
+ {expression: "[1][Symbol.iterator]()"},
+ {expression: "[1, 'two', 3, 'four', 5, 'size'][Symbol.iterator]()"},
+ {expression: "[1, 'two', 3, 'four', 5, 'size'].keys()"},
+ {expression: "[1, 'two', 3, 'four', 5, 'size'].entries()"},
+ {expression: "map = new Map; map.set(1, 2); map.set('key', 'value'); map.values()"},
+ {expression: "map.keys()"},
+ {expression: "map.entries()"},
+ {expression: "set = new Set; for (var i = 0; i <= 100; i++) set.add(i); set.values()"},
+ {expression: "map.entries()"},
+ {expression: "x = undefined; (function() { x = arguments; })(1, 'two'); x[Symbol.iterator]()"},
+
// Promise
{expression: "new Promise(function(){})"},
{expression: "Promise.reject()"},
return value;
}
- function runNextStep() {
- if (currentStepIndex >= steps.length) {
- InspectorTest.completeTest();
- return;
- }
+ function runSteps() {
- var step = steps[currentStepIndex++];
- if (step.browserOnly) {
- runNextStep();
- return;
+ function afterStep() {
+ if (++currentStepIndex >= steps.length)
+ InspectorTest.completeTest();
}
- InspectorTest.log("");
- InspectorTest.log("-----------------------------------------------------");
- InspectorTest.log("EXPRESSION: " + step.expression);
+ function runStep(step) {
+ if (step.browserOnly) {
+ afterStep();
+ return;
+ }
+
+ WebInspector.runtimeManager.evaluateInInspectedWindow(step.expression, "test", false, true, false, true, false, function(remoteObject, wasThrown) {
+ InspectorTest.log("");
+ InspectorTest.log("-----------------------------------------------------");
+ InspectorTest.log("EXPRESSION: " + step.expression);
+ InspectorTest.assert(remoteObject instanceof WebInspector.RemoteObject);
+ InspectorTest.log(JSON.stringify(remoteObject, remoteObjectJSONFilter, " "));
+ afterStep();
+ });
+ }
- WebInspector.runtimeManager.evaluateInInspectedWindow(step.expression, "test", false, true, false, true, false, function(remoteObject, wasThrown) {
- InspectorTest.assert(remoteObject instanceof WebInspector.RemoteObject);
- InspectorTest.log(JSON.stringify(remoteObject, remoteObjectJSONFilter, " "));
- runNextStep();
- });
+ for (var step of steps)
+ runStep(step);
}
- runNextStep();
+ runSteps();
}
function runInBrowserTest()
+2015-03-06 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: ES6: Improved Support for Iterator Objects
+ https://bugs.webkit.org/show_bug.cgi?id=142420
+
+ Reviewed by Timothy Hatcher.
+
+ * inspector/protocol/Runtime.json:
+ Add new object subtype "iterator" for built-in iterator objects.
+
+ * inspector/InjectedScriptSource.js:
+ Return iterator values as Entry objects.
+
+ * inspector/JSInjectedScriptHost.cpp:
+ (Inspector::JSInjectedScriptHost::subtype):
+ Identify "iterator" typed objects.
+
+ (Inspector::JSInjectedScriptHost::getInternalProperties):
+ Provide internal properties for the different Iterator objects.
+
+ (Inspector::JSInjectedScriptHost::iteratorEntries):
+ Fetch the next few iterator entries of a built-in iterator object.
+
+ * inspector/JSInjectedScriptHost.h:
+ * inspector/JSInjectedScriptHostPrototype.cpp:
+ (Inspector::JSInjectedScriptHostPrototype::finishCreation):
+ (Inspector::jsInjectedScriptHostPrototypeFunctionIteratorEntries):
+ Call through to JSInjectedScriptHost.
+
+ * runtime/JSArgumentsIterator.cpp:
+ (JSC::JSArgumentsIterator::clone):
+ * runtime/JSArgumentsIterator.h:
+ (JSC::JSArgumentsIterator::iteratedValue):
+ * runtime/JSArrayIterator.cpp:
+ (JSC::JSArrayIterator::kind):
+ (JSC::JSArrayIterator::iteratedValue):
+ (JSC::JSArrayIterator::clone):
+ * runtime/JSArrayIterator.h:
+ * runtime/JSMapIterator.cpp:
+ (JSC::JSMapIterator::finishCreation):
+ (JSC::JSMapIterator::clone):
+ * runtime/JSMapIterator.h:
+ (JSC::JSMapIterator::kind):
+ (JSC::JSMapIterator::iteratedValue):
+ * runtime/JSSetIterator.cpp:
+ (JSC::JSSetIterator::finishCreation):
+ (JSC::JSSetIterator::clone):
+ * runtime/JSSetIterator.h:
+ (JSC::JSSetIterator::kind):
+ (JSC::JSSetIterator::iteratedValue):
+ * runtime/JSStringIterator.cpp:
+ (JSC::JSStringIterator::iteratedValue):
+ (JSC::JSStringIterator::clone):
+ * runtime/JSStringIterator.h:
+ Add accessors for internal properties and provide a way to clone the
+ iterator so we can be at the same index and peek at the next few
+ objects without modifying the original iterator object.
+
2015-03-06 Ryosuke Niwa <rniwa@webkit.org>
REGRESSION(r180595): construct varargs fails in FTL
if (typeof object !== "object")
return;
- var entries = this._getCollectionEntries(object, InjectedScriptHost.subtype(object), startIndex, numberToFetch);
+ var entries = this._entries(object, InjectedScriptHost.subtype(object), startIndex, numberToFetch);
return entries.map(function(entry) {
entry.value = injectedScript._wrapObject(entry.value, objectGroupName, false, true);
if ("key" in entry)
return InjectedScriptHost.weakMapEntries(object, numberToFetch);
},
- _getCollectionEntries: function(object, subtype, startIndex, numberToFetch)
+ _getIteratorEntries: function(object, numberToFetch)
+ {
+ return InjectedScriptHost.iteratorEntries(object, numberToFetch);
+ },
+
+ _entries: function(object, subtype, startIndex, numberToFetch)
{
if (subtype === "set")
return this._getSetEntries(object, startIndex, numberToFetch);
return this._getMapEntries(object, startIndex, numberToFetch);
if (subtype === "weakmap")
return this._getWeakMapEntries(object, numberToFetch);
+ if (subtype === "iterator")
+ return this._getIteratorEntries(object, numberToFetch);
throw "unexpected type";
},
};
try {
- // Maps and Sets have entries.
- if (this.subtype === "map" || this.subtype === "set" || this.subtype === "weakmap")
+ // Maps, Sets, and Iterators have entries.
+ if (this.subtype === "map" || this.subtype === "set" || this.subtype === "weakmap" || this.subtype === "iterator")
this._appendEntryPreviews(object, preview);
preview.properties = [];
_appendEntryPreviews: function(object, preview)
{
// Fetch 6, but only return 5, so we can tell if we overflowed.
- var entries = injectedScript._getCollectionEntries(object, this.subtype, 0, 6);
+ var entries = injectedScript._entries(object, this.subtype, 0, 6);
if (!entries)
return;
#include "DateInstance.h"
#include "Error.h"
#include "InjectedScriptHost.h"
+#include "IteratorOperations.h"
+#include "JSArgumentsIterator.h"
#include "JSArray.h"
+#include "JSArrayIterator.h"
#include "JSBoundFunction.h"
#include "JSCInlines.h"
#include "JSFunction.h"
#include "JSInjectedScriptHostPrototype.h"
#include "JSMap.h"
+#include "JSMapIterator.h"
#include "JSSet.h"
+#include "JSSetIterator.h"
+#include "JSStringIterator.h"
#include "JSTypedArrays.h"
#include "JSWeakMap.h"
#include "ObjectConstructor.h"
if (value.inherits(JSWeakMap::info()))
return jsNontrivialString(exec, ASCIILiteral("weakmap"));
+ if (value.inherits(JSArrayIterator::info())
+ || value.inherits(JSMapIterator::info())
+ || value.inherits(JSSetIterator::info())
+ || value.inherits(JSStringIterator::info())
+ || value.inherits(JSArgumentsIterator::info()))
+ return jsNontrivialString(exec, ASCIILiteral("iterator"));
+
if (value.inherits(JSInt8Array::info()) || value.inherits(JSInt16Array::info()) || value.inherits(JSInt32Array::info()))
return jsNontrivialString(exec, ASCIILiteral("array"));
if (value.inherits(JSUint8Array::info()) || value.inherits(JSUint16Array::info()) || value.inherits(JSUint32Array::info()))
return array;
}
+ if (JSArrayIterator* arrayIterator = jsDynamicCast<JSArrayIterator*>(value)) {
+ String kind;
+ switch (arrayIterator->kind(exec)) {
+ case ArrayIterateKey:
+ kind = ASCIILiteral("key");
+ break;
+ case ArrayIterateValue:
+ kind = ASCIILiteral("value");
+ break;
+ case ArrayIterateKeyValue:
+ kind = ASCIILiteral("key+value");
+ break;
+ }
+ unsigned index = 0;
+ JSArray* array = constructEmptyArray(exec, nullptr, 2);
+ array->putDirectIndex(exec, index++, constructInternalProperty(exec, "array", arrayIterator->iteratedValue(exec)));
+ array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind)));
+ return array;
+ }
+
+ if (JSMapIterator* mapIterator = jsDynamicCast<JSMapIterator*>(value)) {
+ String kind;
+ switch (mapIterator->kind()) {
+ case MapIterateKey:
+ kind = ASCIILiteral("key");
+ break;
+ case MapIterateValue:
+ kind = ASCIILiteral("value");
+ break;
+ case MapIterateKeyValue:
+ kind = ASCIILiteral("key+value");
+ break;
+ }
+ unsigned index = 0;
+ JSArray* array = constructEmptyArray(exec, nullptr, 2);
+ array->putDirectIndex(exec, index++, constructInternalProperty(exec, "map", mapIterator->iteratedValue()));
+ array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind)));
+ return array;
+ }
+
+ if (JSSetIterator* setIterator = jsDynamicCast<JSSetIterator*>(value)) {
+ String kind;
+ switch (setIterator->kind()) {
+ case SetIterateKey:
+ kind = ASCIILiteral("key");
+ break;
+ case SetIterateValue:
+ kind = ASCIILiteral("value");
+ break;
+ case SetIterateKeyValue:
+ kind = ASCIILiteral("key+value");
+ break;
+ }
+ unsigned index = 0;
+ JSArray* array = constructEmptyArray(exec, nullptr, 2);
+ array->putDirectIndex(exec, index++, constructInternalProperty(exec, "set", setIterator->iteratedValue()));
+ array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind)));
+ return array;
+ }
+
+ if (JSStringIterator* stringIterator = jsDynamicCast<JSStringIterator*>(value)) {
+ unsigned index = 0;
+ JSArray* array = constructEmptyArray(exec, nullptr, 1);
+ array->putDirectIndex(exec, index++, constructInternalProperty(exec, "string", stringIterator->iteratedValue(exec)));
+ return array;
+ }
+
+ if (JSArgumentsIterator* argumentsIterator = jsDynamicCast<JSArgumentsIterator*>(value)) {
+ unsigned index = 0;
+ JSArray* array = constructEmptyArray(exec, nullptr, 1);
+ array->putDirectIndex(exec, index++, constructInternalProperty(exec, "arguments", argumentsIterator->iteratedValue()));
+ return array;
+ }
+
return jsUndefined();
}
return array;
}
+JSValue JSInjectedScriptHost::iteratorEntries(ExecState* exec)
+{
+ if (exec->argumentCount() < 1)
+ return jsUndefined();
+
+ JSValue iterator;
+ JSValue value = exec->uncheckedArgument(0);
+ if (JSArrayIterator* arrayIterator = jsDynamicCast<JSArrayIterator*>(value))
+ iterator = arrayIterator->clone(exec);
+ else if (JSMapIterator* mapIterator = jsDynamicCast<JSMapIterator*>(value))
+ iterator = mapIterator->clone(exec);
+ else if (JSSetIterator* setIterator = jsDynamicCast<JSSetIterator*>(value))
+ iterator = setIterator->clone(exec);
+ else if (JSStringIterator* stringIterator = jsDynamicCast<JSStringIterator*>(value))
+ iterator = stringIterator->clone(exec);
+ else if (JSArgumentsIterator* argumentsIterator = jsDynamicCast<JSArgumentsIterator*>(value))
+ iterator = argumentsIterator->clone(exec);
+ else
+ return jsUndefined();
+
+ unsigned numberToFetch = 5;
+ JSValue numberToFetchArg = exec->argument(1);
+ double fetchDouble = numberToFetchArg.toInteger(exec);
+ if (fetchDouble >= 0)
+ numberToFetch = static_cast<unsigned>(fetchDouble);
+
+ JSArray* array = constructEmptyArray(exec, nullptr);
+
+ for (unsigned i = 0; i < numberToFetch; ++i) {
+ JSValue next = iteratorStep(exec, iterator);
+ if (exec->hadException())
+ break;
+ if (next.isFalse())
+ break;
+
+ JSValue nextValue = iteratorValue(exec, next);
+ if (exec->hadException())
+ break;
+
+ JSObject* entry = constructEmptyObject(exec);
+ entry->putDirect(exec->vm(), Identifier(exec, "value"), nextValue);
+ array->putDirectIndex(exec, i, entry);
+ }
+
+ iteratorClose(exec, iterator);
+
+ return array;
+}
+
JSValue toJS(ExecState* exec, JSGlobalObject* globalObject, InjectedScriptHost* impl)
{
if (!impl)
JSC::JSValue getInternalProperties(JSC::ExecState*);
JSC::JSValue weakMapSize(JSC::ExecState*);
JSC::JSValue weakMapEntries(JSC::ExecState*);
+ JSC::JSValue iteratorEntries(JSC::ExecState*);
protected:
static const unsigned StructureFlags = Base::StructureFlags;
static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionIsHTMLAllCollection(ExecState*);
static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionWeakMapSize(ExecState*);
static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionWeakMapEntries(ExecState*);
+static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionIteratorEntries(ExecState*);
static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeAttributeEvaluate(ExecState*);
JSC_NATIVE_FUNCTION("isHTMLAllCollection", jsInjectedScriptHostPrototypeFunctionIsHTMLAllCollection, DontEnum, 1);
JSC_NATIVE_FUNCTION("weakMapSize", jsInjectedScriptHostPrototypeFunctionWeakMapSize, DontEnum, 1);
JSC_NATIVE_FUNCTION("weakMapEntries", jsInjectedScriptHostPrototypeFunctionWeakMapEntries, DontEnum, 1);
+ JSC_NATIVE_FUNCTION("iteratorEntries", jsInjectedScriptHostPrototypeFunctionIteratorEntries, DontEnum, 1);
Identifier evaluateIdentifier(&vm, "evaluate");
GetterSetter* accessor = GetterSetter::create(vm, globalObject);
return JSValue::encode(castedThis->weakMapEntries(exec));
}
+EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionIteratorEntries(ExecState* exec)
+{
+ JSValue thisValue = exec->thisValue();
+ JSInjectedScriptHost* castedThis = jsDynamicCast<JSInjectedScriptHost*>(thisValue);
+ if (!castedThis)
+ return throwVMTypeError(exec);
+
+ ASSERT_GC_OBJECT_INHERITS(castedThis, JSInjectedScriptHost::info());
+ return JSValue::encode(castedThis->iteratorEntries(exec));
+}
+
EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionSubtype(ExecState* exec)
{
JSValue thisValue = exec->thisValue();
"description": "Mirror object referencing original JavaScript object.",
"properties": [
{ "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean", "symbol"], "description": "Object type." },
- { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "error", "map", "set", "weakmap"], "description": "Object subtype hint. Specified for <code>object</code> type values only." },
+ { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "error", "map", "set", "weakmap", "iterator"], "description": "Object subtype hint. Specified for <code>object</code> type values only." },
{ "name": "className", "type": "string", "optional": true, "description": "Object class (constructor) name. Specified for <code>object</code> type values only." },
{ "name": "value", "type": "any", "optional": true, "description": "Remote object value (in case of primitive values or JSON values if it was requested)." },
{ "name": "description", "type": "string", "optional": true, "description": "String representation of the object." },
"description": "Object containing abbreviated remote object value.",
"properties": [
{ "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean", "symbol"], "description": "Object type." },
- { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "error", "map", "set", "weakmap"], "description": "Object subtype hint. Specified for <code>object</code> type values only." },
+ { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "error", "map", "set", "weakmap", "iterator"], "description": "Object subtype hint. Specified for <code>object</code> type values only." },
{ "name": "description", "type": "string", "optional": true, "description": "String representation of the object." },
{ "name": "lossless", "type": "boolean", "description": "Determines whether preview is lossless (contains all information of the original object)." },
{ "name": "overflow", "type": "boolean", "optional": true, "description": "True iff some of the properties of the original did not fit." },
"properties": [
{ "name": "name", "type": "string", "description": "Property name." },
{ "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean", "symbol", "accessor"], "description": "Object type." },
- { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "error", "map", "set", "weakmap"], "description": "Object subtype hint. Specified for <code>object</code> type values only." },
+ { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "error", "map", "set", "weakmap", "iterator"], "description": "Object subtype hint. Specified for <code>object</code> type values only." },
{ "name": "value", "type": "string", "optional": true, "description": "User-friendly property value string." },
{ "name": "valuePreview", "$ref": "ObjectPreview", "optional": true, "description": "Nested value preview." },
{ "name": "internal", "type": "boolean", "optional": true, "description": "True if this is an internal property." }
m_arguments.set(vm, this, arguments);
}
+JSArgumentsIterator* JSArgumentsIterator::clone(ExecState* exec)
+{
+ auto clone = JSArgumentsIterator::create(exec->vm(), exec->callee()->globalObject()->argumentsIteratorStructure(), m_arguments.get());
+ clone->m_nextIndex = m_nextIndex;
+ return clone;
+}
+
}
return true;
}
+ JSValue iteratedValue() const { return m_arguments.get(); }
+ JSArgumentsIterator* clone(ExecState*);
+
private:
static const unsigned StructureFlags = Base::StructureFlags;
putDirect(vm, vm.propertyNames->arrayIterationKindPrivateName, jsNumber(kind));
}
+ArrayIterationKind JSArrayIterator::kind(ExecState* exec) const
+{
+ JSValue kindValue = getDirect(exec->vm(), exec->vm().propertyNames->arrayIterationKindPrivateName);
+ return static_cast<ArrayIterationKind>(kindValue.asInt32());
+}
+
+JSValue JSArrayIterator::iteratedValue(ExecState* exec) const
+{
+ return getDirect(exec->vm(), exec->vm().propertyNames->iteratedObjectPrivateName);
+}
+
+JSArrayIterator* JSArrayIterator::clone(ExecState* exec)
+{
+ VM& vm = exec->vm();
+ JSValue iteratedObject = getDirect(vm, vm.propertyNames->iteratedObjectPrivateName);
+ JSValue nextIndex = getDirect(vm, vm.propertyNames->arrayIteratorNextIndexPrivateName);
+
+ auto clone = JSArrayIterator::create(exec, exec->callee()->globalObject()->arrayIteratorStructure(), kind(exec), asObject(iteratedObject));
+ clone->putDirect(vm, vm.propertyNames->arrayIteratorNextIndexPrivateName, nextIndex);
+ return clone;
+}
+
}
return instance;
}
+ ArrayIterationKind kind(ExecState*) const;
+ JSValue iteratedValue(ExecState*) const;
+ JSArrayIterator* clone(ExecState*);
+
using JSNonFinalObject::arrayStorageOrNull;
private:
JSArrayIterator(VM& vm, Structure* structure)
void JSMapIterator::finishCreation(VM& vm, JSMap* iteratedObject)
{
Base::finishCreation(vm);
+ m_map.set(vm, this, iteratedObject);
m_iteratedObjectData.set(vm, this, iteratedObject->mapData());
}
return constructArray(callFrame, 0, globalObject, args);
}
+JSMapIterator* JSMapIterator::clone(ExecState* exec)
+{
+ auto clone = JSMapIterator::create(exec->vm(), exec->callee()->globalObject()->mapIteratorStructure(), m_map.get(), m_kind);
+ clone->m_iterator = m_iterator;
+ return clone;
+}
+
}
m_iterator.finish();
}
+ MapIterationKind kind() const { return m_kind; }
+ JSValue iteratedValue() const { return m_map.get(); }
+ JSMapIterator* clone(ExecState*);
+
private:
JSMapIterator(VM& vm, Structure* structure, JSMap* iteratedObject, MapIterationKind kind)
: Base(vm, structure)
JSValue createPair(CallFrame*, JSValue, JSValue);
static void visitChildren(JSCell*, SlotVisitor&);
+ WriteBarrier<JSMap> m_map;
WriteBarrier<MapData> m_iteratedObjectData;
MapData::const_iterator m_iterator;
MapIterationKind m_kind;
void JSSetIterator::finishCreation(VM& vm, JSSet* iteratedObject)
{
Base::finishCreation(vm);
+ m_set.set(vm, this, iteratedObject);
m_iteratedObjectData.set(vm, this, iteratedObject->mapData());
}
return constructArray(callFrame, 0, globalObject, args);
}
+JSSetIterator* JSSetIterator::clone(ExecState* exec)
+{
+ auto clone = JSSetIterator::create(exec->vm(), exec->callee()->globalObject()->setIteratorStructure(), m_set.get(), m_kind);
+ clone->m_iterator = m_iterator;
+ return clone;
+}
+
}
m_iterator.finish();
}
+ SetIterationKind kind() const { return m_kind; }
+ JSValue iteratedValue() const { return m_set.get(); }
+ JSSetIterator* clone(ExecState*);
+
private:
JSSetIterator(VM& vm, Structure* structure, JSSet* iteratedObject, SetIterationKind kind)
: Base(vm, structure)
JSValue createPair(CallFrame*, JSValue, JSValue);
static void visitChildren(JSCell*, SlotVisitor&);
+ WriteBarrier<JSSet> m_set;
WriteBarrier<MapData> m_iteratedObjectData;
MapData::const_iterator m_iterator;
SetIterationKind m_kind;
putDirect(vm, vm.propertyNames->stringIteratorNextIndexPrivateName, jsNumber(0));
}
+JSValue JSStringIterator::iteratedValue(ExecState* exec) const
+{
+ return getDirect(exec->vm(), exec->vm().propertyNames->iteratedStringPrivateName);
+}
+
+JSStringIterator* JSStringIterator::clone(ExecState* exec)
+{
+ VM& vm = exec->vm();
+ JSValue iteratedString = getDirect(vm, vm.propertyNames->iteratedStringPrivateName);
+ JSValue nextIndex = getDirect(vm, vm.propertyNames->stringIteratorNextIndexPrivateName);
+
+ auto clone = JSStringIterator::create(exec, exec->callee()->globalObject()->stringIteratorStructure(), asString(iteratedString));
+ clone->putDirect(vm, vm.propertyNames->stringIteratorNextIndexPrivateName, nextIndex);
+ return clone;
+}
+
} // namespace JSC
return instance;
}
+ JSValue iteratedValue(ExecState*) const;
+ JSStringIterator* clone(ExecState*);
+
private:
JSStringIterator(VM& vm, Structure* structure)
: Base(vm, structure)
2015-03-06 Joseph Pecoraro <pecoraro@apple.com>
+ Web Inspector: ES6: Improved Support for Iterator Objects
+ https://bugs.webkit.org/show_bug.cgi?id=142420
+
+ Reviewed by Timothy Hatcher.
+
+ * UserInterface/Views/ConsoleMessageImpl.js:
+ (WebInspector.ConsoleMessageImpl):
+ Treat an iterator like an object.
+
+ * UserInterface/Views/ObjectPreviewView.js:
+ Output iterator previews with []s, not {}s.
+
+2015-03-06 Joseph Pecoraro <pecoraro@apple.com>
+
Web Inspector: Adopt Object Literal Method Property Syntax
https://bugs.webkit.org/show_bug.cgi?id=142409
"map": this._formatParameterAsObject,
"set": this._formatParameterAsObject,
"weakmap": this._formatParameterAsObject,
+ "iterator": this._formatParameterAsObject,
"array": this._formatParameterAsArray,
"node": this._formatParameterAsNode,
"string": this._formatParameterAsString
{
var lossless = preview.lossless && !preview.propertyPreviews.length;
- element.appendChild(document.createTextNode("{"));
+ var isIterator = preview.subtype === "iterator";
+
+ element.appendChild(document.createTextNode(isIterator ? "[" : "{"));
var limit = Math.min(preview.collectionEntryPreviews.length, this._numberOfPropertiesToShowInMode());
for (var i = 0; i < limit; ++i) {
if (preview.overflow)
element.appendChild(document.createTextNode(", \u2026"));
- element.appendChild(document.createTextNode("}"));
+ element.appendChild(document.createTextNode(isIterator ? "]" : "}"));
return lossless;
},