Merge mozilla-central into mozilla-inbound

This commit is contained in:
Ehsan Akhgari 2012-07-04 22:16:59 -04:00
commit 6e5624f985
176 changed files with 1873 additions and 3694 deletions

View File

@ -38,10 +38,13 @@ let gDrag = {
// Mark nodes as being dragged.
let selector = ".newtab-site, .newtab-control, .newtab-thumbnail";
let nodes = aSite.node.parentNode.querySelectorAll(selector);
let parentCell = aSite.node.parentNode;
let nodes = parentCell.querySelectorAll(selector);
for (let i = 0; i < nodes.length; i++)
nodes[i].setAttribute("dragged", "true");
parentCell.setAttribute("dragged", "true");
this._setDragData(aSite, aEvent);
// Store the cursor offset.
@ -88,7 +91,7 @@ let gDrag = {
* @param aEvent The 'dragend' event.
*/
end: function Drag_end(aSite, aEvent) {
let nodes = aSite.node.parentNode.querySelectorAll("[dragged]");
let nodes = gGrid.node.querySelectorAll("[dragged]")
for (let i = 0; i < nodes.length; i++)
nodes[i].removeAttribute("dragged");

View File

@ -153,6 +153,7 @@ _BROWSER_FILES = \
browser_bug743421.js \
browser_bug749738.js \
browser_bug763468.js \
browser_bug767836.js \
browser_canonizeURL.js \
browser_customize.js \
browser_findbarClose.js \

View File

@ -0,0 +1,93 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
// initialization
const pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
const PREF = "browser.newtab.url";
const NEWTABURL = Services.prefs.getCharPref(PREF) || "about:blank";
const TESTURL = "http://example.com/";
function test() {
waitForExplicitFinish();
// check whether the mode that we start off with is normal or not
ok(!pb.privateBrowsingEnabled, "private browsing is disabled");
// check whether any custom new tab url has been configured
ok(!Services.prefs.prefHasUserValue(PREF), "No custom newtab url is set");
openNewTab(function () {
// Check the new tab opened while in normal mode
is(gBrowser.selectedBrowser.currentURI.spec, NEWTABURL,
"URL of NewTab should be browser.newtab.url in Normal mode");
// Set the custom newtab url
Services.prefs.setCharPref(PREF, TESTURL);
ok(Services.prefs.prefHasUserValue(PREF), "Custom newtab url is set");
// Open a newtab after setting the custom newtab url
openNewTab(function () {
is(gBrowser.selectedBrowser.currentURI.spec, TESTURL,
"URL of NewTab should be the custom url");
// clear the custom url preference
Services.prefs.clearUserPref(PREF);
ok(!Services.prefs.prefHasUserValue(PREF), "No custom newtab url is set");
// enter private browsing mode
togglePrivateBrowsing(function () {
ok(pb.privateBrowsingEnabled, "private browsing is enabled");
// Open a new tab page in private browsing mode
openNewTab(function () {
// Check the new tab opened while in private browsing mode
is(gBrowser.selectedBrowser.currentURI.spec, "about:privatebrowsing",
"URL of NewTab should be about:privatebrowsing in PB mode");
Services.prefs.setCharPref(PREF, TESTURL);
ok(Services.prefs.prefHasUserValue(PREF), "Custom newtab url is set");
// Open a newtab after setting the custom newtab url
openNewTab(function () {
is(gBrowser.selectedBrowser.currentURI.spec, TESTURL,
"URL of NewTab should be the custom url");
Services.prefs.clearUserPref(PREF);
ok(!Services.prefs.prefHasUserValue(PREF), "No custom newtab url is set");
// exit private browsing mode
togglePrivateBrowsing(function () {
ok(!pb.privateBrowsingEnabled, "private browsing is disabled");
gBrowser.removeTab(gBrowser.selectedTab);
gBrowser.removeTab(gBrowser.selectedTab);
finish();
});
});
});
});
});
});
}
function togglePrivateBrowsing(aCallback) {
let topic = "private-browsing-transition-complete";
Services.obs.addObserver(function observe() {
Services.obs.removeObserver(observe, topic);
executeSoon(aCallback);
}, topic, false);
pb.privateBrowsingEnabled = !pb.privateBrowsingEnabled;
}
function openNewTab(aCallback) {
// Open a new tab
BrowserOpenTab();
let browser = gBrowser.selectedBrowser;
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
executeSoon(aCallback);
}, true);
}

View File

@ -16,6 +16,7 @@ _BROWSER_FILES = \
browser_newtab_disable.js \
browser_newtab_drag_drop.js \
browser_newtab_drop_preview.js \
browser_newtab_focus.js \
browser_newtab_private_browsing.js \
browser_newtab_reset.js \
browser_newtab_tabsync.js \

View File

@ -0,0 +1,54 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/*
* These tests make sure that focusing the 'New Tage Page' works as expected.
*/
function runTests() {
// Focus count in new tab page.
// 28 = 9 * 3 + 1 = 9 sites and 1 toggle button, each site has a link, a pin
// and a remove button.
let FOCUS_COUNT = 28;
if ("nsILocalFileMac" in Ci) {
// 19 = Mac doesn't focus links, so 9 focus targets less than Windows/Linux.
FOCUS_COUNT = 19;
}
// Create a new tab page.
setLinks("0,1,2,3,4,5,6,7,8");
setPinnedLinks("");
yield addNewTabPageTab();
gURLBar.focus();
// Count the focus with the enabled page.
yield countFocus(FOCUS_COUNT);
// Disable page and count the focus with the disabled page.
NewTabUtils.allPages.enabled = false;
yield countFocus(1);
}
/**
* Focus the urlbar and count how many focus stops to return again to the urlbar.
*/
function countFocus(aExpectedCount) {
let focusCount = 0;
let contentDoc = getContentDocument();
window.addEventListener("focus", function onFocus() {
let focusedElement = document.commandDispatcher.focusedElement;
if (focusedElement && focusedElement.classList.contains("urlbar-input")) {
window.removeEventListener("focus", onFocus, true);
is(focusCount, aExpectedCount, "Validate focus count in the new tab page.");
executeSoon(TestRunner.next);
} else {
if (focusedElement && focusedElement.ownerDocument == contentDoc &&
focusedElement instanceof HTMLElement) {
focusCount++;
}
document.commandDispatcher.advanceFocus();
}
}, true);
document.commandDispatcher.advanceFocus();
}

View File

@ -1,4 +1,4 @@
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
# -*- Mode: javascript; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
@ -12,7 +12,8 @@ XPCOMUtils.defineLazyGetter(this, "BROWSER_NEW_TAB_URL", function () {
const TOPIC = "private-browsing-transition-complete";
function getNewTabPageURL() {
if (("gPrivateBrowsingUI" in window)) {
if (("gPrivateBrowsingUI" in window) &&
!Services.prefs.prefHasUserValue(PREF)) {
// gPrivateBrowsingUI may not be initialized yet, in that case we'll
// update BROWSER_NEW_TAB_URL when it gets initialized.
if (!gPrivateBrowsingUI.initialized)

View File

@ -2823,6 +2823,108 @@ let SessionStoreInternal = {
this._sendRestoreCompletedNotifications();
},
/**
* Sets the tabs restoring order with the following priority:
* Selected tab, pinned tabs, visible tabs, unhidden tabs and hidden tabs.
* @param aTabBrowser
* Tab browser object
* @param aTabs
* Array of tab references
* @param aTabData
* Array of tab data
* @param aSelectedTab
* Index of selected tab
*/
_setTabsRestoringOrder : function ssi__setTabsRestoringOrder(
aTabBrowser, aTabs, aTabData, aSelectedTab) {
// Temporally store the pinned tabs before moving the hidden tabs and
// optimizing the visible tabs. In case the selected tab is a pinned tab,
// the index is also stored.
let pinnedTabs = aTabData.filter(function (aData) aData.pinned).length;
let pinnedTabsArray = [];
let pinnedTabsDataArray = [];
let pinnedSelectedTab = null;
if (pinnedTabs && aTabs.length > 1) {
for (let t = aTabs.length - 1; t >= 0; t--) {
if (aTabData[t].pinned) {
pinnedTabsArray.unshift(aTabs.splice(t, 1)[0]);
pinnedTabsDataArray.unshift(aTabData.splice(t, 1)[0]);
if (aSelectedTab) {
if (aSelectedTab > (t + 1))
--aSelectedTab;
else if (aSelectedTab == (t + 1)) {
aSelectedTab = null;
pinnedSelectedTab = 1;
}
} else if (pinnedSelectedTab)
++pinnedSelectedTab;
}
}
}
// Without the pinned tabs, we move the hidden tabs to the end of the list
// and optimize the visible tabs.
let unhiddenTabs = aTabData.filter(function (aData) !aData.hidden).length;
if (unhiddenTabs && aTabs.length > 1) {
// Load hidden tabs last, by pushing them to the end of the list.
for (let t = 0, tabsToReorder = aTabs.length - unhiddenTabs; tabsToReorder > 0; ) {
if (aTabData[t].hidden) {
aTabs = aTabs.concat(aTabs.splice(t, 1));
aTabData = aTabData.concat(aTabData.splice(t, 1));
if (aSelectedTab && aSelectedTab > t)
--aSelectedTab;
--tabsToReorder;
continue;
}
++t;
}
// Determine if we can optimize & load visible tabs first
let maxVisibleTabs = Math.ceil(aTabBrowser.tabContainer.mTabstrip.scrollClientSize /
aTabs[unhiddenTabs - 1].getBoundingClientRect().width);
// Make sure we restore visible tabs first, if there are enough
if (aSelectedTab && maxVisibleTabs < unhiddenTabs && aSelectedTab > 1) {
let firstVisibleTab = 0;
if (unhiddenTabs - maxVisibleTabs > aSelectedTab) {
// aSelectedTab is leftmost since we scroll to it when possible
firstVisibleTab = aSelectedTab - 1;
} else {
// aSelectedTab is rightmost or no more room to scroll right
firstVisibleTab = unhiddenTabs - maxVisibleTabs;
}
aTabs = aTabs.splice(firstVisibleTab, maxVisibleTabs).concat(aTabs);
aTabData = aTabData.splice(firstVisibleTab, maxVisibleTabs).concat(aTabData);
aSelectedTab -= firstVisibleTab;
}
}
// Load the pinned tabs at the beginning of the list and restore the
// selected tab index.
if (pinnedTabsArray) {
// Restore the selected tab index.
if (pinnedSelectedTab) {
aSelectedTab = pinnedSelectedTab;
} else {
aSelectedTab += pinnedTabsArray.length;
}
// Load the pinned tabs at the beginning of the list.
for (let t = pinnedTabsArray.length - 1; t >= 0; t--) {
aTabs.unshift(pinnedTabsArray.splice(t, 1)[0]);
aTabData.unshift(pinnedTabsDataArray.splice(t, 1)[0]);
}
}
// Load the selected tab to the first position.
if (aSelectedTab-- && aTabs[aSelectedTab]) {
aTabs.unshift(aTabs.splice(aSelectedTab, 1)[0]);
aTabData.unshift(aTabData.splice(aSelectedTab, 1)[0]);
aTabBrowser.selectedTab = aTabs[0];
}
return [aTabs, aTabData];
},
/**
* Manage history restoration for a window
* @param aWindow
@ -2875,48 +2977,9 @@ let SessionStoreInternal = {
return;
}
let unhiddenTabs = aTabData.filter(function (aData) !aData.hidden).length;
if (unhiddenTabs && aTabs.length > 1) {
// Load hidden tabs last, by pushing them to the end of the list
for (let t = 0, tabsToReorder = aTabs.length - unhiddenTabs; tabsToReorder > 0; ) {
if (aTabData[t].hidden) {
aTabs = aTabs.concat(aTabs.splice(t, 1));
aTabData = aTabData.concat(aTabData.splice(t, 1));
if (aSelectTab > t)
--aSelectTab;
--tabsToReorder;
continue;
}
++t;
}
// Determine if we can optimize & load visible tabs first
let maxVisibleTabs = Math.ceil(tabbrowser.tabContainer.mTabstrip.scrollClientSize /
aTabs[unhiddenTabs - 1].getBoundingClientRect().width);
// make sure we restore visible tabs first, if there are enough
if (maxVisibleTabs < unhiddenTabs && aSelectTab > 1) {
let firstVisibleTab = 0;
if (unhiddenTabs - maxVisibleTabs > aSelectTab) {
// aSelectTab is leftmost since we scroll to it when possible
firstVisibleTab = aSelectTab - 1;
} else {
// aSelectTab is rightmost or no more room to scroll right
firstVisibleTab = unhiddenTabs - maxVisibleTabs;
}
aTabs = aTabs.splice(firstVisibleTab, maxVisibleTabs).concat(aTabs);
aTabData = aTabData.splice(firstVisibleTab, maxVisibleTabs).concat(aTabData);
aSelectTab -= firstVisibleTab;
}
}
// make sure to restore the selected tab first (if any)
if (aSelectTab-- && aTabs[aSelectTab]) {
aTabs.unshift(aTabs.splice(aSelectTab, 1)[0]);
aTabData.unshift(aTabData.splice(aSelectTab, 1)[0]);
tabbrowser.selectedTab = aTabs[0];
}
// Sets the tabs restoring order.
[aTabs, aTabData] =
this._setTabsRestoringOrder(tabbrowser, aTabs, aTabData, aSelectTab);
// Prepare the tabs so that they can be properly restored. We'll pin/unpin
// and show/hide tabs as necessary. We'll also set the labels, user typed

View File

@ -8,15 +8,23 @@ function test() {
requestLongerTimeout(3);
// builds the tests state based on a few parameters
function buildTestState(num, selected, hidden) {
let state = { windows: [ { "tabs": [], "selected": selected } ] };
function buildTestState(num, selected, hidden, pinned) {
let state = { windows: [ { "tabs": [], "selected": selected + 1 } ] };
while (num--) {
state.windows[0].tabs.push({entries: [{url: "http://example.com/"}]});
state.windows[0].tabs.push({
entries: [
{ url: "http://example.com/?t=" + state.windows[0].tabs.length }
]
});
let i = state.windows[0].tabs.length - 1;
if (hidden.length > 0 && i == hidden[0]) {
state.windows[0].tabs[i].hidden = true;
hidden.splice(0, 1);
}
if (pinned.length > 0 && i == pinned[0]) {
state.windows[0].tabs[i].pinned = true;
pinned.splice(0, 1);
}
}
return state;
}
@ -24,56 +32,128 @@ function test() {
let tests = [
{ testNum: 1,
totalTabs: 13,
selectedTab: 1,
selectedTab: 0,
shownTabs: 6,
hiddenTabs: [],
pinnedTabs: [],
order: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
},
{ testNum: 2,
totalTabs: 13,
selectedTab: 13,
selectedTab: 12,
shownTabs: 6,
hiddenTabs: [],
pinnedTabs: [],
order: [12, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6]
},
{ testNum: 3,
totalTabs: 13,
selectedTab: 4,
selectedTab: 3,
shownTabs: 6,
hiddenTabs: [],
pinnedTabs: [],
order: [3, 4, 5, 6, 7, 8, 0, 1, 2, 9, 10, 11, 12]
},
{ testNum: 4,
totalTabs: 13,
selectedTab: 11,
selectedTab: 10,
shownTabs: 6,
hiddenTabs: [],
pinnedTabs: [],
order: [10, 7, 8, 9, 11, 12, 0, 1, 2, 3, 4, 5, 6]
},
{ testNum: 5,
totalTabs: 13,
selectedTab: 13,
selectedTab: 12,
shownTabs: 6,
hiddenTabs: [0, 4, 9],
pinnedTabs: [],
order: [12, 6, 7, 8, 10, 11, 1, 2, 3, 5, 0, 4, 9]
},
{ testNum: 6,
totalTabs: 13,
selectedTab: 4,
selectedTab: 3,
shownTabs: 6,
hiddenTabs: [1, 7, 12],
pinnedTabs: [],
order: [3, 4, 5, 6, 8, 9, 0, 2, 10, 11, 1, 7, 12]
},
{ testNum: 7,
totalTabs: 13,
selectedTab: 4,
selectedTab: 3,
shownTabs: 6,
hiddenTabs: [0, 1, 2],
pinnedTabs: [],
order: [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2]
},
{ testNum: 8,
totalTabs: 13,
selectedTab: 0,
shownTabs: 6,
hiddenTabs: [],
pinnedTabs: [0],
order: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
},
{ testNum: 9,
totalTabs: 13,
selectedTab: 1,
shownTabs: 6,
hiddenTabs: [],
pinnedTabs: [0],
order: [1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
},
{ testNum: 10,
totalTabs: 13,
selectedTab: 3,
shownTabs: 6,
hiddenTabs: [2],
pinnedTabs: [0,1],
order: [3, 0, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 2]
},
{ testNum: 11,
totalTabs: 13,
selectedTab: 12,
shownTabs: 6,
hiddenTabs: [],
pinnedTabs: [0,1,2],
order: [12, 0, 1, 2, 7, 8, 9, 10, 11, 3, 4, 5, 6]
},
{ testNum: 12,
totalTabs: 13,
selectedTab: 6,
shownTabs: 6,
hiddenTabs: [3,4,5],
pinnedTabs: [0,1,2],
order: [6, 0, 1, 2, 7, 8, 9, 10, 11, 12, 3, 4, 5]
},
{ testNum: 13,
totalTabs: 13,
selectedTab: 1,
shownTabs: 6,
hiddenTabs: [3,4,5],
pinnedTabs: [0,1,2],
order: [1, 0, 2, 6, 7, 8, 9, 10, 11, 12, 3, 4, 5]
},
{ testNum: 14,
totalTabs: 13,
selectedTab: 2,
shownTabs: 6,
hiddenTabs: [],
pinnedTabs: [0,1,2],
order: [2, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
},
{ testNum: 15,
totalTabs: 13,
selectedTab: 3,
shownTabs: 6,
hiddenTabs: [1,4],
pinnedTabs: [0,1,2],
order: [3, 0, 1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 4]
}
];
let tabMinWidth = parseInt(getComputedStyle(gBrowser.selectedTab, null).minWidth);
let tabMinWidth =
parseInt(getComputedStyle(gBrowser.selectedTab, null).minWidth);
let testIndex = 0;
function runNextTest() {
@ -84,41 +164,46 @@ function test() {
info ("Starting test " + (++testIndex));
let test = tests.shift();
let state = buildTestState(test.totalTabs, test.selectedTab, test.hiddenTabs);
let state = buildTestState(test.totalTabs, test.selectedTab,
test.hiddenTabs, test.pinnedTabs);
let tabbarWidth = Math.floor((test.shownTabs - 0.5) * tabMinWidth);
let win = openDialog(location, "_blank", "chrome,all,dialog=no");
let actualOrder = [];
let tabsRestored = [];
win.addEventListener("SSTabRestoring", function onSSTabRestoring(aEvent) {
let tab = aEvent.originalTarget;
let currentIndex = Array.indexOf(win.gBrowser.tabs, tab);
actualOrder.push(currentIndex);
let tabLink = tab.linkedBrowser.currentURI.spec;
let tabIndex =
tabLink.substring(tabLink.indexOf("?t=") + 3, tabLink.length);
if (actualOrder.length < state.windows[0].tabs.length)
// we need to compare with the tab's restoring index, no with the
// position index, since the pinned tabs change the positions in the
// tabbar.
tabsRestored.push(tabIndex);
if (tabsRestored.length < state.windows[0].tabs.length)
return;
// all of the tabs should be restoring or restored by now
is(actualOrder.length, state.windows[0].tabs.length,
is(tabsRestored.length, state.windows[0].tabs.length,
"Test #" + testIndex + ": Number of restored tabs is as expected");
is(actualOrder.join(" "), test.order.join(" "),
is(tabsRestored.join(" "), test.order.join(" "),
"Test #" + testIndex + ": 'visible' tabs restored first");
// Cleanup.
// cleanup
win.removeEventListener("SSTabRestoring", onSSTabRestoring, false);
win.close();
executeSoon(runNextTest);
}, false);
win.addEventListener("load", function onLoad(aEvent) {
win.removeEventListener("load", onLoad, false);
executeSoon(function () {
let extent = win.outerWidth - win.gBrowser.tabContainer.mTabstrip.scrollClientSize;
let windowWidth = tabbarWidth + extent;
win.resizeTo(windowWidth, win.outerHeight);
ss.setWindowState(win, JSON.stringify(state), true);
});
}, false);
whenWindowLoaded(win, function(aEvent) {
let extent =
win.outerWidth - win.gBrowser.tabContainer.mTabstrip.scrollClientSize;
let windowWidth = tabbarWidth + extent;
win.resizeTo(windowWidth, win.outerHeight);
ss.setWindowState(win, JSON.stringify(state), true);
});
};
runNextTest();

View File

@ -56,7 +56,7 @@
-moz-margin-end: 0;
}
.newtab-cell:hover:not(:empty) {
.newtab-cell:hover:not(:empty):not([dragged]) {
border-color: rgba(8,22,37,.25) rgba(8,22,37,.27) rgba(8,22,37,.3);
}

View File

@ -56,7 +56,7 @@
-moz-margin-end: 0;
}
.newtab-cell:hover:not(:empty) {
.newtab-cell:hover:not(:empty):not([dragged]) {
border-color: rgba(8,22,37,.25) rgba(8,22,37,.27) rgba(8,22,37,.3);
}

View File

@ -56,7 +56,7 @@
-moz-margin-end: 0;
}
.newtab-cell:hover:not(:empty) {
.newtab-cell:hover:not(:empty):not([dragged]) {
border-color: rgba(8,22,37,.25) rgba(8,22,37,.27) rgba(8,22,37,.3);
}

View File

@ -331,9 +331,9 @@ FieldSetter(JSContext *cx, unsigned argc, JS::Value *vp)
static JSBool
XBLResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
JSObject **objp)
JSMutableHandleObject objp)
{
*objp = NULL;
objp.set(NULL);
if (!JSID_IS_STRING(id)) {
return true;
@ -379,15 +379,13 @@ XBLResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
JS::StringValue(JSID_TO_STRING(id)));
if (!::JS_DefinePropertyById(cx, obj, id, JS::UndefinedValue(),
JS_DATA_TO_FUNC_PTR(JSPropertyOp,
get.reference()),
JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp,
set.reference()),
JS_DATA_TO_FUNC_PTR(JSPropertyOp, get.get()),
JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, set.get()),
field->AccessorAttributes())) {
return false;
}
*objp = obj;
objp.set(obj);
return true;
}

View File

@ -5376,7 +5376,7 @@ GetDocument(JSObject *obj)
JSBool
nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
JSHandleId id, unsigned flags,
JSObject **objp)
JSMutableHandleObject objp)
{
if (flags & (JSRESOLVE_ASSIGNING | JSRESOLVE_QUALIFIED) ||
!JSID_IS_STRING(id)) {
@ -5430,7 +5430,7 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
return JS_FALSE;
}
*objp = obj;
objp.set(obj);
}
return JS_TRUE;
@ -7323,9 +7323,11 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// Resolve special classes.
for (PRUint32 i = 0; i < ArrayLength(sOtherResolveFuncs); i++) {
if (!sOtherResolveFuncs[i](cx, obj, id, flags, objp)) {
JS::RootedObject tmp(cx, *objp);
if (!sOtherResolveFuncs[i](cx, obj, id, flags, &tmp)) {
return NS_ERROR_FAILURE;
}
*objp = tmp;
if (*objp) {
return NS_OK;
}
@ -8965,7 +8967,7 @@ nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JSHandleObject obj_,
JSBool
nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id,
unsigned flags, JSObject **objp)
unsigned flags, JSMutableHandleObject objp)
{
if (flags & JSRESOLVE_ASSIGNING) {
// Nothing to do here if we're assigning
@ -8980,7 +8982,7 @@ nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JSHandleObject obj, JSHan
JSFunction *fnc = ::JS_DefineFunctionById(cx, obj, id, CallToGetPropMapper,
0, JSPROP_ENUMERATE);
*objp = obj;
objp.set(obj);
return fnc != nsnull;
}
@ -9017,7 +9019,7 @@ nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JSHandleObject obj, JSHan
if (v != JSVAL_VOID) {
ok = ::JS_DefinePropertyById(cx, obj, id, v, nsnull, nsnull, 0);
*objp = obj;
objp.set(obj);
}
return ok;
@ -9164,7 +9166,7 @@ nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj
JSBool
nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
JSHandleId id, unsigned flags,
JSObject **objp)
JSMutableHandleObject objp)
{
if (nsDOMClassInfo::sAll_id == id) {
// document.all is resolved for the first time. Define it.
@ -9176,7 +9178,7 @@ nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
return JS_FALSE;
}
*objp = helper;
objp.set(helper);
}
}
@ -9187,7 +9189,7 @@ nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
JSBool
nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSHandleObject obj,
JSHandleId id, unsigned flags,
JSObject **objp)
JSMutableHandleObject objp)
{
if (JSID_IS_STRING(id)) {
nsDocument *doc = GetDocument(obj);
@ -9225,7 +9227,7 @@ nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSHandleObject obj,
return JS_FALSE;
}
*objp = obj;
objp.set(obj);
}
}

View File

@ -384,7 +384,7 @@ public:
static JSBool GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
JSHandleId id, unsigned flags,
JSObject **objp);
JSMutableHandleObject objp);
static JSBool GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj,
JSHandleId id, jsval *vp);
static JSBool SecurityCheckOnAddDelProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
@ -778,17 +778,17 @@ public:
static JSBool DocumentAllGetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
jsval *vp);
static JSBool DocumentAllNewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id,
unsigned flags, JSObject **objp);
unsigned flags, JSMutableHandleObject objp);
static void ReleaseDocument(JSFreeOp *fop, JSObject *obj);
static JSBool CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp);
static JSBool DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj,
JSHandleId id, jsval *vp);
static JSBool DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
JSHandleId id, unsigned flags,
JSObject **objp);
JSMutableHandleObject objp);
static JSBool DocumentAllTagsNewResolve(JSContext *cx, JSHandleObject obj,
JSHandleId id, unsigned flags,
JSObject **objp);
JSMutableHandleObject objp);
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, PRUint32 flags,

View File

@ -63,8 +63,6 @@ _TEST_FILES = \
test_lookupGetter.html \
test_InstanceOf.html \
test_traceProtos.html \
test_forOf.html \
forOf_iframe.html \
$(NULL)

View File

@ -1,13 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>iframe content for test_forOf_iframe.html</title>
</head>
<body>
<div id="basket">
<span id="egg0"></span>
<span id="egg1"><span id="duckling1"></span></span>
<span id="egg2"></span>
</div>
</body>
</html>

View File

@ -1,94 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=725907
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 725907</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=725907">Mozilla Bug 725907</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<div id="basket">
<span id="egg0"></span>
<span id="egg1"><span id="duckling1"></span></span>
<span id="egg2"></span>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 725907 **/
function runTestsForDocument(document, msgSuffix) {
function is(a, b, msg) { SimpleTest.is(a, b, msg + msgSuffix); }
function isnot(a, b, msg) { SimpleTest.isnot(a, b, msg + msgSuffix); }
var basket = document.getElementById("basket");
var egg3 = document.createElement("span");
egg3.id = "egg3";
var log = '';
for (var x of basket.childNodes) {
if (x.nodeType != x.TEXT_NODE)
log += x.id + ";";
}
is(log, "egg0;egg1;egg2;", "'for (x of div.childNodes)' should iterate over child nodes");
log = '';
for (var x of basket.childNodes) {
if (x.nodeType != x.TEXT_NODE) {
log += x.id + ";";
if (x.id == "egg1")
basket.appendChild(egg3);
}
}
is(log, "egg0;egg1;egg2;egg3;", "'for (x of div.childNodes)' should see elements added during iteration");
var iter1 = basket.childNodes.iterator();
var iter2 = basket.childNodes.iterator();
isnot(iter1, iter2, "nodelist.iterator() returns a new iterator each time");
log = '';
basket.appendChild(document.createTextNode("some text"));
for (var x of basket.children)
log += x.id + ";";
is(log, "egg0;egg1;egg2;egg3;", "'for (x of div.children)' should iterate over child elements");
var iter1 = basket.children.iterator();
var iter2 = basket.children.iterator();
isnot(iter1, iter2, ".iterator() returns a new iterator each time");
var count = 0;
for (var x of document.getElementsByClassName("hazardous-materials"))
count++;
is(count, 0, "'for (x of emptyNodeList)' loop should run zero times");
var log = '';
for (var x of document.querySelectorAll("span"))
log += x.id + ";";
is(log, "egg0;egg1;duckling1;egg2;egg3;", "for-of loop should work with a querySelectorAll() NodeList");
}
/* All the tests run twice. First, in this document, so without any wrappers. */
runTestsForDocument(document, "");
/* And once using the document of an iframe, so working with cross-compartment wrappers. */
SimpleTest.waitForExplicitFinish();
function iframeLoaded(iframe) {
runTestsForDocument(iframe.contentWindow.document, " (in iframe)");
SimpleTest.finish();
}
</script>
<iframe src="forOf_iframe.html" onload="iframeLoaded(this)"></iframe>
</pre>
</body>
</html>

View File

@ -127,7 +127,7 @@ NPObjWrapper_newEnumerate(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op
static JSBool
NPObjWrapper_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
JSObject **objp);
JSMutableHandleObject objp);
static JSBool
NPObjWrapper_Convert(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp);
@ -1596,7 +1596,7 @@ NPObjWrapper_newEnumerate(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op
static JSBool
NPObjWrapper_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
JSObject **objp)
JSMutableHandleObject objp)
{
NPObject *npobj = GetNPObject(obj);
@ -1623,7 +1623,7 @@ NPObjWrapper_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsign
return JS_FALSE;
}
*objp = obj;
objp.set(obj);
return JS_TRUE;
}
@ -1639,7 +1639,7 @@ NPObjWrapper_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsign
JSFunction *fnc = ::JS_DefineFunctionById(cx, obj, id, CallNPMethod, 0,
JSPROP_ENUMERATE);
*objp = obj;
objp.set(obj);
return fnc != nsnull;
}

View File

@ -368,13 +368,13 @@ BEGIN_WORKERS_NAMESPACE
// Entry point for the DOM.
JSBool
ResolveWorkerClasses(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, unsigned aFlags,
JSObject** aObjp)
JSMutableHandleObject aObjp)
{
AssertIsOnMainThread();
// Don't care about assignments, bail now.
if (aFlags & JSRESOLVE_ASSIGNING) {
*aObjp = nsnull;
aObjp.set(nsnull);
return true;
}
@ -418,7 +418,7 @@ ResolveWorkerClasses(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, unsign
if (shouldResolve) {
// Don't do anything if workers are disabled.
if (!isChrome && !Preferences::GetBool(PREF_WORKERS_ENABLED)) {
*aObjp = nsnull;
aObjp.set(nsnull);
return true;
}
@ -440,12 +440,12 @@ ResolveWorkerClasses(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, unsign
return false;
}
*aObjp = aObj;
aObjp.set(aObj);
return true;
}
// Not resolved.
*aObjp = nsnull;
aObjp.set(nsnull);
return true;
}

View File

@ -787,14 +787,14 @@ private:
static JSBool
Resolve(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, unsigned aFlags,
JSObject** aObjp)
JSMutableHandleObject aObjp)
{
JSBool resolved;
if (!JS_ResolveStandardClass(aCx, aObj, aId, &resolved)) {
return false;
}
*aObjp = resolved ? aObj.value() : NULL;
aObjp.set(resolved ? aObj.get() : NULL);
return true;
}

View File

@ -45,7 +45,7 @@ AssertIsOnMainThread()
// All of these are implemented in RuntimeService.cpp
JSBool
ResolveWorkerClasses(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, unsigned aFlags,
JSObject** aObjp);
JSMutableHandleObject aObjp);
void
CancelWorkersForWindow(JSContext* aCx, nsPIDOMWindow* aWindow);

