mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central into mozilla-inbound
This commit is contained in:
commit
6e5624f985
@ -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");
|
||||
|
||||
|
@ -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 \
|
||||
|
93
browser/base/content/test/browser_bug767836.js
Normal file
93
browser/base/content/test/browser_bug767836.js
Normal 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);
|
||||
}
|
@ -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 \
|
||||
|
54
browser/base/content/test/newtab/browser_newtab_focus.js
Normal file
54
browser/base/content/test/newtab/browser_newtab_focus.js
Normal 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();
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -63,8 +63,6 @@ _TEST_FILES = \
|
||||
test_lookupGetter.html \
|
||||
test_InstanceOf.html \
|
||||
test_traceProtos.html \
|
||||
test_forOf.html \
|
||||
forOf_iframe.html \
|
||||
$(NULL)
|
||||
|
||||
|
||||
|
@ -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>
|
@ -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>
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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))
|
||||
|
@ -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 {
|
||||
|
@ -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
@ -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 */
|
||||
|
@ -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
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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();
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;');
|
@ -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;');
|
@ -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);
|
@ -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
|
@ -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);
|
@ -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);
|
@ -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');
|
@ -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);
|
@ -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);
|
@ -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");
|
@ -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);
|
@ -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]]);
|
@ -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');
|
@ -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);
|
@ -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);
|
||||
}
|
@ -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);
|
@ -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);
|
@ -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;');
|
@ -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;');
|
@ -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);
|
||||
|
@ -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);
|
@ -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
|
@ -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);
|
@ -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);
|
@ -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;
|
||||
}
|
@ -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();
|
@ -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);
|
@ -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");
|
@ -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);
|
@ -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
|
||||
|
@ -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");
|
@ -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);
|
@ -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);
|
||||
}
|
@ -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);
|
@ -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);
|
@ -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);
|
@ -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);
|
@ -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");
|
@ -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]));
|
@ -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);
|
@ -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);
|
@ -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)
|
||||
|
@ -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');
|
||||
|
@ -1,7 +1,5 @@
|
||||
// for-of can iterate strict arguments objects.
|
||||
|
||||
Object.prototype.iterator = Array.prototype.iterator;
|
||||
|
||||
var s;
|
||||
function test() {
|
||||
"use strict";
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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');
|
||||
|
@ -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);
|
@ -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({});
|
@ -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});
|
@ -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);
|
@ -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);
|
||||
}
|
@ -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");
|
@ -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);
|
@ -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);
|
||||
}
|
@ -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));
|
@ -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
Loading…
Reference in New Issue
Block a user