Bug 699565 - Part 4 - for-of loops on array-like DOM object. r=bz.

This commit is contained in:
Jason Orendorff 2012-02-07 12:57:17 -06:00
parent 84ac816f69
commit 2ee2e8f0d9
8 changed files with 91 additions and 0 deletions

View File

@ -64,6 +64,7 @@ _BROWSER_TEST_FILES = \
browser_webconsole_consoleonpage.js \
browser_webconsole_chrome.js \
browser_webconsole_execution_scope.js \
browser_webconsole_for_of.js \
browser_webconsole_history.js \
browser_webconsole_hud_getters.js \
browser_webconsole_js_input_and_output_styling.js \
@ -226,6 +227,7 @@ _BROWSER_TEST_PAGES = \
browser_gcli_inspect.html \
test-bug-658368-time-methods.html \
test-webconsole-error-observer.html \
test-for-of.html \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

View File

@ -0,0 +1,33 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// A for-of loop in Web Console code can loop over a content NodeList.
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-for-of.html";
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.gcli.enable");
});
function test() {
Services.prefs.setBoolPref("devtools.gcli.enable", false);
addTab(TEST_URI);
browser.addEventListener("DOMContentLoaded", testForOf, false);
}
function testForOf() {
browser.removeEventListener("DOMContentLoaded", testForOf, false);
openConsole();
var hud = HUDService.getHudByWindow(content);
var jsterm = hud.jsterm;
jsterm.execute("{ [x.tagName for (x of document.body.childNodes) if (x.nodeType === 1)].join(' '); }");
let node = hud.outputNode.querySelector(".webconsole-msg-output");
ok(/H1 DIV H2 P/.test(node.textContent),
"for-of loop should find all top-level nodes");
jsterm.clearOutput();
jsterm.history.splice(0, jsterm.history.length); // workaround for bug 592552
finishTest();
}

View File

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html>
<body>
<h1>a</h1>
<div><p>b</p></div>
<h2>c</h2>
<p>d</p>

View File

@ -79,6 +79,7 @@ _TEST_FILES = \
test_browserFrame4.html \
test_browserFrame5.html \
test_browserFrame6.html \
test_for_of.html \
$(NULL)
_CHROME_FILES = \

View File

@ -0,0 +1,25 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Tests for for-of loops</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
</head>
<body onload="doTest()">
<p id="display"></p>
<div id="content" style="display: none"></div>
<script>
function doTest() {
// DOM NodeLists are iterable.
var a = [];
for (var e of document.body.childNodes)
if (e.nodeType === 1)
a.push(e.tagName);
is("P DIV SCRIPT", a.join(" "), "for-of should see each element in the body");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
</script>
</body>
</html>

View File

@ -4410,6 +4410,15 @@ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
return JS_TRUE;
}
JS_PUBLIC_API(JSObject *)
JS_NewElementIterator(JSContext *cx, JSObject *obj)
{
AssertNoGC(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
return ElementIteratorObject::create(cx, obj);
}
JS_PUBLIC_API(JSBool)
JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
{

View File

@ -4047,6 +4047,13 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj);
extern JS_PUBLIC_API(JSBool)
JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp);
/*
* Create an object to iterate over the elements of obj in for-of order. This
* can be used to implement the iteratorObject hook for an array-like Class.
*/
extern JS_PUBLIC_API(JSObject *)
JS_NewElementIterator(JSContext *cx, JSObject *obj);
extern JS_PUBLIC_API(JSBool)
JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
jsval *vp, uintN *attrsp);

View File

@ -1249,6 +1249,13 @@ template<class LC>
bool
ListBase<LC>::iterate(JSContext *cx, JSObject *proxy, uintN flags, Value *vp)
{
if (flags == JSITER_FOR_OF) {
JSObject *iterobj = JS_NewElementIterator(cx, proxy);
if (!iterobj)
return false;
vp->setObject(*iterobj);
return true;
}
return ProxyHandler::iterate(cx, proxy, flags, vp);
}