View File

@ -84,7 +84,8 @@ global_enumerate(JSContext *cx, JSHandleObject *obj)
}
static JSBool
global_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags, JSObject **objp)
global_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
MutableHandleObject objp)
{
#ifdef LAZY_STANDARD_CLASSES
if ((flags & JSRESOLVE_ASSIGNING) == 0) {
@ -93,7 +94,7 @@ global_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
return JS_FALSE;
if (resolved) {
*objp = obj;
objp.set(obj);
return JS_TRUE;
}
}
@ -138,7 +139,7 @@ global_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
fun = JS_DefineFunction(cx, obj, name, Exec, 0, JSPROP_ENUMERATE);
ok = (fun != NULL);
if (ok)
*objp = obj;
objp.set(obj);
break;
}
}

View File

@ -298,13 +298,13 @@ JSObject_to_PObjectWrapperParent(JSObject* from, PObjectWrapperParent** to)
ObjectWrapperParent::
JSObject_from_PObjectWrapperParent(JSContext* cx,
const PObjectWrapperParent* from,
JSObject** to)
JSMutableHandleObject to)
{
const ObjectWrapperParent* owp =
static_cast<const ObjectWrapperParent*>(from);
*to = owp
? owp->GetJSObject(cx)
: JSVAL_TO_OBJECT(JSVAL_NULL);
to.set(owp
? owp->GetJSObject(cx)
: JSVAL_TO_OBJECT(JSVAL_NULL));
return true;
}
@ -314,7 +314,7 @@ jsval_from_PObjectWrapperParent(JSContext* cx,
const PObjectWrapperParent* from,
jsval* to)
{
JSObject* obj;
JS::RootedObject obj(cx);
if (!JSObject_from_PObjectWrapperParent(cx, from, &obj))
return false;
*to = OBJECT_TO_JSVAL(obj);
@ -544,7 +544,7 @@ ObjectWrapperParent::CPOW_NewEnumerate(JSContext *cx, JSHandleObject obj,
/*static*/ JSBool
ObjectWrapperParent::CPOW_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id,
unsigned flags, JSObject **objp)
unsigned flags, JSMutableHandleObject objp)
{
CPOW_LOG(("Calling CPOW_NewResolve (%s)...",
JSVAL_TO_CSTR(cx, id)));
@ -569,9 +569,10 @@ ObjectWrapperParent::CPOW_NewResolve(JSContext *cx, JSHandleObject obj, JSHandle
!JSObject_from_PObjectWrapperParent(cx, out_pobj, objp))
return JS_FALSE;
if (*objp) {
AutoResolveFlag arf(*objp);
JS_DefinePropertyById(cx, *objp, id, JSVAL_VOID, NULL, NULL,
if (objp) {
AutoResolveFlag arf(objp);
JS::RootedObject obj2(cx, objp);
JS_DefinePropertyById(cx, obj2, id, JSVAL_VOID, NULL, NULL,
JSPROP_ENUMERATE);
}
return JS_TRUE;

View File

@ -80,7 +80,7 @@ private:
static JSBool
CPOW_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
JSObject **objp);
JSMutableHandleObject objp);
static JSBool
CPOW_Convert(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp);
@ -108,7 +108,7 @@ private:
static bool
JSObject_from_PObjectWrapperParent(JSContext* cx,
const PObjectWrapperParent* from,
JSObject** to);
JSMutableHandleObject to);
static bool
jsval_from_PObjectWrapperParent(JSContext* cx,
const PObjectWrapperParent* from,

View File

@ -15,6 +15,9 @@ namespace js {
class TempAllocPolicy;
/* Integral types for all hash functions. */
typedef uint32_t HashNumber;
/*****************************************************************************/
namespace detail {
@ -285,6 +288,7 @@ class HashTable : private AllocPolicy
static const uint8_t sMinAlphaFrac = 64; /* (0x100 * .25) taken from jsdhash.h */
static const uint8_t sMaxAlphaFrac = 192; /* (0x100 * .75) taken from jsdhash.h */
static const uint8_t sInvMaxAlpha = 171; /* (ceil(0x100 / .75) >> 1) */
static const HashNumber sGoldenRatio = 0x9E3779B9U; /* taken from jsdhash.h */
static const HashNumber sFreeKey = Entry::sFreeKey;
static const HashNumber sRemovedKey = Entry::sRemovedKey;
static const HashNumber sCollisionBit = Entry::sCollisionBit;
@ -304,7 +308,10 @@ class HashTable : private AllocPolicy
static HashNumber prepareHash(const Lookup& l)
{
HashNumber keyHash = ScrambleHashCode(HashPolicy::hash(l));
HashNumber keyHash = HashPolicy::hash(l);
/* Improve keyHash distribution. */
keyHash *= sGoldenRatio;
/* Avoid reserved hash codes. */
if (!isLiveHash(keyHash))

View File

@ -355,26 +355,6 @@ JS_FLOOR_LOG2W(size_t n)
return js_FloorLog2wImpl(n);
}
/*
* JS_ROTATE_LEFT32
*
* There is no rotate operation in the C Language so the construct (a << 4) |
* (a >> 28) is used instead. Most compilers convert this to a rotate
* instruction but some versions of MSVC don't without a little help. To get
* MSVC to generate a rotate instruction, we have to use the _rotl intrinsic
* and use a pragma to make _rotl inline.
*
* MSVC in VS2005 will do an inline rotate instruction on the above construct.
*/
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || \
defined(_M_X64))
#include <stdlib.h>
#pragma intrinsic(_rotl)
#define JS_ROTATE_LEFT32(a, bits) _rotl(a, bits)
#else
#define JS_ROTATE_LEFT32(a, bits) (((a) << (bits)) | ((a) >> (32 - (bits))))
#endif
JS_END_EXTERN_C
#ifdef __cplusplus
@ -915,61 +895,6 @@ RoundUpPow2(size_t x)
return size_t(1) << JS_CEILING_LOG2W(x);
}
/* Integral types for all hash functions. */
typedef uint32_t HashNumber;
namespace detail {
/*
* Given a raw hash code, h, return a number to be used as an index into a
* power-of-two-sized hash table.
*
* This function aims to produce as uniform an output distribution as possible,
* especially in the rightmost bits, even though the input distribution may be
* highly nonrandom, given the constraints that this must be deterministic and
* quick to compute.
*/
inline HashNumber
ScrambleHashCode(HashNumber h)
{
/*
* Simply returning h would not cause any hash tables to produce wrong
* answers. But it can produce pathologically bad performance: The caller
* bitmasks the result, keeping only the lowest bits. The low bits of
* hash codes are often low-entropy.
*
* Multiplying by a constant is a good start. It mixes the bits such that
* each bit of the output is a combination of several bits of the
* input--except for the lowest few bits which are not mixed at all
* (shuffleBits * X has the same three low bits as X, for all X). So after
* multiplication, we rotate those least-mixed low bits out toward the end
* where they are likely to be masked away. The number of bits rotated
* toward the end is shiftBits, which is 12 so that hash tables with size
* up to 2^(32-12) = 2^20 = about a million buckets will get the best-mixed
* bits we have.
*
* The particular value of shuffleBits is taken from the hex expansion of
* the golden ratio, which starts 1.9E3779B9.... This value has been
* cargo-culted around since the original jshash.h. I doubt there is
* anything particularly magical about it, except:
*
* - It's odd. Multiplying by any odd number modulo 2^32 loses no entropy;
* multiplying by any even number zeroes out a bit (or more).
*
* - It has a fairly even mix of one bits and zero bits. Too few one-bits
* and each bit of the output ends up being a combination of a very small
* number of input bits. Too many one-bits and you end up with the same
* problem; in the limit, multiplying by 0xffffffff modulo 2^32 is the
* same as multiplying by -1, which hardly mixes the bits at all.
*/
static const HashNumber shuffleBits = 0x9E3779B9U;
h *= shuffleBits;
static const int bitsToRotate = 20;
return JS_ROTATE_LEFT32(h, bitsToRotate);
}
} /* namespace detail */
} /* namespace js */
namespace JS {

View File

@ -1,38 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef Iterator_inl_h_
#define Iterator_inl_h_
#include "jsiter.h"
#include "jsobjinlines.h"
inline bool
JSObject::isPropertyIterator() const
{
return hasClass(&js::PropertyIteratorObject::class_);
}
inline js::PropertyIteratorObject &
JSObject::asPropertyIterator()
{
JS_ASSERT(isPropertyIterator());
return *static_cast<js::PropertyIteratorObject *>(this);
}
js::NativeIterator *
js::PropertyIteratorObject::getNativeIterator() const
{
JS_ASSERT(isPropertyIterator());
return static_cast<js::NativeIterator *>(getPrivate());
}
inline void
js::PropertyIteratorObject::setNativeIterator(js::NativeIterator *ni)
{
setPrivate(ni);
}
#endif // Iterator_inl_h_

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
#include "jscntxt.h"
#include "jsobj.h"
#include "mozilla/FloatingPoint.h"
#include "js/HashTable.h"
namespace js {
@ -32,8 +32,6 @@ class HashableValue {
typedef HashableValue Lookup;
static HashNumber hash(const Lookup &v) { return v.hash(); }
static bool match(const HashableValue &k, const Lookup &l) { return k.equals(l); }
static bool isEmpty(const HashableValue &v) { return v.value.isMagic(JS_HASH_KEY_EMPTY); }
static void makeEmpty(HashableValue *vp) { vp->value = MagicValue(JS_HASH_KEY_EMPTY); }
};
HashableValue() : value(UndefinedValue()) {}
@ -42,7 +40,6 @@ class HashableValue {
HashNumber hash() const;
bool equals(const HashableValue &other) const;
HashableValue mark(JSTracer *trc) const;
Value get() const { return value.get(); }
class AutoRooter : private AutoGCRooter
{
@ -64,20 +61,13 @@ class HashableValue {
};
};
template <class Key, class Value, class OrderedHashPolicy, class AllocPolicy>
class OrderedHashMap;
template <class T, class OrderedHashPolicy, class AllocPolicy>
class OrderedHashSet;
typedef OrderedHashMap<HashableValue,
RelocatableValue,
HashableValue::Hasher,
RuntimeAllocPolicy> ValueMap;
typedef OrderedHashSet<HashableValue,
HashableValue::Hasher,
RuntimeAllocPolicy> ValueSet;
typedef HashMap<HashableValue,
RelocatableValue,
HashableValue::Hasher,
RuntimeAllocPolicy> ValueMap;
typedef HashSet<HashableValue,
HashableValue::Hasher,
RuntimeAllocPolicy> ValueSet;
class MapObject : public JSObject {
public:
@ -95,7 +85,6 @@ class MapObject : public JSObject {
static JSBool has(JSContext *cx, unsigned argc, Value *vp);
static JSBool set(JSContext *cx, unsigned argc, Value *vp);
static JSBool delete_(JSContext *cx, unsigned argc, Value *vp);
static JSBool iterator(JSContext *cx, unsigned argc, Value *vp);
};
class SetObject : public JSObject {
@ -113,7 +102,6 @@ class SetObject : public JSObject {
static JSBool has(JSContext *cx, unsigned argc, Value *vp);
static JSBool add(JSContext *cx, unsigned argc, Value *vp);
static JSBool delete_(JSContext *cx, unsigned argc, Value *vp);
static JSBool iterator(JSContext *cx, unsigned argc, Value *vp);
};
} /* namespace js */

View File

@ -514,7 +514,6 @@ static JSPropertySpec sArrayProps[] = {
static JSFunctionSpec sArrayInstanceFunctions[] = {
JS_FN("addressOfElement", ArrayType::AddressOfElement, 1, CDATAFN_FLAGS),
JS_FN("iterator", JS_ArrayIterator, 0, CDATAFN_FLAGS),
JS_FS_END
};

File diff suppressed because it is too large Load Diff

View File

@ -239,19 +239,19 @@ EmitN(JSContext *cx, BytecodeEmitter *bce, JSOp op, size_t extra);
* value other than undefined if the constant was found, true with *vp set to
* JSVAL_VOID if not found, and false on error.
*/
bool
JSBool
DefineCompileTimeConstant(JSContext *cx, BytecodeEmitter *bce, JSAtom *atom, ParseNode *pn);
/*
* Emit code into bce for the tree rooted at pn.
*/
bool
JSBool
EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn);
/*
* Emit function code using bce for the tree rooted at body.
*/
bool
JSBool
EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *body);
} /* namespace frontend */
@ -421,7 +421,7 @@ NewSrcNote3(JSContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptrdiff_t off
jssrcnote *
AddToSrcNoteDelta(JSContext *cx, BytecodeEmitter *bce, jssrcnote *sn, ptrdiff_t delta);
bool
JSBool
FinishTakingSrcNotes(JSContext *cx, BytecodeEmitter *bce, jssrcnote *notes);
void

View File

@ -72,7 +72,7 @@ ContainsVarOrConst(ParseNode *pn)
* Fold from one constant type to another.
* XXX handles only strings and numbers for now
*/
static bool
static JSBool
FoldType(JSContext *cx, ParseNode *pn, ParseNodeKind kind)
{
if (!pn->isKind(kind)) {
@ -81,7 +81,7 @@ FoldType(JSContext *cx, ParseNode *pn, ParseNodeKind kind)
if (pn->isKind(PNK_STRING)) {
double d;
if (!ToNumber(cx, StringValue(pn->pn_atom), &d))
return false;
return JS_FALSE;
pn->pn_dval = d;
pn->setKind(PNK_NUMBER);
pn->setOp(JSOP_DOUBLE);
@ -92,10 +92,10 @@ FoldType(JSContext *cx, ParseNode *pn, ParseNodeKind kind)
if (pn->isKind(PNK_NUMBER)) {
JSString *str = js_NumberToString(cx, pn->pn_dval);
if (!str)
return false;
return JS_FALSE;
pn->pn_atom = js_AtomizeString(cx, str);
if (!pn->pn_atom)
return false;
return JS_FALSE;
pn->setKind(PNK_STRING);
pn->setOp(JSOP_STRING);
}
@ -104,7 +104,7 @@ FoldType(JSContext *cx, ParseNode *pn, ParseNodeKind kind)
default:;
}
}
return true;
return JS_TRUE;
}
/*
@ -112,7 +112,7 @@ FoldType(JSContext *cx, ParseNode *pn, ParseNodeKind kind)
* one of them aliases pn, so you can't safely fetch pn2->pn_next, e.g., after
* a successful call to this function.
*/
static bool
static JSBool
FoldBinaryNumeric(JSContext *cx, JSOp op, ParseNode *pn1, ParseNode *pn2,
ParseNode *pn, Parser *parser)
{
@ -188,12 +188,12 @@ FoldBinaryNumeric(JSContext *cx, JSOp op, ParseNode *pn1, ParseNode *pn2,
pn->setOp(JSOP_DOUBLE);
pn->setArity(PN_NULLARY);
pn->pn_dval = d;
return true;
return JS_TRUE;
}
#if JS_HAS_XML_SUPPORT
static bool
static JSBool
FoldXMLConstants(JSContext *cx, ParseNode *pn, Parser *parser)
{
JS_ASSERT(pn->isArity(PN_LIST));
@ -238,20 +238,20 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, Parser *parser)
case PNK_XMLCDATA:
str = js_MakeXMLCDATAString(cx, pn2->pn_atom);
if (!str)
return false;
return JS_FALSE;
break;
case PNK_XMLCOMMENT:
str = js_MakeXMLCommentString(cx, pn2->pn_atom);
if (!str)
return false;
return JS_FALSE;
break;
case PNK_XMLPI: {
XMLProcessingInstruction &pi = pn2->asXMLProcessingInstruction();
str = js_MakeXMLPIString(cx, pi.target(), pi.data());
if (!str)
return false;
return JS_FALSE;
break;
}
@ -278,7 +278,7 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, Parser *parser)
pn1->setArity(PN_NULLARY);
pn1->pn_atom = js_AtomizeString(cx, accum);
if (!pn1->pn_atom)
return false;
return JS_FALSE;
JS_ASSERT(pnp != &pn1->pn_next);
*pnp = pn1;
}
@ -295,7 +295,7 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, Parser *parser)
: js_ConcatStrings(cx, accum, str);
}
if (!str)
return false;
return JS_FALSE;
#ifdef DEBUG_brendanXXX
printf("2: %d, %d => ", i, j);
FileEscapedString(stdout, str, 0);
@ -317,7 +317,7 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, Parser *parser)
if (str) {
accum = js_ConcatStrings(cx, accum, str);
if (!accum)
return false;
return JS_FALSE;
}
JS_ASSERT(*pnp == pn1);
@ -330,7 +330,7 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, Parser *parser)
pn1->setArity(PN_NULLARY);
pn1->pn_atom = js_AtomizeString(cx, accum);
if (!pn1->pn_atom)
return false;
return JS_FALSE;
JS_ASSERT(pnp != &pn1->pn_next);
*pnp = pn1;
}
@ -350,7 +350,7 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, Parser *parser)
pn->setOp(JSOP_TOXML);
}
}
return true;
return JS_TRUE;
}
#endif /* JS_HAS_XML_SUPPORT */

View File

@ -600,7 +600,7 @@ struct ParseNode {
} binary;
struct { /* one kid if unary */
ParseNode *kid;
bool hidden; /* hidden genexp-induced JSOP_YIELD
JSBool hidden; /* hidden genexp-induced JSOP_YIELD
or directive prologue member (as
pn_prologue) */
} unary;

View File

@ -403,7 +403,7 @@ HasFinalReturn(ParseNode *pn)
}
}
static bool
static JSBool
ReportBadReturn(JSContext *cx, Parser *parser, ParseNode *pn, Parser::Reporter reporter,
unsigned errnum, unsigned anonerrnum)
{
@ -417,7 +417,7 @@ ReportBadReturn(JSContext *cx, Parser *parser, ParseNode *pn, Parser::Reporter r
return (parser->*reporter)(pn, errnum, name.ptr());
}
static bool
static JSBool
CheckFinalReturn(JSContext *cx, Parser *parser, ParseNode *pn)
{
JS_ASSERT(parser->tc->sc->inFunction());
@ -919,13 +919,13 @@ js::DefineArg(ParseNode *pn, JSAtom *atom, unsigned i, Parser *parser)
* function is called indirectly from the variable declaration parser by way
* of CheckDestructuring and its friends.
*/
typedef bool
typedef JSBool
(*Binder)(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser);
static bool
static JSBool
BindLet(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser);
static bool
static JSBool
BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser);
struct BindData {
@ -961,7 +961,7 @@ struct BindData {
};
#if JS_HAS_DESTRUCTURING
static bool
static JSBool
BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
{
TreeContext *tc = parser->tc;
@ -974,7 +974,7 @@ BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser
*/
if (tc->decls.lookupFirst(atom)) {
parser->reportError(NULL, JSMSG_DESTRUCT_DUP_ARG);
return false;
return JS_FALSE;
}
ParseNode *pn = data->pn;
@ -1036,20 +1036,20 @@ Parser::newFunction(TreeContext *tc, JSAtom *atom, FunctionSyntaxKind kind)
return fun;
}
static bool
static JSBool
MatchOrInsertSemicolon(JSContext *cx, TokenStream *ts)
{
TokenKind tt = ts->peekTokenSameLine(TSF_OPERAND);
if (tt == TOK_ERROR)
return false;
return JS_FALSE;
if (tt != TOK_EOF && tt != TOK_EOL && tt != TOK_SEMI && tt != TOK_RC) {
/* Advance the scanner for proper error location reporting. */
ts->getToken(TSF_OPERAND);
ts->reportError(JSMSG_SEMI_BEFORE_STMNT);
return false;
return JS_FALSE;
}
(void) ts->matchToken(TOK_SEMI);
return true;
return JS_TRUE;
}
static bool
@ -1959,7 +1959,7 @@ ReportRedeclaration(JSContext *cx, Parser *parser, ParseNode *pn, bool isConst,
* populate data->pn->pn_{op,cookie,defn,dflags}; and stash a pointer to
* data->pn in a slot of the block object.
*/
static bool
static JSBool
BindLet(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
{
TreeContext *tc = parser->tc;
@ -2100,7 +2100,7 @@ BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, TreeContex
return true;
}
static bool
static JSBool
BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
{
TreeContext *tc = parser->tc;
@ -2131,14 +2131,14 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
if (dn_kind == Definition::ARG) {
JSAutoByteString name;
if (!js_AtomToPrintableString(cx, atom, &name))
return false;
return JS_FALSE;
if (op == JSOP_DEFCONST) {
parser->reportError(pn, JSMSG_REDECLARED_PARAM, name.ptr());
return false;
return JS_FALSE;
}
if (!parser->reportStrictWarning(pn, JSMSG_VAR_HIDES_ARG, name.ptr()))
return false;
return JS_FALSE;
} else {
bool error = (op == JSOP_DEFCONST ||
dn_kind == Definition::CONST ||
@ -2156,7 +2156,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
!(parser->*reporter)(pn, JSMSG_REDECLARED_VAR,
Definition::kindString(dn_kind), name.ptr()))
{
return false;
return JS_FALSE;
}
}
}
@ -2164,7 +2164,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
if (mdl.empty()) {
if (!Define(pn, atom, tc))
return false;
return JS_FALSE;
} else {
/*
* A var declaration never recreates an existing binding, it restates
@ -2188,7 +2188,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
if (pn->isDefn()) {
pnu = NameNode::create(PNK_NAME, atom, parser, parser->tc);
if (!pnu)
return false;
return JS_FALSE;
}
LinkUseToDef(pnu, dn);
@ -2206,7 +2206,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
if (dn) {
JS_ASSERT_IF(data->op == JSOP_DEFCONST,
dn->kind() == Definition::CONST);
return true;
return JS_TRUE;
}
/*
@ -2220,7 +2220,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
} else {
ParseNode *pn2 = NameNode::create(PNK_NAME, atom, parser, parser->tc);
if (!pn2)
return false;
return JS_FALSE;
/* The token stream may be past the location for pn. */
pn2->pn_pos = pn->pn_pos;
@ -2230,7 +2230,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
}
if (!tc->decls.addHoist(atom, (Definition *) pn))
return false;
return JS_FALSE;
pn->setDefn(true);
pn->pn_dflags &= ~PND_PLACEHOLDER;
}
@ -2338,14 +2338,14 @@ NoteNameUse(ParseNode *pn, Parser *parser)
#if JS_HAS_DESTRUCTURING
static bool
static JSBool
BindDestructuringVar(JSContext *cx, BindData *data, ParseNode *pn, Parser *parser)
{
JS_ASSERT(pn->isKind(PNK_NAME));
data->pn = pn;
if (!data->binder(cx, data, pn->pn_atom, parser))
return false;
return JS_FALSE;
/*
* Select the appropriate name-setting opcode, respecting eager selection
@ -2362,7 +2362,7 @@ BindDestructuringVar(JSContext *cx, BindData *data, ParseNode *pn, Parser *parse
pn->pn_dflags |= PND_CONST;
NoteLValue(cx, pn, parser->tc->sc, PND_INITIALIZED);
return true;
return JS_TRUE;
}
/*
@ -2383,7 +2383,7 @@ BindDestructuringVar(JSContext *cx, BindData *data, ParseNode *pn, Parser *parse
* JSOP_ENUMELEM yet, because the LHS may turn out to be an arg or local var,
* which can be optimized further. So we select JSOP_SETNAME.
*/
static bool
static JSBool
BindDestructuringLHS(JSContext *cx, ParseNode *pn, Parser *parser)
{
switch (pn->getKind()) {
@ -2404,7 +2404,7 @@ BindDestructuringLHS(JSContext *cx, ParseNode *pn, Parser *parser)
case PNK_LP:
if (!MakeSetCall(cx, pn, parser, JSMSG_BAD_LEFTSIDE_OF_ASS))
return false;
return JS_FALSE;
break;
#if JS_HAS_XML_SUPPORT
@ -2416,10 +2416,10 @@ BindDestructuringLHS(JSContext *cx, ParseNode *pn, Parser *parser)
default:
parser->reportError(pn, JSMSG_BAD_LEFTSIDE_OF_ASS);
return false;
return JS_FALSE;
}
return true;
return JS_TRUE;
}
/*
@ -2473,7 +2473,7 @@ CheckDestructuring(JSContext *cx, BindData *data, ParseNode *left, Parser *parse
}
Rooted<StaticBlockObject *> blockObj(cx);
blockObj = data && data->binder == BindLet ? data->let.blockObj.reference() : NULL;
blockObj = data && data->binder == BindLet ? data->let.blockObj.get() : NULL;
uint32_t blockCountBefore = blockObj ? blockObj->slotCount() : 0;
if (left->isKind(PNK_RB)) {
@ -2568,7 +2568,7 @@ Parser::destructuringExpr(BindData *data, TokenKind tt)
JS_ASSERT(tokenStream.isCurrentTokenType(tt));
tc->inDeclDestructuring = true;
ParseNode *pn = primaryExpr(tt, false);
ParseNode *pn = primaryExpr(tt, JS_FALSE);
tc->inDeclDestructuring = false;
if (!pn)
return NULL;
@ -4147,7 +4147,7 @@ Parser::variables(ParseNodeKind kind, StaticBlockObject *blockObj, VarContext va
#if JS_HAS_DESTRUCTURING
if (tt == TOK_LB || tt == TOK_LC) {
tc->inDeclDestructuring = true;
pn2 = primaryExpr(tt, false);
pn2 = primaryExpr(tt, JS_FALSE);
tc->inDeclDestructuring = false;
if (!pn2)
return NULL;
@ -4618,7 +4618,7 @@ SetLvalKid(JSContext *cx, Parser *parser, ParseNode *pn, ParseNode *kid,
static const char incop_name_str[][10] = {"increment", "decrement"};
static bool
static JSBool
SetIncOpKid(JSContext *cx, Parser *parser, ParseNode *pn, ParseNode *kid,
TokenKind tt, bool preorder)
{
@ -4642,7 +4642,7 @@ SetIncOpKid(JSContext *cx, Parser *parser, ParseNode *pn, ParseNode *kid,
case PNK_LP:
if (!MakeSetCall(cx, kid, parser, JSMSG_BAD_INCOP_OPERAND))
return false;
return JS_FALSE;
/* FALL THROUGH */
#if JS_HAS_XML_SUPPORT
case PNK_XMLUNARY:
@ -4661,7 +4661,7 @@ SetIncOpKid(JSContext *cx, Parser *parser, ParseNode *pn, ParseNode *kid,
op = JSOP_NOP;
}
pn->setOp(op);
return true;
return JS_TRUE;
}
ParseNode *
@ -4700,7 +4700,7 @@ Parser::unaryExpr()
pn = UnaryNode::create((tt == TOK_INC) ? PNK_PREINCREMENT : PNK_PREDECREMENT, this);
if (!pn)
return NULL;
pn2 = memberExpr(true);
pn2 = memberExpr(JS_TRUE);
if (!pn2)
return NULL;
if (!SetIncOpKid(context, this, pn, pn2, tt, true))
@ -4752,7 +4752,7 @@ Parser::unaryExpr()
default:
tokenStream.ungetToken();
pn = memberExpr(true);
pn = memberExpr(JS_TRUE);
if (!pn)
return NULL;
@ -5199,7 +5199,7 @@ Parser::comprehensionTail(ParseNode *kid, unsigned blockid, bool isGenexp,
case TOK_LB:
case TOK_LC:
tc->inDeclDestructuring = true;
pn3 = primaryExpr(tt, false);
pn3 = primaryExpr(tt, JS_FALSE);
tc->inDeclDestructuring = false;
if (!pn3)
return NULL;
@ -5462,11 +5462,11 @@ Parser::assignExprWithoutYield(unsigned msg)
return res;
}
bool
JSBool
Parser::argumentList(ParseNode *listNode)
{
if (tokenStream.matchToken(TOK_RP, TSF_OPERAND))
return true;
return JS_TRUE;
GenexpGuard guard(this);
bool arg0 = true;
@ -5474,7 +5474,7 @@ Parser::argumentList(ParseNode *listNode)
do {
ParseNode *argNode = assignExpr();
if (!argNode)
return false;
return JS_FALSE;
if (arg0)
guard.endBody();
@ -5483,25 +5483,25 @@ Parser::argumentList(ParseNode *listNode)
!argNode->isInParens() &&
tokenStream.peekToken() == TOK_COMMA) {
reportError(argNode, JSMSG_BAD_GENERATOR_SYNTAX, js_yield_str);
return false;
return JS_FALSE;
}
#endif
#if JS_HAS_GENERATOR_EXPRS
if (tokenStream.matchToken(TOK_FOR)) {
if (!guard.checkValidBody(argNode))
return false;
return JS_FALSE;
argNode = generatorExpr(argNode);
if (!argNode)
return false;
return JS_FALSE;
if (listNode->pn_count > 1 ||
tokenStream.peekToken() == TOK_COMMA) {
reportError(argNode, JSMSG_BAD_GENERATOR_SYNTAX, js_generator_str);
return false;
return JS_FALSE;
}
} else
#endif
if (arg0 && !guard.maybeNoteGenerator(argNode))
return false;
return JS_FALSE;
arg0 = false;
@ -5510,13 +5510,13 @@ Parser::argumentList(ParseNode *listNode)
if (tokenStream.getToken() != TOK_RP) {
reportError(NULL, JSMSG_PAREN_AFTER_ARGS);
return false;
return JS_FALSE;
}
return true;
return JS_TRUE;
}
ParseNode *
Parser::memberExpr(bool allowCallSyntax)
Parser::memberExpr(JSBool allowCallSyntax)
{
ParseNode *lhs;
@ -5528,7 +5528,7 @@ Parser::memberExpr(bool allowCallSyntax)
lhs = ListNode::create(PNK_NEW, this);
if (!lhs)
return NULL;
ParseNode *ctorExpr = memberExpr(false);
ParseNode *ctorExpr = memberExpr(JS_FALSE);
if (!ctorExpr)
return NULL;
lhs->setOp(JSOP_NEW);
@ -5544,7 +5544,7 @@ Parser::memberExpr(bool allowCallSyntax)
}
lhs->pn_pos.end = lhs->last()->pn_pos.end;
} else {
lhs = primaryExpr(tt, false);
lhs = primaryExpr(tt, JS_FALSE);
if (!lhs)
return NULL;
@ -5641,7 +5641,7 @@ Parser::memberExpr(bool allowCallSyntax)
if (!nextMember)
return NULL;
tt = tokenStream.getToken(TSF_OPERAND | TSF_KEYWORD_IS_NAME);
ParseNode *pn3 = primaryExpr(tt, true);
ParseNode *pn3 = primaryExpr(tt, JS_TRUE);
if (!pn3)
return NULL;
if (pn3->isKind(PNK_NAME) && !pn3->isInParens()) {
@ -5950,7 +5950,7 @@ Parser::attributeIdentifier()
* Make a TOK_LC unary node whose pn_kid is an expression.
*/
ParseNode *
Parser::xmlExpr(bool inTag)
Parser::xmlExpr(JSBool inTag)
{
JS_ASSERT(allowsXML());
@ -6002,7 +6002,7 @@ Parser::xmlNameExpr()
do {
tt = tokenStream.currentToken().type;
if (tt == TOK_LC) {
pn2 = xmlExpr(true);
pn2 = xmlExpr(JS_TRUE);
if (!pn2)
return NULL;
} else {
@ -6104,7 +6104,7 @@ Parser::xmlTagContent(ParseNodeKind tagkind, JSAtom **namep)
JS_ASSERT(tokenStream.currentToken().t_op == JSOP_STRING);
pn2 = atomNode(PNK_XMLATTR, JSOP_STRING);
} else if (tt == TOK_LC) {
pn2 = xmlExpr(true);
pn2 = xmlExpr(JS_TRUE);
pn->pn_xflags |= PNX_CANTFOLD;
} else {
reportError(NULL, JSMSG_BAD_XML_ATTR_VALUE);
@ -6133,7 +6133,7 @@ Parser::xmlTagContent(ParseNodeKind tagkind, JSAtom **namep)
* Consume XML element tag content, including the TOK_XMLETAGO (</) sequence
* that opens the end tag for the container.
*/
bool
JSBool
Parser::xmlElementContent(ParseNode *pn)
{
JS_ASSERT(allowsXML());
@ -6141,7 +6141,7 @@ Parser::xmlElementContent(ParseNode *pn)
tokenStream.setXMLTagMode(false);
for (;;) {
TokenKind tt = tokenStream.getToken(TSF_XMLTEXTMODE);
XML_CHECK_FOR_ERROR_AND_EOF(tt, false);
XML_CHECK_FOR_ERROR_AND_EOF(tt, JS_FALSE);
JS_ASSERT(tt == TOK_XMLSPACE || tt == TOK_XMLTEXT);
JSAtom *textAtom = tokenStream.currentToken().atom();
@ -6157,18 +6157,18 @@ Parser::xmlElementContent(ParseNode *pn)
}
tt = tokenStream.getToken(TSF_OPERAND);
XML_CHECK_FOR_ERROR_AND_EOF(tt, false);
XML_CHECK_FOR_ERROR_AND_EOF(tt, JS_FALSE);
if (tt == TOK_XMLETAGO)
break;
ParseNode *pn2;
if (tt == TOK_LC) {
pn2 = xmlExpr(false);
pn2 = xmlExpr(JS_FALSE);
if (!pn2)
return false;
pn->pn_xflags |= PNX_CANTFOLD;
} else if (tt == TOK_XMLSTAGO) {
pn2 = xmlElementOrList(false);
pn2 = xmlElementOrList(JS_FALSE);
if (!pn2)
return false;
pn2->pn_xflags &= ~PNX_XMLROOT;
@ -6191,14 +6191,14 @@ Parser::xmlElementContent(ParseNode *pn)
tokenStream.setXMLTagMode(true);
JS_ASSERT(tokenStream.currentToken().type == TOK_XMLETAGO);
return true;
return JS_TRUE;
}
/*
* Return a PN_LIST node containing an XML or XMLList Initialiser.
*/
ParseNode *
Parser::xmlElementOrList(bool allowList)
Parser::xmlElementOrList(JSBool allowList)
{
JS_ASSERT(allowsXML());
@ -6334,7 +6334,7 @@ Parser::xmlElementOrList(bool allowList)
}
ParseNode *
Parser::xmlElementOrListRoot(bool allowList)
Parser::xmlElementOrListRoot(JSBool allowList)
{
JS_ASSERT(allowsXML());
@ -6903,7 +6903,7 @@ Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
case TOK_LP:
{
bool genexp;
JSBool genexp;
pn = parenExpr(&genexp);
if (!pn)
@ -6927,7 +6927,7 @@ Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
break;
case TOK_XMLSTAGO:
pn = xmlElementOrListRoot(true);
pn = xmlElementOrListRoot(JS_TRUE);
if (!pn)
return NULL;
break;
@ -7024,7 +7024,7 @@ Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
}
ParseNode *
Parser::parenExpr(bool *genexp)
Parser::parenExpr(JSBool *genexp)
{
TokenPtr begin;
ParseNode *pn;
@ -7033,7 +7033,7 @@ Parser::parenExpr(bool *genexp)
begin = tokenStream.currentToken().pos.begin;
if (genexp)
*genexp = false;
*genexp = JS_FALSE;
GenexpGuard guard(this);
@ -7061,7 +7061,7 @@ Parser::parenExpr(bool *genexp)
return NULL;
}
pn->pn_pos.end = tokenStream.currentToken().pos.end;
*genexp = true;
*genexp = JS_TRUE;
}
} else
#endif /* JS_HAS_GENERATOR_EXPRS */

View File

@ -200,9 +200,9 @@ struct Parser : private AutoGCRooter
ParseNode *mulExpr1i();
ParseNode *mulExpr1n();
ParseNode *unaryExpr();
ParseNode *memberExpr(bool allowCallSyntax);
ParseNode *memberExpr(JSBool allowCallSyntax);
ParseNode *primaryExpr(TokenKind tt, bool afterDoubleDot);
ParseNode *parenExpr(bool *genexp = NULL);
ParseNode *parenExpr(JSBool *genexp = NULL);
/*
* Additional JS parsers.
@ -218,7 +218,7 @@ struct Parser : private AutoGCRooter
ParseNode *comprehensionTail(ParseNode *kid, unsigned blockid, bool isGenexp,
ParseNodeKind kind = PNK_SEMI, JSOp op = JSOP_NOP);
ParseNode *generatorExpr(ParseNode *kid);
bool argumentList(ParseNode *listNode);
JSBool argumentList(ParseNode *listNode);
ParseNode *bracketedExpr();
ParseNode *letBlock(LetContext letContext);
ParseNode *returnOrYield(bool useAssignExpr);
@ -238,12 +238,12 @@ struct Parser : private AutoGCRooter
ParseNode *qualifiedSuffix(ParseNode *pn);
ParseNode *qualifiedIdentifier();
ParseNode *attributeIdentifier();
ParseNode *xmlExpr(bool inTag);
ParseNode *xmlExpr(JSBool inTag);
ParseNode *xmlNameExpr();
ParseNode *xmlTagContent(ParseNodeKind tagkind, JSAtom **namep);
bool xmlElementContent(ParseNode *pn);
ParseNode *xmlElementOrList(bool allowList);
ParseNode *xmlElementOrListRoot(bool allowList);
JSBool xmlElementContent(ParseNode *pn);
ParseNode *xmlElementOrList(JSBool allowList);
ParseNode *xmlElementOrListRoot(JSBool allowList);
ParseNode *starOrAtPropertyIdentifier(TokenKind tt);
ParseNode *propertyQualifiedIdentifier();

View File

@ -94,24 +94,24 @@ js::FindKeyword(const jschar *s, size_t length)
return NULL;
}
bool
JSBool
js::IsIdentifier(JSLinearString *str)
{
const jschar *chars = str->chars();
size_t length = str->length();
if (length == 0)
return false;
return JS_FALSE;
jschar c = *chars;
if (!IsIdentifierStart(c))
return false;
return JS_FALSE;
const jschar *end = chars + length;
while (++chars != end) {
c = *chars;
if (!IsIdentifierPart(c))
return false;
return JS_FALSE;
}
return true;
return JS_TRUE;
}
#ifdef _MSC_VER
@ -601,7 +601,7 @@ TokenStream::getXMLEntity()
{
ptrdiff_t offset, length, i;
int c, d;
bool ispair;
JSBool ispair;
jschar *bp, digit;
char *bytes;
JSErrNum msg;
@ -782,7 +782,7 @@ TokenStream::getXMLTextOrTag(TokenKind *ttp, Token **tpp)
tokenbuf.clear();
if (IsXMLNamespaceStart(c)) {
bool sawColon = false;
JSBool sawColon = JS_FALSE;
if (!tokenbuf.append(c))
goto error;
@ -797,7 +797,7 @@ TokenStream::getXMLTextOrTag(TokenKind *ttp, Token **tpp)
reportError(JSMSG_BAD_XML_QNAME);
goto error;
}
sawColon = true;
sawColon = JS_TRUE;
}
if (!tokenbuf.append(c))
@ -2127,13 +2127,13 @@ JS_FRIEND_API(int)
js_fgets(char *buf, int size, FILE *file)
{
int n, i, c;
bool crflag;
JSBool crflag;
n = size - 1;
if (n < 0)
return -1;
crflag = false;
crflag = JS_FALSE;
for (i = 0; i < n && (c = fast_getc(file)) != EOF; i++) {
buf[i] = c;
if (c == '\n') { /* any \n ends a line */

View File

@ -829,7 +829,7 @@ FindKeyword(const jschar *s, size_t length);
* Check that str forms a valid JS identifier name. The function does not
* check if str is a JS keyword.
*/
bool
JSBool
IsIdentifier(JSLinearString *str);
/*

View File

@ -36,8 +36,8 @@
* MarkString, etc. These functions check if an object is in the compartment
* currently being GCed. If it is, they call PushMarkStack. Roots are pushed
* this way as well as pointers traversed inside trace hooks (for things like
* PropertyIteratorObjects). It is always valid to call a MarkX function
* instead of PushMarkStack, although it may be slower.
* IteratorClass). It it always valid to call a MarkX function instead of
* PushMarkStack, although it may be slower.
*
* The MarkX functions also handle non-GC object traversal. In this case, they
* call a callback for each object visited. This is a recursive process; the

View File

@ -106,10 +106,10 @@ class Handle
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
const T *address() const { return ptr; }
T value() const { return *ptr; }
T get() const { return *ptr; }
operator T () const { return value(); }
T operator ->() const { return value(); }
operator T () const { return get(); }
T operator ->() const { return get(); }
private:
Handle() {}
@ -124,6 +124,43 @@ typedef Handle<JSString*> HandleString;
typedef Handle<jsid> HandleId;
typedef Handle<Value> HandleValue;
/*
* Similar to a handle, but the underlying storage can be changed. This is
* useful for outparams.
*/
template <typename T>
class MutableHandle
{
public:
template <typename S>
MutableHandle(MutableHandle<S> handle,
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
{
this->ptr = reinterpret_cast<const T *>(handle.address());
}
template <typename S>
inline
MutableHandle(Rooted<S> *root,
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
void set(T v) { *ptr = v; }
T *address() const { return ptr; }
T get() const { return *ptr; }
operator T () const { return get(); }
T operator ->() const { return get(); }
private:
MutableHandle() {}
T *ptr;
};
typedef MutableHandle<JSObject*> MutableHandleObject;
typedef MutableHandle<Value> MutableHandleValue;
template <typename T>
struct RootMethods<T *>
{
@ -174,8 +211,8 @@ class Rooted
T operator ->() const { return ptr; }
T * address() { return &ptr; }
const T * address() const { return &ptr; }
T & reference() { return ptr; }
T raw() const { return ptr; }
T & get() { return ptr; }
const T & get() const { return ptr; }
T & operator =(T value)
{
@ -209,6 +246,14 @@ Handle<T>::Handle(Rooted<S> &root,
ptr = reinterpret_cast<const T *>(root.address());
}
template<typename T> template <typename S>
inline
MutableHandle<T>::MutableHandle(Rooted<S> *root,
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
{
ptr = root->address();
}
typedef Rooted<JSObject*> RootedObject;
typedef Rooted<JSFunction*> RootedFunction;
typedef Rooted<JSScript*> RootedScript;

View File

@ -1,6 +1,6 @@
// Map(x) throws if x is not iterable (unless x is undefined).
load(libdir + "asserts.js");
var nonIterables = [null, true, 1, -0, 3.14, NaN, {}, Math, this];
var nonIterables = [null, true, 1, -0, 3.14, NaN, "", "xyzzy", {}, Math, this];
for (let k of nonIterables)
assertThrowsInstanceOf(function () { Map(k); }, TypeError);

View File

@ -1,11 +0,0 @@
// for-of can be used to iterate over a Map twice.
var map = Map([['a', 0], ['b', 1], ['c', 2]]);
var log = '';
for (let i = 0; i < 2; i++) {
for (let [k, v] of map)
log += k + v;
log += ';'
}
assertEq(log, 'a0b1c2;a0b1c2;');

View File

@ -1,11 +0,0 @@
// Nested for-of loops can iterate over a Map.
var map = Map([['a', 0], ['b', 1]]);
var log = '';
for (let [k0, v0] of map) {
log += k0 + v0 + ':'
for (let [k1, v1] of map)
log += k1 + v1;
log += ';'
};
assertEq(log, 'a0:a0b1;b1:a0b1;');

View File

@ -1,15 +0,0 @@
// map.iterator() is live: entries added during iteration are visited.
var map = Map();
function force(k) {
if (!map.has(k) && k >= 0)
map.set(k, k - 1);
}
force(5);
var log = '';
for (let [k, v] of map) {
log += k + ';';
force(v);
}
assertEq(log, '5;4;3;2;1;0;');
assertEq(map.size(), 6);

View File

@ -1,11 +0,0 @@
// A Map iterator does not iterate over new entries added after it throws StopIteration.
load(libdir + "asserts.js");
load(libdir + "eqArrayHelper.js");
var map = Map();
var iter0 = map.iterator(), iter1 = map.iterator();
assertThrowsValue(function () { iter0.next(); }, StopIteration); // closes iter0
map.set(1, 2);
assertThrowsValue(function () { iter0.next(); }, StopIteration); // already closed
assertEqArray(iter1.next(), [1, 2]); // was not yet closed

View File

@ -1,14 +0,0 @@
// Removing and re-adding entries while an iterator is live causes the iterator to visit them again.
var map = Map([['a', 1]]);
var n = 5;
for (let [k, v] of map) {
assertEq(k, 'a');
assertEq(v, 1);
if (n === 0)
break;
map.delete('a');
map.set('a', 1);
n--;
}
assertEq(n, 0);

View File

@ -1,15 +0,0 @@
// Map iterators produces entries in the order they were inserted.
load(libdir + "eqArrayHelper.js");
var map = Map();
for (var i = 7; i !== 1; i = i * 7 % 1117)
map.set("" + i, i);
assertEq(map.size(), 557);
i = 7;
for (var pair of map) {
assertEqArray(pair, ["" + i, i]);
i = i * 7 % 1117;
}
assertEq(i, 1);

View File

@ -1,15 +0,0 @@
// mapiter.next() returns an actual array.
var key = {};
var map = Map([[key, 'value']]);
var entry = map.iterator().next();
assertEq(Array.isArray(entry), true);
assertEq(Object.getPrototypeOf(entry), Array.prototype);
assertEq(Object.isExtensible(entry), true);
assertEq(entry.length, 2);
var names = Object.getOwnPropertyNames(entry).sort();
assertEq(names.length, 3);
assertEq(names.join(","), "0,1,length");
assertEq(entry[0], key);
assertEq(entry[1], 'value');

View File

@ -1,10 +0,0 @@
// mapiter.next() returns a fresh array each time.
var map = Map([['a', 1], ['b', 2]]);
var iter = map.iterator();
var a = iter.next(), b = iter.next();
assertEq(a !== b, true);
assertEq(a[0], 'a');
assertEq(b[0], 'b');
var a1 = map.iterator().next();
assertEq(a !== a1, true);

View File

@ -1,12 +0,0 @@
// Modifying an array returned by mapiter.next() does not modify the Map.
var map = Map([['a', 1]]);
var pair = map.iterator().next();
assertEq(pair[0], 'a');
pair[0] = 'b';
pair[1] = 2;
assertEq(pair[0], 'b');
assertEq(pair[1], 2);
assertEq(map.get('a'), 1);
assertEq(map.has('b'), false);
assertEq(map.size(), 1);

View File

@ -1,8 +0,0 @@
// for-of works on a cross-compartment wrapper of a Map.
var g = newGlobal('new-compartment');
var mw = g.eval("Map([['a', 1], ['b', 2]])");
var log = '';
for (let [k, v] of mw)
log += k + v;
assertEq(log, "a1b2");

View File

@ -1,19 +0,0 @@
// map.iterator() and iter.next() are non-generic but work on cross-compartment wrappers.
load(libdir + "asserts.js");
load(libdir + "eqArrayHelper.js");
var g = newGlobal('new-compartment');
var iterator_fn = Map.prototype.iterator;
assertThrowsInstanceOf(function () { iterator_fn.call({}); }, TypeError);
assertThrowsInstanceOf(function () { iterator_fn.call(Set()); }, TypeError);
var mapw = g.eval("Map([['x', 1], ['y', 2]])");
assertEqArray(iterator_fn.call(mapw).next(), ["x", 1]);
var next_fn = Map().iterator().next;
assertThrowsInstanceOf(function () { next_fn.call({}); }, TypeError);
assertThrowsInstanceOf(function () { next_fn.call(Set().iterator()); }, TypeError);
var iterw = mapw.iterator();
assertEqArray(next_fn.call(iterw), ["x", 1]);
assertEqArray(next_fn.call(iterw), ["y", 2]);
assertThrowsValue(function () { next_fn.call(iterw); }, g.StopIteration);

View File

@ -1,40 +0,0 @@
// A map iterator can cope with removing the current entry.
function test(pairs) {
print(uneval(pairs));
var map = Map(pairs);
var all_keys = '';
var false_keys = '';
for (let [k, v] of map) {
all_keys += k;
if (!v)
false_keys += k;
}
var log = '';
for (let [k, remove] of map) {
log += k;
if (remove)
map.delete(k);
}
assertEq(log, all_keys);
var remaining_keys = [k for ([k] of map)].join('');
assertEq(remaining_keys, false_keys);
}
// removing the only entry
test([['a', true]]);
// removing the first entry
test([['a', true], ['b', false], ['c', false]]);
// removing a middle entry
test([['a', false], ['b', true], ['c', false]]);
// removing the last entry
test([['a', false], ['b', false], ['c', true]]);
// removing all entries
test([['a', true], ['b', true], ['c', true]]);

View File

@ -1,11 +0,0 @@
// A map iterator can cope with removing the next entry.
var map = Map([['a', 0], ['b', 1], ['c', 2], ['d', 3]]);
var iter = map.iterator();
var log = '';
for (let [k, v] of iter) {
log += k + v;
if (k === 'b')
map.delete('c');
}
assertEq(log, 'a0b1d3');

View File

@ -1,12 +0,0 @@
// A map iterator can cope with removing the next entry, then the current entry.
load(libdir + "asserts.js");
var map = Map([['a', 0], ['b', 1], ['c', 2], ['d', 3]]);
var iter = map.iterator();
assertEq(iter.next()[0], 'a');
assertEq(iter.next()[0], 'b');
map.delete('c');
map.delete('b');
assertEq(iter.next()[0], 'd');
assertThrowsValue(function () { iter.next(); }, StopIteration);

View File

@ -1,32 +0,0 @@
// Multiple live iterators on the same Map can cope with removing entries.
load(libdir + "eqArrayHelper.js");
load(libdir + "asserts.js");
// Make a map.
var map = Map();
var SIZE = 7;
for (var j = 0; j < SIZE; j++)
map.set(j, j);
// Make lots of iterators pointing to entry 2 of the map.
var NITERS = 5;
var iters = [];
for (var i = 0; i < NITERS; i++) {
var iter = map.iterator();
assertEqArray(iter.next(), [0, 0]);
assertEqArray(iter.next(), [1, 1]);
iters[i] = iter;
}
// Remove half of the map entries.
for (var j = 0; j < SIZE; j += 2)
map.delete(j);
// Make sure all the iterators still work.
for (var i = 0; i < NITERS; i++) {
var iter = iters[i];
for (var j = 3; j < SIZE; j += 2)
assertEqArray(iter.next(), [j, j]);
assertThrowsValue(function () { iter.next(); }, StopIteration);
}

View File

@ -1,22 +0,0 @@
// Removing a Map entry already visited by an iterator does not cause any
// entries to be skipped.
var map = Map();
for (var i = 0; i < 20; i++)
map.set(String.fromCharCode('A'.charCodeAt(0) + i), i);
var log = '';
for (var [k, v] of map) {
log += k;
if (v % 5 === 4) {
// Delete all entries preceding this one.
for (let [k1, v1] of map) {
if (k1 === k)
break;
map.delete(k1);
}
}
}
assertEq(log, 'ABCDEFGHIJKLMNOPQRST');
assertEq(map.size(), 1); // Only the last entry remains.
assertEq(map.get('T'), 19);

View File

@ -1,20 +0,0 @@
// Removing many Map entries does not cause a live iterator to skip any of the
// entries that were not removed. (Compacting a Map must not be observable to
// script.)
load(libdir + "asserts.js");
var map = Map();
for (var i = 0; i < 32; i++)
map.set(i, i);
var iter = map.iterator();
assertEq(iter.next()[0], 0);
for (var i = 0; i < 30; i++)
map.delete(i);
assertEq(map.size(), 2);
for (var i = 32; i < 100; i++)
map.set(i, i); // eventually triggers compaction
for (var i = 30; i < 100; i++)
assertEq(iter.next()[0], i);
assertThrowsValue(function () { iter.next(); }, StopIteration);

View File

@ -1,11 +0,0 @@
// for-of can be used to iterate over a Set twice.
var set = Set(['a', 'b', 'c']);
var log = '';
for (let i = 0; i < 2; i++) {
for (let x of set)
log += x;
log += ';'
}
assertEq(log, 'abc;abc;');

View File

@ -1,11 +0,0 @@
// Nested for-of loops can iterate over a Set.
var map = Set(['a', 'b']);
var log = '';
for (let x of map) {
log += x + ':'
for (let y of map)
log += y;
log += ';'
};
assertEq(log, 'a:ab;b:ab;');

View File

@ -1,11 +0,0 @@
// Iterating over a set of objects yields those exact objects.
var arr = [{}, {}, {}, [], /xyz/, new Date];
var set = Set(arr);
assertEq(set.size(), arr.length);
var i = 0;
for (var x of set)
assertEq(x, arr[i++]);
assertEq(i, arr.length);

View File

@ -1,11 +0,0 @@
// set.iterator() is live: entries added during iteration are visited.
var set = Set([5]);
var log = '';
for (let x of set) {
log += x + ';';
if (x > 0)
set.add(x - 1);
}
assertEq(log, '5;4;3;2;1;0;');
assertEq(set.size(), 6);

View File

@ -1,10 +0,0 @@
// A Set iterator does not iterate over new entries added after it throws StopIteration.
load(libdir + "asserts.js");
var set = Set();
var iter0 = set.iterator(), iter1 = set.iterator();
assertThrowsValue(function () { iter0.next(); }, StopIteration); // closes iter0
set.add("x");
assertThrowsValue(function () { iter0.next(); }, StopIteration); // already closed
assertEq(iter1.next(), "x"); // was not yet closed

View File

@ -1,13 +0,0 @@
// Removing and re-adding entries while an iterator is live causes the iterator to visit them again.
var set = Set(['a']);
var n = 5;
for (let v of set) {
assertEq(v, 'a');
if (n === 0)
break;
set.delete('a');
set.add('a');
n--;
}
assertEq(n, 0);

View File

@ -1,8 +0,0 @@
// A Set iterator keeps the data alive.
load(libdir + "referencesVia.js");
var key = {};
var set = Set([key]);
var iter = set.iterator();
referencesVia(iter, "**UNKNOWN SLOT 0**", set);
referencesVia(set, "key", key);

View File

@ -1,8 +0,0 @@
// GC-ing during a for-of loop doesn't crash.
var i = 0;
for (var x of Set(Object.getOwnPropertyNames(this))) {
gc();
if (++i >= 20)
break;
}

View File

@ -1,20 +0,0 @@
// GC in nested for-loops is safe.
var x;
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
for (x of Set([1]))
gc();

View File

@ -1,14 +0,0 @@
// Set iterators produces entries in the order they were inserted.
var set = Set();
var i;
for (i = 7; i !== 1; i = i * 7 % 1117)
set.add(i);
assertEq(set.size(), 557);
i = 7;
for (var v of set) {
assertEq(v, i);
i = i * 7 % 1117;
}
assertEq(i, 1);

View File

@ -1,8 +0,0 @@
// for-of works on a cross-compartment wrapper of a Set.
var g = newGlobal('new-compartment');
var mw = g.eval("Set(['a', 'b', 1, 2])");
var log = '';
for (let x of mw)
log += x;
assertEq(log, "ab12");

View File

@ -1,18 +0,0 @@
// map.iterator() and iter.next() are non-generic but work on cross-compartment wrappers.
load(libdir + "asserts.js");
var g = newGlobal('new-compartment');
var iterator_fn = Set.prototype.iterator;
assertThrowsInstanceOf(function () { iterator_fn.call({}); }, TypeError);
assertThrowsInstanceOf(function () { iterator_fn.call(Map()); }, TypeError);
var setw = g.eval("Set(['x', 'y'])");
assertEq(iterator_fn.call(setw).next(), "x");
var next_fn = Set().iterator().next;
assertThrowsInstanceOf(function () { next_fn.call({}); }, TypeError);
assertThrowsInstanceOf(function () { next_fn.call(Map().iterator()); }, TypeError);
var iterw = setw.iterator();
assertEq(next_fn.call(iterw), "x");
assertEq(next_fn.call(iterw), "y");
assertThrowsValue(function () { next_fn.call(iterw); }, g.StopIteration);

View File

@ -1,26 +0,0 @@
// A set iterator can cope with removing the current entry.
function test(letters, toRemove) {
var set = Set(letters);
toRemove = Set(toRemove);
var leftovers = [x for (x of set) if (!toRemove.has(x))].join("");
var log = "";
for (let x of set) {
log += x;
if (toRemove.has(x))
set.delete(x);
}
assertEq(log, letters);
var remaining = [x for (x of set)].join("");
assertEq(remaining, leftovers);
}
test('a', 'a'); // removing the only entry
test('abc', 'a'); // removing the first entry
test('abc', 'b'); // removing a middle entry
test('abc', 'c'); // removing the last entry
test('abc', 'abc') // removing all entries

View File

@ -1,11 +0,0 @@
// A map iterator can cope with removing the next entry.
var set = Set("abcd");
var iter = set.iterator();
var log = "";
for (let x of iter) {
log += x;
if (x === "b")
set.delete("c");
}
assertEq(log, "abd");

View File

@ -1,12 +0,0 @@
// A set iterator can cope with removing the next entry, then the current entry.
load(libdir + "asserts.js");
var set = Set("abcd");
var iter = set.iterator();
assertEq(iter.next(), "a");
assertEq(iter.next(), "b");
set.delete("c");
set.delete("b");
assertEq(iter.next(), "d");
assertThrowsValue(function () { iter.next(); }, StopIteration);

View File

@ -1,31 +0,0 @@
// Multiple live iterators on the same Set can cope with removing entries.
load(libdir + "asserts.js");
// Make a set.
var set = Set();
var SIZE = 7;
for (var j = 0; j < SIZE; j++)
set.add(j);
// Make lots of iterators pointing to entry 2 of the set.
var NITERS = 5;
var iters = [];
for (var i = 0; i < NITERS; i++) {
var iter = set.iterator();
assertEq(iter.next(), 0);
assertEq(iter.next(), 1);
iters[i] = iter;
}
// Remove half of the set entries.
for (var j = 0; j < SIZE; j += 2)
set.delete(j);
// Make sure all the iterators still work.
for (var i = 0; i < NITERS; i++) {
var iter = iters[i];
for (var j = 3; j < SIZE; j += 2)
assertEq(iter.next(), j);
assertThrowsValue(function () { iter.next(); }, StopIteration);
}

View File

@ -1,22 +0,0 @@
// Removing a Set entry already visited by an iterator does not cause any
// entries to be skipped.
var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var set = Set(str);
var log = '';
var i = 0;
for (var x of set) {
log += x;
if (i++ % 5 === 0) {
// Delete all entries preceding this one.
for (let y of set) {
if (y === x)
break;
set.delete(y);
}
}
}
assertEq(log, str);
assertEq(set.size(), 1); // Elements 0 to 24 are removed, leaving only 25 (Z).
assertEq(set.has('Z'), true);

View File

@ -1,20 +0,0 @@
// Removing many Set entries does not cause a live iterator to skip any of the
// entries that were not removed. (Compacting a Set must not be observable to
// script.)
load(libdir + "asserts.js");
var set = Set();
for (var i = 0; i < 32; i++)
set.add(i);
var iter = set.iterator();
assertEq(iter.next(), 0);
for (var i = 0; i < 30; i++)
set.delete(i);
assertEq(set.size(), 2);
for (var i = 32; i < 100; i++)
set.add(i); // eventually triggers compaction
for (var i = 30; i < 100; i++)
assertEq(iter.next(), i);
assertThrowsValue(function () { iter.next(); }, StopIteration);

View File

@ -1,12 +0,0 @@
// collection.iterator() returns an Iterator object.
function test(obj) {
var iter = obj.iterator();
assertEq(typeof iter, "object");
assertEq(iter instanceof Iterator, true);
assertEq(iter.toString(), "[object Iterator]");
}
test([]);
test(new Map);
test(new Set);

View File

@ -1,12 +0,0 @@
// for-of on an empty collection does not execute the loop body or modify the loop variable.
function test(empty) {
var x = 'unchanged';
for (x of empty)
throw fit;
assertEq(x, 'unchanged');
}
test([]);
test(new Map);
test(new Set);

View File

@ -1,14 +0,0 @@
// An iterator keeps its data alive.
load(libdir + "referencesVia.js");
var key = {};
function test(obj, edgeName) {
var iter = obj.iterator();
referencesVia(iter, "**UNKNOWN SLOT 0**", obj);
referencesVia(obj, edgeName, key);
}
test([key], "element[0]");
test(Map([[key, 'value']]), "key");
test(Set([key]), "key");

View File

@ -1,13 +0,0 @@
// All iterators of the same collection type share their immediate prototype.
// Those prototype objects in turn inherit directly from Iterator.prototype.
function test(obj0, obj1) {
var iter0 = obj0.iterator(), iter1 = obj1.iterator();
var proto = Object.getPrototypeOf(iter0);
assertEq(Object.getPrototypeOf(iter1), proto);
assertEq(Object.getPrototypeOf(proto), Iterator.prototype);
}
test([], [1]);
test(Map(), Map([[1, 1]]));
test(Set(), Set([1]));

View File

@ -1,11 +0,0 @@
// Iterators of different collection types have different prototypes.
var aproto = Object.getPrototypeOf(Array().iterator());
var mproto = Object.getPrototypeOf(Map().iterator());
var sproto = Object.getPrototypeOf(Set().iterator());
assertEq(aproto !== mproto, true);
assertEq(aproto !== sproto, true);
assertEq(mproto !== sproto, true);
assertEq(aproto.next !== mproto.next, true);
assertEq(aproto.next !== sproto.next, true);
assertEq(mproto.next !== sproto.next, true);

View File

@ -1,22 +0,0 @@
// Iterator prototype surfaces.
load(libdir + "asserts.js");
function test(constructor) {
var proto = Object.getPrototypeOf(constructor().iterator());
var names = Object.getOwnPropertyNames(proto);
assertEq(names.length, 1);
assertEq(names[0], 'next');
var desc = Object.getOwnPropertyDescriptor(proto, 'next');
assertEq(desc.configurable, true);
assertEq(desc.enumerable, false);
assertEq(desc.writable, true);
assertEq(proto.iterator(), proto);
assertThrowsValue(function () { proto.next(); }, StopIteration);
}
//test(Array);
test(Map);
test(Set);

View File

@ -1,9 +1,5 @@
// for-of can iterate arguments objects.
// Arguments objects do not have a .iterator() method by default.
// Install one on Object.prototype.
Object.prototype.iterator = Array.prototype.iterator;
var s;
function test() {
for (var v of arguments)

View File

@ -6,7 +6,6 @@ function f() {
var s = '';
var args = f('a', 'b', 'c');
Object.prototype.iterator = Array.prototype.iterator;
for (var v of args)
s += v;
assertEq(s, 'abc');

View File

@ -1,7 +1,5 @@
// for-of can iterate strict arguments objects.
Object.prototype.iterator = Array.prototype.iterator;
var s;
function test() {
"use strict";

View File

@ -1,7 +1,5 @@
// for-of can iterate arguments objects for other active frames.
Object.prototype.iterator = Array.prototype.iterator;
var s;
function g(obj) {
for (var v of obj)

View File

@ -1,7 +1,5 @@
// for-of can iterate strict arguments objects in non-strict code.
Object.prototype.iterator = Array.prototype.iterator;
var s;
function g(obj) {
for (var v of obj)

View File

@ -1,7 +1,5 @@
// Changing arguments.length affects a for-of loop iterating over arguments.
Object.prototype.iterator = Array.prototype.iterator;
var s;
function f() {
arguments.length = 2;

View File

@ -1,7 +1,5 @@
// Changing arguments.length during a for-of loop iterating over arguments affects the loop.
Object.prototype.iterator = Array.prototype.iterator;
var s;
function f() {
for (var v of arguments) {

View File

@ -4,7 +4,6 @@ var m = {1: 'peek'};
var a = [0, , 2, 3];
a.__proto__ = m;
var log = [];
Object.prototype.iterator = Array.prototype.iterator;
for (var x of a)
log.push(x);
assertEq(log[1], 'peek');

View File

@ -1,11 +0,0 @@
// Array iterators reflect changes to elements of the underlying array.
load(libdir + "asserts.js");
var arr = [0, 1, 2];
var it = arr.iterator();
arr[0] = 1000;
arr[2] = 2000;
assertEq(it.next(), 1000);
assertEq(it.next(), 1);
assertEq(it.next(), 2000);
assertThrowsValue(function () { it.next(); }, StopIteration);

View File

@ -1,12 +0,0 @@
// Array iterators keep the underlying array, arraylike object, or string alive.
load(libdir + "referencesVia.js");
function test(obj) {
var it = Array.prototype.iterator.call(obj);
assertEq(referencesVia(it, "**UNKNOWN SLOT 0**", obj), true);
}
test([]);
test([1, 2, 3, 4]);
test({});

View File

@ -1,27 +0,0 @@
// Array.prototype.iterator is generic.
// That is, it can be applied to arraylike objects and strings, not just arrays.
load(libdir + "asserts.js");
function test(obj) {
var it = Array.prototype.iterator.call(obj);
for (var i = 0; i < (obj.length >>> 0); i++)
assertEq(it.next(), obj[i]);
assertThrowsValue(function () { it.next(); }, StopIteration);
}
test({length: 0});
test({length: 0, 0: 'x', 1: 'y'});
test({length: 2, 0: 'x', 1: 'y'});
test(Object.create(['x', 'y', 'z']));
test(Object.create({length: 2, 0: 'x', 1: 'y'}));
test("");
test("ponies");
// Perverse length values.
test({length: 0x1f00000000});
test({length: -0xfffffffe, 0: 'a', 1: 'b'});
test({length: "011", 9: 9, 10: 10, 11: 11});
test({length: -0});
test({length: 2.7, 0: 0, 1: 1, 2: 2});
test({length: {valueOf: function () { return 3; }}, 0: 0, 1: 1, 2: 2});

View File

@ -1,12 +0,0 @@
// If an array with an active iterator is lengthened, the iterator visits the new elements.
load(libdir + "asserts.js");
var arr = [0, 1];
var it = arr.iterator();
it.next();
it.next();
arr[2] = 2;
arr.length = 4;
assertEq(it.next(), 2);
assertEq(it.next(), undefined);
assertThrowsValue(function () { it.next(); }, StopIteration);

View File

@ -1,9 +0,0 @@
// Array.prototype.iterator applied to undefined or null does not throw (until .next is called).
load(libdir + "asserts.js");
for (var v of [undefined, null]) {
var it = Array.prototype.iterator.call(v);
// This will throw because the iterator is trying to get v.length.
assertThrowsInstanceOf(function () { it.next(); }, TypeError);
}

View File

@ -1,23 +0,0 @@
// An array iterator for a proxy calls the traps in a predictable order.
load(libdir + "asserts.js");
var s = '';
var it = Array.prototype.iterator.call(Proxy.create({
get: function (recipient, name) {
if (name == 'length') {
s += 'L';
return 2;
} else {
s += name;
return name;
}
}
}));
assertEq(it.next(), "0");
s += ' ';
assertEq(it.next(), "1");
s += ' ';
assertThrowsValue(function () { it.next(); }, StopIteration);
assertEq(s, "L0 L1 L");

View File

@ -1,9 +0,0 @@
// If an array is truncated to the left of an iterator it, it.next() throws StopIteration.
load(libdir + "asserts.js");
var arr = [0, 1, 2];
var it = arr.iterator();
it.next();
it.next();
arr.length = 1;
assertThrowsValue(function () { it.next(); }, StopIteration);

View File

@ -1,10 +0,0 @@
// Superficial tests of the Array.prototype.iterator builtin function and its workalikes.
var constructors = [Array, String, Uint8Array, Uint8ClampedArray];
for (var c of constructors) {
assertEq(c.prototype.iterator.length, 0);
var desc = Object.getOwnPropertyDescriptor(c.prototype, "iterator");
assertEq(desc.configurable, true);
assertEq(desc.enumerable, false);
assertEq(desc.writable, true);
}

View File

@ -1,22 +0,0 @@
// Superficial tests for iterators created by Array.prototype.iterator
var proto = Object.getPrototypeOf([].iterator());
assertEq(Object.getPrototypeOf(proto), Iterator.prototype);
function check(it) {
assertEq(typeof it, 'object');
assertEq(Object.getPrototypeOf(it), proto);
assertEq(Object.getOwnPropertyNames(it).length, 0);
assertEq(it.iterator(), it);
// for-in enumerates the iterator's properties.
it.x = 0;
var s = '';
for (var p in it)
s += p + '.';
assertEq(s, 'x.');
}
check([].iterator());
check(Array.prototype.iterator.call({}));
check(Array.prototype.iterator.call(undefined));

View File

@ -1,17 +0,0 @@
// for-of works on CData objects of array type, but throws for other CData objects.
if (this.ctypes) {
load(libdir + "asserts.js");
var v = ctypes.int32_t(17);
assertThrowsInstanceOf(function () { for (var x of v) ; }, TypeError);
var intarray_t = ctypes.int32_t.array();
var a = new intarray_t([0, 1, 1, 2, 3]);
var b = [x for (x of a)];
assertEq(b.join(), '0,1,1,2,3');
var it = a.iterator();
assertEq(it.next(), 0);
a[1] = -100;
assertEq(it.next(), -100);
}

Some files were not shown because too many files have changed in this diff Show More