Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2014-01-30 12:31:53 +01:00
commit ee3229a280
178 changed files with 4014 additions and 1684 deletions

1
.clang-format Normal file
View File

@ -0,0 +1 @@
BasedOnStyle: Mozilla

View File

@ -1,2 +1,3 @@
\mfbt/
\js/
\media/

View File

@ -1917,8 +1917,10 @@ DocAccessible::UpdateTreeInternal(Accessible* aChild, bool aIsInsert,
// XXX: do we really want to send focus to focused DOM node not taking into
// account active item?
if (focusedAcc)
if (focusedAcc) {
FocusMgr()->DispatchFocusEvent(this, focusedAcc);
SelectionMgr()->SetControlSelectionListener(focusedAcc->GetNode()->AsElement());
}
return updateFlags;
}

View File

@ -57,6 +57,7 @@ this.EventManager.prototype = {
this.webProgress.addProgressListener(this,
(Ci.nsIWebProgress.NOTIFY_STATE_ALL |
Ci.nsIWebProgress.NOTIFY_LOCATION));
this.addEventListener('wheel', this, true);
this.addEventListener('scroll', this, true);
this.addEventListener('resize', this, true);
}
@ -77,6 +78,7 @@ this.EventManager.prototype = {
AccessibilityEventObserver.removeListener(this);
try {
this.webProgress.removeProgressListener(this);
this.removeEventListener('wheel', this, true);
this.removeEventListener('scroll', this, true);
this.removeEventListener('resize', this, true);
} catch (x) {
@ -89,6 +91,23 @@ this.EventManager.prototype = {
handleEvent: function handleEvent(aEvent) {
try {
switch (aEvent.type) {
case 'wheel':
{
let attempts = 0;
let vc = Utils.getVirtualCursor(this.contentScope.content.document);
let intervalId = this.contentScope.content.setInterval(() => {
if (!Utils.isAliveAndVisible(vc.position, true)) {
this.contentScope.content.clearInterval(intervalId);
let delta = aEvent.deltaX || aEvent.deltaY;
this.contentScope.content.setTimeout(() => {
vc[delta > 0 ? 'moveNext' : 'movePrevious'](TraversalRules.SimpleOnScreen);
}, 100);
} else if (++attempts > 5) {
this.contentScope.content.clearInterval(intervalId);
}
}, 150);
break;
}
case 'scroll':
case 'resize':
{
@ -255,11 +274,20 @@ this.EventManager.prototype = {
let acc = aEvent.accessible;
let doc = aEvent.accessibleDocument;
if (acc.role != Roles.DOCUMENT && doc.role != Roles.CHROME_WINDOW) {
this.contentScope.content.clearTimeout(this._autoMove);
let vc = Utils.getVirtualCursor(doc);
vc.moveNext(TraversalRules.Simple, acc, true);
}
break;
}
case Events.DOCUMENT_LOAD_COMPLETE:
{
this._autoMove = this.contentScope.content.setTimeout(() => {
Utils.getVirtualCursor(aEvent.accessibleDocument)
.moveNext(TraversalRules.Simple, aEvent.accessible, true);
}, 500);
break;
}
}
},

View File

@ -318,7 +318,8 @@ this.OutputGenerator = {
'image map': INCLUDE_DESC,
'option': INCLUDE_DESC,
'listbox': INCLUDE_DESC,
'definitionlist': INCLUDE_DESC | INCLUDE_NAME},
'definitionlist': INCLUDE_DESC | INCLUDE_NAME,
'dialog': INCLUDE_DESC | INCLUDE_NAME },
objectOutputFunctions: {
_generateBaseOutput: function _generateBaseOutput(aAccessible, aRoleStr, aState, aFlags) {

View File

@ -22,13 +22,14 @@ XPCOMUtils.defineLazyModuleGetter(this, 'States',
let gSkipEmptyImages = new PrefCache('accessibility.accessfu.skip_empty_images');
function BaseTraversalRule(aRoles, aMatchFunc) {
function BaseTraversalRule(aRoles, aMatchFunc, aPreFilter) {
this._explicitMatchRoles = new Set(aRoles);
this._matchRoles = aRoles;
if (aRoles.indexOf(Roles.LABEL) < 0) {
this._matchRoles.push(Roles.LABEL);
}
this._matchFunc = aMatchFunc || function (acc) { return Filters.MATCH; };
this.preFilter = aPreFilter || gSimplePreFilter;
}
BaseTraversalRule.prototype = {
@ -37,11 +38,6 @@ BaseTraversalRule.prototype = {
return aRules.value.length;
},
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE |
Ci.nsIAccessibleTraversalRule.PREFILTER_ARIA_HIDDEN |
Ci.nsIAccessibleTraversalRule.PREFILTER_TRANSPARENT,
match: function BaseTraversalRule_match(aAccessible)
{
let role = aAccessible.role;
@ -96,59 +92,71 @@ var gSimpleTraversalRoles =
// Used for traversing in to child OOP frames.
Roles.INTERNAL_FRAME];
this.TraversalRules = {
Simple: new BaseTraversalRule(
gSimpleTraversalRoles,
function Simple_match(aAccessible) {
function hasZeroOrSingleChildDescendants () {
for (let acc = aAccessible; acc.childCount > 0; acc = acc.firstChild) {
if (acc.childCount > 1) {
return false;
}
}
return true;
}
switch (aAccessible.role) {
case Roles.COMBOBOX:
// We don't want to ignore the subtree because this is often
// where the list box hangs out.
return Filters.MATCH;
case Roles.TEXT_LEAF:
{
// Nameless text leaves are boring, skip them.
let name = aAccessible.name;
if (name && name.trim())
return Filters.MATCH;
else
return Filters.IGNORE;
}
case Roles.STATICTEXT:
{
let parent = aAccessible.parent;
// Ignore prefix static text in list items. They are typically bullets or numbers.
if (parent.childCount > 1 && aAccessible.indexInParent == 0 &&
parent.role == Roles.LISTITEM)
return Filters.IGNORE;
return Filters.MATCH;
}
case Roles.GRAPHIC:
return TraversalRules._shouldSkipImage(aAccessible);
case Roles.LINK:
case Roles.HEADER:
case Roles.HEADING:
return hasZeroOrSingleChildDescendants() ?
(Filters.MATCH | Filters.IGNORE_SUBTREE) : (Filters.IGNORE);
default:
// Ignore the subtree, if there is one. So that we don't land on
// the same content that was already presented by its parent.
return Filters.MATCH |
Filters.IGNORE_SUBTREE;
var gSimpleMatchFunc = function gSimpleMatchFunc(aAccessible) {
function hasZeroOrSingleChildDescendants () {
for (let acc = aAccessible; acc.childCount > 0; acc = acc.firstChild) {
if (acc.childCount > 1) {
return false;
}
}
),
return true;
}
switch (aAccessible.role) {
case Roles.COMBOBOX:
// We don't want to ignore the subtree because this is often
// where the list box hangs out.
return Filters.MATCH;
case Roles.TEXT_LEAF:
{
// Nameless text leaves are boring, skip them.
let name = aAccessible.name;
if (name && name.trim())
return Filters.MATCH;
else
return Filters.IGNORE;
}
case Roles.STATICTEXT:
{
let parent = aAccessible.parent;
// Ignore prefix static text in list items. They are typically bullets or numbers.
if (parent.childCount > 1 && aAccessible.indexInParent == 0 &&
parent.role == Roles.LISTITEM)
return Filters.IGNORE;
return Filters.MATCH;
}
case Roles.GRAPHIC:
return TraversalRules._shouldSkipImage(aAccessible);
case Roles.LINK:
case Roles.HEADER:
case Roles.HEADING:
return hasZeroOrSingleChildDescendants() ?
(Filters.MATCH | Filters.IGNORE_SUBTREE) : (Filters.IGNORE);
default:
// Ignore the subtree, if there is one. So that we don't land on
// the same content that was already presented by its parent.
return Filters.MATCH |
Filters.IGNORE_SUBTREE;
}
};
var gSimplePreFilter = Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE |
Ci.nsIAccessibleTraversalRule.PREFILTER_ARIA_HIDDEN |
Ci.nsIAccessibleTraversalRule.PREFILTER_TRANSPARENT;
this.TraversalRules = {
Simple: new BaseTraversalRule(gSimpleTraversalRoles, gSimpleMatchFunc),
SimpleOnScreen: new BaseTraversalRule(
gSimpleTraversalRoles, gSimpleMatchFunc,
Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE |
Ci.nsIAccessibleTraversalRule.PREFILTER_ARIA_HIDDEN |
Ci.nsIAccessibleTraversalRule.PREFILTER_TRANSPARENT |
Ci.nsIAccessibleTraversalRule.PREFILTER_OFFSCREEN),
Anchor: new BaseTraversalRule(
[Roles.LINK],

View File

@ -269,7 +269,7 @@ this.Utils = {
return false;
},
isAliveAndVisible: function isAliveAndVisible(aAccessible) {
isAliveAndVisible: function isAliveAndVisible(aAccessible, aIsOnScreen) {
if (!aAccessible) {
return false;
}
@ -277,6 +277,7 @@ this.Utils = {
try {
let state = this.getState(aAccessible);
if (state.contains(States.DEFUNCT) || state.contains(States.INVISIBLE) ||
(aIsOnScreen && state.contains(States.OFFSCREEN)) ||
Utils.inHiddenSubtree(aAccessible)) {
return false;
}

View File

@ -230,6 +230,8 @@ function init() {
if (user) {
show("stage");
show("manage");
let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
document.title = sb.GetStringFromName("manage.pageTitle");
} else {
show("stage");
show("intro");

View File

@ -15,7 +15,7 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>&syncBrand.fxa-plural.label;</title>
<title>&aboutAccounts.pageTitle;</title>
<meta name="viewport" content="width=device-width"/>
@ -55,9 +55,7 @@
<div id="intro">
<header>
<h1>&syncBrand.fxa-plural.label;</h1>
<h2>&syncBrand.shortName.label;</h2>
<h1>&aboutAccounts.pageTitle;</h1>
</header>
<section>

View File

@ -11,52 +11,11 @@
#endif
oncommand="MultiplexHandler(event)"
#ifdef OMIT_ACCESSKEYS
#expand onpopupshowing="CharsetMenu.build(event, '__ID_PREFIX__', false);"
#expand onpopupshowing="CharsetMenu.build(event.target, '__ID_PREFIX__', false);"
#else
#expand onpopupshowing="CharsetMenu.build(event, '__ID_PREFIX__');"
#expand onpopupshowing="CharsetMenu.build(event.target, '__ID_PREFIX__');"
#endif
onpopupshown="UpdateMenus(event);">
<menupopup>
<menu label="&charsetMenuAutodet.label;"
#ifndef OMIT_ACCESSKEYS
accesskey="&charsetMenuAutodet.accesskey;"
#endif
>
<menupopup>
<menuitem type="radio"
name="detectorGroup"
#expand id="__ID_PREFIX__chardet.off"
label="&charsetMenuAutodet.off.label;"
#ifndef OMIT_ACCESSKEYS
accesskey="&charsetMenuAutodet.off.accesskey;"
#endif
/>
<menuitem type="radio"
name="detectorGroup"
#expand id="__ID_PREFIX__chardet.ja_parallel_state_machine"
label="&charsetMenuAutodet.ja.label;"
#ifndef OMIT_ACCESSKEYS
accesskey="&charsetMenuAutodet.ja.accesskey;"
#endif
/>
<menuitem type="radio"
name="detectorGroup"
#expand id="__ID_PREFIX__chardet.ruprob"
label="&charsetMenuAutodet.ru.label;"
#ifndef OMIT_ACCESSKEYS
accesskey="&charsetMenuAutodet.ru.accesskey;"
#endif
/>
<menuitem type="radio"
name="detectorGroup"
#expand id="__ID_PREFIX__chardet.ukprob"
label="&charsetMenuAutodet.uk.label;"
#ifndef OMIT_ACCESSKEYS
accesskey="&charsetMenuAutodet.uk.accesskey;"
#endif
/>
</menupopup>
</menu>
<menuseparator/>
</menupopup>
</menu>

View File

@ -6,6 +6,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
"resource://gre/modules/FxAccounts.jsm");
registerCleanupFunction(function() {
// Ensure we don't pollute prefs for next tests.
@ -47,7 +49,7 @@ let gTests = [
ok(false, "Failed to get all commands");
deferred.reject();
}
return deferred.promise;
return deferred.promise.then(() => fxAccounts.signOut());
}
},
@ -74,18 +76,19 @@ function test()
});
}
function promiseNewTabLoadEvent(aUrl, aEventType="load")
function promiseNewTabLoadEvent(aUrl)
{
let deferred = Promise.defer();
let tab = gBrowser.selectedTab = gBrowser.addTab(aUrl);
tab.linkedBrowser.addEventListener(aEventType, function load(event) {
tab.linkedBrowser.removeEventListener(aEventType, load, true);
let iframe = tab.linkedBrowser.contentDocument.getElementById("remote");
iframe.addEventListener("load", function frameLoad(e) {
iframe.removeEventListener("load", frameLoad, false);
deferred.resolve();
}, false);
}, true);
let browser = tab.linkedBrowser;
browser.addEventListener("load", function onLoad(event) {
let iframe = browser.contentDocument.getElementById("remote");
if (iframe && event.target == iframe.contentDocument) {
browser.removeEventListener("load", onLoad, true);
deferred.resolve();
}
}, true);
return deferred.promise;
}

View File

@ -35,4 +35,4 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'):
DEFINES['MENUBAR_CAN_AUTOHIDE'] = 1
JAR_MANIFESTS += ['jar.mn']
JAR_MANIFESTS += ['jar.mn']

View File

@ -18,7 +18,14 @@
</hbox>
<vbox id="customization-palette" class="customization-palette" flex="1"/>
<spacer id="customization-spacer" flex="1"/>
<hbox>
<hbox id="customization-footer">
#ifdef CAN_DRAW_IN_TITLEBAR
<button id="customization-titlebar-visibility-button" class="customizationmode-button"
label="&customizeMode.titlebar;" type="checkbox"
#NB: because oncommand fires after click, by the time we've fired, the checkbox binding
# will already have switched the button's state, so this is correct:
oncommand="gCustomizeMode.toggleTitlebar(this.hasAttribute('checked'))"/>
#endif
<button id="customization-toolbar-visibility-button" label="&customizeMode.toolbars;" class="customizationmode-button" type="menu">
<menupopup id="customization-toolbar-menu" onpopupshowing="onViewToolbarsPopupShowing(event)"/>
</button>

View File

@ -150,7 +150,7 @@
<vbox id="PanelUI-characterEncodingView-customlist"
class="PanelUI-characterEncodingView-list"/>
<vbox>
<label value="&charsetMenuAutodet.label;"/>
<label id="PanelUI-characterEncodingView-autodetect-label"/>
<vbox id="PanelUI-characterEncodingView-autodetect"
class="PanelUI-characterEncodingView-list"/>
</vbox>

View File

@ -16,9 +16,16 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUIUtils",
"resource:///modules/PlacesUIUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RecentlyClosedTabsAndWindowsMenuUtils",
"resource:///modules/sessionstore/RecentlyClosedTabsAndWindowsMenuUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
"resource://gre/modules/ShortcutUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "CharsetManager",
"@mozilla.org/charset-converter-manager;1",
"nsICharsetConverterManager");
XPCOMUtils.defineLazyGetter(this, "CharsetBundle", function() {
const kCharsetBundle = "chrome://global/locale/charsetMenu.properties";
return Services.strings.createBundle(kCharsetBundle);
});
XPCOMUtils.defineLazyGetter(this, "BrandBundle", function() {
const kBrandBundle = "chrome://branding/locale/brand.properties";
return Services.strings.createBundle(kBrandBundle);
@ -32,13 +39,26 @@ let gModuleName = "[CustomizableWidgets]";
#include logging.js
function setAttributes(aNode, aAttrs) {
let doc = aNode.ownerDocument;
for (let [name, value] of Iterator(aAttrs)) {
if (!value) {
if (aNode.hasAttribute(name))
aNode.removeAttribute(name);
} else {
if (name == "label" || name == "tooltiptext")
value = CustomizableUI.getLocalizedProperty({id: aAttrs.id}, name);
if (name == "shortcutId") {
continue;
}
if (name == "label" || name == "tooltiptext") {
let stringId = (typeof value == "string") ? value : name;
let additionalArgs = [];
if (aAttrs.shortcutId) {
let shortcut = doc.getElementById(aAttrs.shortcutId);
if (doc) {
additionalArgs.push(ShortcutUtils.prettifyShortcut(shortcut));
}
}
value = CustomizableUI.getLocalizedProperty({id: aAttrs.id}, stringId, additionalArgs);
}
aNode.setAttribute(name, value);
}
}
@ -63,6 +83,7 @@ const CustomizableWidgets = [{
type: "view",
viewId: "PanelUI-history",
shortcutId: "key_gotoHistory",
tooltiptext: "history-panelmenu.tooltiptext2",
defaultArea: CustomizableUI.AREA_PANEL,
onViewShowing: function(aEvent) {
// Populate our list of history
@ -190,6 +211,7 @@ const CustomizableWidgets = [{
}, {
id: "save-page-button",
shortcutId: "key_savePage",
tooltiptext: "save-page-button.tooltiptext2",
defaultArea: CustomizableUI.AREA_PANEL,
onCommand: function(aEvent) {
let win = aEvent.target &&
@ -202,6 +224,7 @@ const CustomizableWidgets = [{
}, {
id: "find-button",
shortcutId: "key_find",
tooltiptext: "find-button.tooltiptext2",
defaultArea: CustomizableUI.AREA_PANEL,
onCommand: function(aEvent) {
let win = aEvent.target &&
@ -214,6 +237,7 @@ const CustomizableWidgets = [{
}, {
id: "open-file-button",
shortcutId: "openFileKb",
tooltiptext: "open-file-button.tooltiptext2",
defaultArea: CustomizableUI.AREA_PANEL,
onCommand: function(aEvent) {
let win = aEvent.target
@ -289,6 +313,7 @@ const CustomizableWidgets = [{
}, {
id: "add-ons-button",
shortcutId: "key_openAddons",
tooltiptext: "add-ons-button.tooltiptext2",
defaultArea: CustomizableUI.AREA_PANEL,
onCommand: function(aEvent) {
let win = aEvent.target &&
@ -303,7 +328,14 @@ const CustomizableWidgets = [{
defaultArea: CustomizableUI.AREA_PANEL,
#ifdef XP_WIN
label: "preferences-button.labelWin",
tooltiptext: "preferences-button.tooltipWin",
tooltiptext: "preferences-button.tooltipWin2",
#else
#ifdef XP_MACOSX
tooltiptext: "preferences-button.tooltiptext.withshortcut",
shortcutId: "key_preferencesCmdMac",
#else
tooltiptext: "preferences-button.tooltiptext",
#endif
#endif
onCommand: function(aEvent) {
let win = aEvent.target &&
@ -334,20 +366,23 @@ const CustomizableWidgets = [{
command: "cmd_fullZoomReduce",
class: cls,
label: true,
tooltiptext: true
tooltiptext: "tooltiptext2",
shortcutId: "key_fullZoomReduce",
}, {
id: "zoom-reset-button",
closemenu: closeMenu,
command: "cmd_fullZoomReset",
class: cls,
tooltiptext: true
tooltiptext: "tooltiptext2",
shortcutId: "key_fullZoomReset",
}, {
id: "zoom-in-button",
closemenu: closeMenu,
command: "cmd_fullZoomEnlarge",
class: cls,
label: true,
tooltiptext: true
tooltiptext: "tooltiptext2",
shortcutId: "key_fullZoomEnlarge",
}];
let node = aDocument.createElementNS(kNSXUL, "toolbaritem");
@ -490,19 +525,22 @@ const CustomizableWidgets = [{
command: "cmd_cut",
class: cls,
label: true,
tooltiptext: true
tooltiptext: "tooltiptext2",
shortcutId: "key_cut",
}, {
id: "copy-button",
command: "cmd_copy",
class: cls,
label: true,
tooltiptext: true
tooltiptext: "tooltiptext2",
shortcutId: "key_copy",
}, {
id: "paste-button",
command: "cmd_paste",
class: cls,
label: true,
tooltiptext: true
tooltiptext: "tooltiptext2",
shortcutId: "key_paste",
}];
let node = aDocument.createElementNS(kNSXUL, "toolbaritem");
@ -610,6 +648,7 @@ const CustomizableWidgets = [{
id: "characterencoding-button",
type: "view",
viewId: "PanelUI-characterEncodingView",
tooltiptext: "characterencoding-button.tooltiptext2",
defaultArea: CustomizableUI.AREA_PANEL,
maybeDisableMenu: function(aDocument) {
let window = aDocument.defaultView;
@ -731,6 +770,11 @@ const CustomizableWidgets = [{
onViewShowing: function(aEvent) {
let document = aEvent.target.ownerDocument;
let autoDetectLabelId = "PanelUI-characterEncodingView-autodetect-label";
let autoDetectLabel = document.getElementById(autoDetectLabelId);
let label = CharsetBundle.GetStringFromName("charsetMenuAutodet");
autoDetectLabel.setAttribute("value", label);
this.populateList(document,
"PanelUI-characterEncodingView-customlist",
"browser");
@ -817,6 +861,7 @@ const CustomizableWidgets = [{
}
}, {
id: "email-link-button",
tooltiptext: "email-link-button.tooltiptext2",
onCommand: function(aEvent) {
let win = aEvent.view;
win.MailIntegration.sendLinkForWindow(win.content);

View File

@ -16,6 +16,7 @@ const kDragDataTypePrefix = "text/toolbarwrapper-id/";
const kPlaceholderClass = "panel-customization-placeholder";
const kSkipSourceNodePref = "browser.uiCustomization.skipSourceNodeCheck";
const kToolbarVisibilityBtn = "customization-toolbar-visibility-button";
const kDrawInTitlebarPref = "browser.tabs.drawInTitlebar";
const kMaxTransitionDurationMs = 2000;
Cu.import("resource://gre/modules/Services.jsm");
@ -50,6 +51,11 @@ function CustomizeMode(aWindow) {
this.visiblePalette = this.document.getElementById(kPaletteId);
this.paletteEmptyNotice = this.document.getElementById("customization-empty");
this.paletteSpacer = this.document.getElementById("customization-spacer");
#ifdef CAN_DRAW_IN_TITLEBAR
this._updateTitlebarButton();
Services.prefs.addObserver(kDrawInTitlebarPref, this, false);
this.window.addEventListener("unload", this);
#endif
};
CustomizeMode.prototype = {
@ -80,6 +86,12 @@ CustomizeMode.prototype = {
return this.window.CustomizationHandler;
},
uninit: function() {
#ifdef CAN_DRAW_IN_TITLEBAR
Services.prefs.removeObserver(kDrawInTitlebarPref, this);
#endif
},
toggle: function() {
if (this._handler.isEnteringCustomizeMode || this._handler.isExitingCustomizeMode) {
this._wantToBeInCustomizeMode = !this._wantToBeInCustomizeMode;
@ -967,9 +979,43 @@ CustomizeMode.prototype = {
this.exit();
}
break;
#ifdef CAN_DRAW_IN_TITLEBAR
case "unload":
this.uninit();
break;
#endif
}
},
#ifdef CAN_DRAW_IN_TITLEBAR
observe: function(aSubject, aTopic, aData) {
switch (aTopic) {
case "nsPref:changed":
this._updateTitlebarButton();
break;
}
},
_updateTitlebarButton: function() {
let drawInTitlebar = true;
try {
drawInTitlebar = Services.prefs.getBoolPref(kDrawInTitlebarPref);
} catch (ex) { }
let button = this.document.getElementById("customization-titlebar-visibility-button");
// Drawing in the titlebar means 'hiding' the titlebar:
if (drawInTitlebar) {
button.removeAttribute("checked");
} else {
button.setAttribute("checked", "true");
}
},
toggleTitlebar: function(aShouldShowTitlebar) {
// Drawing in the titlebar means not showing the titlebar, hence the negation:
Services.prefs.setBoolPref(kDrawInTitlebarPref, !aShouldShowTitlebar);
},
#endif
_onDragStart: function(aEvent) {
__dumpDragData(aEvent);
let item = aEvent.target;

View File

@ -9,6 +9,9 @@ EXTRA_JS_MODULES += [
'ScrollbarSampler.jsm',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
EXTRA_PP_JS_MODULES += [
'CustomizableUI.jsm',
'CustomizableWidgets.jsm',

View File

@ -40,22 +40,6 @@ const DOWNLOAD_VIEW_SUPPORTED_COMMANDS =
const NOT_AVAILABLE = Number.MAX_VALUE;
/**
* Download a URL.
*
* @param aURL
* the url to download (nsIURI object)
* @param [optional] aFileName
* the destination file name
*/
function DownloadURL(aURL, aFileName) {
// For private browsing, try to get document out of the most recent browser
// window, or provide our own if there's no browser window.
let browserWin = RecentWindow.getMostRecentBrowserWindow();
let initiatingDoc = browserWin ? browserWin.document : document;
saveURL(aURL, aFileName, null, true, true, undefined, initiatingDoc);
}
/**
* A download element shell is responsible for handling the commands and the
* displayed data for a single download view element. The download element
@ -645,7 +629,10 @@ DownloadElementShell.prototype = {
// In future we may try to download into the same original target uri, when
// we have it. Though that requires verifying the path is still valid and
// may surprise the user if he wants to be requested every time.
DownloadURL(this.downloadURI, this.getDownloadMetaData().fileName);
let browserWin = RecentWindow.getMostRecentBrowserWindow();
let initiatingDoc = browserWin ? browserWin.document : document;
DownloadURL(this.downloadURI, this.getDownloadMetaData().fileName,
initiatingDoc);
},
/* nsIController */
@ -1433,7 +1420,9 @@ DownloadsPlacesView.prototype = {
_downloadURLFromClipboard: function DPV__downloadURLFromClipboard() {
let [url, name] = this._getURLFromClipboardData();
DownloadURL(url, name);
let browserWin = RecentWindow.getMostRecentBrowserWindow();
let initiatingDoc = browserWin ? browserWin.document : document;
DownloadURL(url, name, initiatingDoc);
},
doCommand: function DPV_doCommand(aCommand) {
@ -1487,6 +1476,11 @@ DownloadsPlacesView.prototype = {
else
contextMenu.removeAttribute("state");
if (state == nsIDM.DOWNLOAD_DOWNLOADING) {
// The resumable property of a download may change at any time, so
// ensure we update the related command now.
goUpdateCommand("downloadsCmd_pauseResume");
}
return true;
},
@ -1579,8 +1573,11 @@ DownloadsPlacesView.prototype = {
let name = { };
let url = Services.droppedLinkHandler.dropLink(aEvent, name);
if (url)
DownloadURL(url, name.value);
if (url) {
let browserWin = RecentWindow.getMostRecentBrowserWindow();
let initiatingDoc = browserWin ? browserWin.document : document;
DownloadURL(url, name.value, initiatingDoc);
}
}
};

View File

@ -505,8 +505,7 @@ const DownloadsPanel = {
let uri = NetUtil.newURI(url);
DownloadsCommon.log("Pasted URL seems valid. Starting download.");
saveURL(uri.spec, name || uri.spec, null, true, true,
undefined, document);
DownloadURL(uri.spec, name, document);
} catch (ex) {}
},

View File

@ -220,6 +220,11 @@ let SessionHistoryListener = {
addEventListener("load", this, true);
addEventListener("hashchange", this, true);
Services.obs.addObserver(this, "browser:purge-session-history", false);
// Collect data if we start with a non-empty shistory.
if (!SessionHistory.isEmpty(docShell)) {
this.collect();
}
},
uninit: function () {

View File

@ -24,6 +24,10 @@ function debug(msg) {
* The external API exported by this module.
*/
this.SessionHistory = Object.freeze({
isEmpty: function (docShell) {
return SessionHistoryInternal.isEmpty(docShell);
},
collect: function (docShell) {
return SessionHistoryInternal.collect(docShell);
},
@ -37,6 +41,19 @@ this.SessionHistory = Object.freeze({
* The internal API for the SessionHistory module.
*/
let SessionHistoryInternal = {
/**
* Returns whether the given docShell's session history is empty.
*
* @param docShell
* The docShell that owns the session history.
*/
isEmpty: function (docShell) {
let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
let history = webNavigation.sessionHistory;
let uri = webNavigation.currentURI.spec;
return uri == "about:blank" && history.count == 0;
},
/**
* Collects session history data for a given docShell.
*

View File

@ -2,6 +2,8 @@
- 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/. -->
<!ENTITY aboutAccountsSetup.description "Sign in to backup and sync your tabs, bookmarks, and more.">
<!ENTITY aboutAccountsSetup.startButton.label "Get Started">
<!ENTITY aboutAccountsSetup.useOldSync.label "Using Sync on an older version of &brandShortName;?">
<!ENTITY aboutAccounts.pageTitle "Welcome to Sync">
<!ENTITY aboutAccountsSetup.description "Sign in to sync your tabs, bookmarks, passwords &amp; more.">
<!ENTITY aboutAccountsSetup.startButton.label "Get started">
<!ENTITY aboutAccountsSetup.useOldSync.label "Using an older version of Sync?">

View File

@ -693,6 +693,7 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY customizeMode.menuAndToolbars.emptyLink "Choose from thousands of add-ons">
<!ENTITY customizeMode.restoreDefaults "Restore Defaults">
<!ENTITY customizeMode.toolbars "Show / Hide Toolbars">
<!ENTITY customizeMode.titlebar "Title Bar">
<!ENTITY social.chatBar.commandkey "c">
<!ENTITY social.chatBar.label "Focus chats">

View File

@ -3,73 +3,80 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
history-panelmenu.label = History
# LOCALIZATION NOTE (history-panelmenu.tooltiptext): Use the unicode ellipsis char,
# \u2026, or use "..." if \u2026 doesn't suit traditions in your locale.
history-panelmenu.tooltiptext = History… (%S)
# LOCALIZATION NOTE(history-panelmenu.tooltiptext2): %S is the keyboard shortcut
history-panelmenu.tooltiptext2 = Show your history (%S)
privatebrowsing-button.label = New Private Window
# LOCALIZATION NOTE(privatebrowsing-button.tooltiptext): %S is the keyboard shortcut
privatebrowsing-button.tooltiptext = Open a new Private Browsing window (%S)
save-page-button.label = Save Page
# LOCALIZATION NOTE(save-page-button.tooltiptext): %S is the keyboard shortcut
save-page-button.tooltiptext = Save this page (%S)
# LOCALIZATION NOTE(save-page-button.tooltiptext2): %S is the keyboard shortcut
# Use the unicode ellipsis char, \u2026, or use "..." if \u2026 doesn't suit traditions in your locale.
save-page-button.tooltiptext2 = Save this page… (%S)
find-button.label = Find
# LOCALIZATION NOTE(find-button.tooltiptext): %S is the keyboard shortcut
find-button.tooltiptext = Find in this page (%S)
# LOCALIZATION NOTE(find-button.tooltiptext2): %S is the keyboard shortcut.
# Use the unicode ellipsis char, \u2026, or use "..." if \u2026 doesn't suit traditions in your locale.
find-button.tooltiptext2 = Find in this page… (%S)
open-file-button.label = Open File
# LOCALIZATION NOTE(open-file-button.tooltiptext): %S is the keyboard shortcut
open-file-button.tooltiptext = Open file (%S)
# LOCALIZATION NOTE (open-file-button.tooltiptext2): %S is the keyboard shortcut.
# Use the unicode ellipsis char, \u2026, or use "..." if \u2026 doesn't suit traditions in your locale.
open-file-button.tooltiptext2 = Open file… (%S)
developer-button.label = Developer
# LOCALIZATION NOTE(developer-button.tooltiptext): %S is the keyboard shortcut
developer-button.tooltiptext = Web Developer Tools (%S)
add-ons-button.label = Add-ons
# LOCALIZATION NOTE(add-ons-button.tooltiptext): %S is the keyboard shortcut
add-ons-button.tooltiptext = Add-ons Manager (%S)
# LOCALIZATION NOTE(add-ons-button.tooltiptext2): %S is the keyboard shortcut
add-ons-button.tooltiptext2 = Open Add-ons Manager (%S)
switch-to-metro-button2.label = Windows 8 Touch
# LOCALIZATION NOTE(switch-to-metro-button2.tooltiptext): %S is the brand short name
switch-to-metro-button2.tooltiptext = Relaunch in %S for Windows 8 Touch
preferences-button.label = Preferences
# LOCALIZATION NOTE (preferences-button.tooltiptext): Use the unicode ellipsis char,
# \u2026, or use "..." if \u2026 doesn't suit traditions in your locale.
preferences-button.tooltiptext = Preferences…
preferences-button.tooltiptext2 = Open Preferences
preferences-button.tooltiptext.withshortcut = Open Preferences (%S)
# LOCALIZATION NOTE (preferences-button.labelWin): Windows-only label for Options
preferences-button.labelWin = Options
# LOCALIZATION NOTE (preferences-button.tooltipWin): Windows-only tooltip for Options
preferences-button.tooltipWin = Options
preferences-button.tooltipWin2 = Open Options
zoom-controls.label = Zoom Controls
zoom-controls.tooltiptext = Zoom Controls
zoom-out-button.label = Zoom out
zoom-out-button.tooltiptext = Zoom out
# LOCALIZATION NOTE(zoom-out-button.tooltiptext2): %S is the keyboard shortcut.
zoom-out-button.tooltiptext2 = Zoom out (%S)
# LOCALIZATION NOTE(zoom-reset-button.label): %S is the current zoom level,
# %% will be displayed as a single % character (% is commonly used to define
# format specifiers, so it needs to be escaped).
zoom-reset-button.label = %S%%
zoom-reset-button.tooltiptext = Reset zoom level
# LOCALIZATION NOTE(zoom-reset-button.tooltiptext2): %S is the keyboard shortcut.
zoom-reset-button.tooltiptext2 = Reset zoom level (%S)
zoom-in-button.label = Zoom in
zoom-in-button.tooltiptext = Zoom in
# LOCALIZATION NOTE(zoom-in-button.tooltiptext2): %S is the keyboard shortcut.
zoom-in-button.tooltiptext2 = Zoom in (%S)
edit-controls.label = Edit Controls
edit-controls.tooltiptext = Edit Controls
cut-button.label = Cut
cut-button.tooltiptext = Cut
# LOCALIZATION NOTE(cut-button.tooltiptext2): %S is the keyboard shortcut.
cut-button.tooltiptext2 = Cut (%S)
copy-button.label = Copy
copy-button.tooltiptext = Copy
# LOCALIZATION NOTE(copy-button.tooltiptext2): %S is the keyboard shortcut.
copy-button.tooltiptext2 = Copy (%S)
paste-button.label = Paste
paste-button.tooltiptext = Paste
# LOCALIZATION NOTE(paste-button.tooltiptext2): %S is the keyboard shortcut.
paste-button.tooltiptext2 = Paste (%S)
# LOCALIZATION NOTE (feed-button.tooltiptext): Use the unicode ellipsis char,
# \u2026, or use "..." if \u2026 doesn't suit traditions in your locale.
@ -77,10 +84,12 @@ feed-button.label = Subscribe
feed-button.tooltiptext = Subscribe to this page…
characterencoding-button.label = Character Encoding
characterencoding-button.tooltiptext = Character encoding
characterencoding-button.tooltiptext2 = Show Character Encoding options
email-link-button.label = Email Link
email-link-button.tooltiptext = Email Link
# LOCALIZATION NOTE (email-link-button.tooltiptext2): Use the unicode ellipsis char,
# \u2026, or use "..." if \u2026 doesn't suit traditions in your locale.
email-link-button.tooltiptext2 = Email Link…
# LOCALIZATION NOTE(quit-button.tooltiptext.linux): %S is the keyboard shortcut
quit-button.tooltiptext.linux = Quit (%S)

View File

@ -60,3 +60,6 @@ relink.verify.title = Merge Warning
relink.verify.heading = Are you sure you want to sign in to Sync?
# LOCALIZATION NOTE (relink.verify.description): Email address of a user previously signed into sync.
relink.verify.description = A different user was previously signed in to Sync on this device. Signing in will merge this browser's bookmarks, passwords and other settings with %S
manage.pageTitle = Manage Sync

View File

@ -25,6 +25,7 @@ var Appbar = {
// tilegroup selection events for all modules get bubbled up
window.addEventListener("selectionchange", this, false);
Services.obs.addObserver(this, "metro_on_async_tile_created", false);
// gather appbar telemetry data
try {
@ -35,6 +36,14 @@ var Appbar = {
}
},
observe: function(aSubject, aTopic, aData) {
switch (aTopic) {
case "metro_on_async_tile_created":
this._updatePinButton();
break;
}
},
handleEvent: function Appbar_handleEvent(aEvent) {
switch (aEvent.type) {
case 'URLChanged':

View File

@ -166,8 +166,8 @@ gTests.push({
"Displays the low, high, and average FTR frame intervals when flinging a page of text.");
PerfTest.declareNumericalResults([
{ value: low, desc: "low" },
{ value: high, desc: "high" },
{ value: ave, desc: "average" }
{ value: high, desc: "high", shareAxis: 0 },
{ value: ave, desc: "average", shareAxis: 0 }
]);
}
});
@ -213,8 +213,8 @@ gTests.push({
"Displays the low, high, and average FTR frame intervals for about:start.");
PerfTest.declareNumericalResults([
{ value: results.low, desc: "low" },
{ value: results.high, desc: "high" },
{ value: results.ave, desc: "average" }
{ value: results.high, desc: "high", shareAxis: 0 },
{ value: results.ave, desc: "average", shareAxis: 0 }
]);
}
});
});

View File

@ -194,6 +194,12 @@ documenttab[selected] .documenttab-selection {
background: transparent -moz-image-rect(url("chrome://browser/skin/images/tab-overlay.png"), 50%, 100%, 100%, 0%) 50% 50% no-repeat;
}
.documenttab-crop:-moz-locale-dir(rtl),
.documenttab-selection:-moz-locale-dir(rtl),
documenttab[selected] .documenttab-selection:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}
.documenttab-close {
background: none !important;
padding: @metro_spacing_small@ !important;
@ -389,8 +395,7 @@ documenttab[selected] .documenttab-selection {
background-position: right 6px center;
}
#overlay-plus:-moz-locale-dir(ltr),
#overlay-back:-moz-locale-dir(rtl) {
#overlay-plus:-moz-locale-dir(ltr) {
right: -70px;
background-position: left 6px center;
}
@ -443,12 +448,21 @@ documenttab[selected] .documenttab-selection {
transform: translateX(40px) scale(1.2);
}
#overlay-plus:-moz-locale-dir(ltr):hover,
#overlay-back:-moz-locale-dir(rtl):hover {
#overlay-plus:-moz-locale-dir(ltr):hover {
background-position: left 12px center;
transform: translateX(-40px) scale(1.2);
}
#overlay-back:-moz-locale-dir(rtl):hover {
transform: translateX(-40px) scale(1.2) scaleX(-1);
}
#overlay-back:-moz-locale-dir(rtl) {
transform: scaleX(-1);
right: -70px;
background-position: right 9px center;
}
#overlay-back[mousedrag],
#overlay-plus[mousedrag] {
transition-property: left, right, transform, background-position,
@ -535,6 +549,11 @@ documenttab[selected] .documenttab-selection {
transition: opacity @forward_transition_length@ ease-out;
}
#back-button:-moz-locale-dir(rtl),
#forward-button:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}
#back-button[disabled] {
visibility: visible;
opacity: 0.5;
@ -858,6 +877,10 @@ documenttab[selected] .documenttab-selection {
-moz-box-pack: center;
}
#panel-close-button:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}
@media (min-resolution: @min_res_140pc@) {
#panel-close-button {
list-style-image: url(chrome://browser/skin/images/navbar-back@1.4x.png);

View File

@ -79,6 +79,10 @@ flyoutpanel[visible] {
-moz-image-region: rect(0 32px 32px 0);
}
.flyout-close-button:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}
.flyout-close-button:hover {
-moz-image-region: rect(0 64px 32px 32px);
}

View File

@ -4056,6 +4056,21 @@ window > chatbox {
border-left: 3px solid transparent;
}
@media (min-resolution: 2dppx) {
#customization-titlebar-visibility-button {
list-style-image: url("chrome://browser/skin/customizableui/customize-titleBar-toggle@2x.png");
-moz-image-region: rect(0, 48px, 48px, 0);
}
#customization-titlebar-visibility-button[checked] {
-moz-image-region: rect(0, 96px, 48px, 48px);
}
#customization-titlebar-visibility-button > .button-box > .button-icon {
width: 24px;
}
}
/* End customization mode */
#main-window[privatebrowsingmode=temporary] {

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

View File

@ -24,10 +24,12 @@ browser.jar:
* skin/classic/browser/browser-lightweightTheme.css
skin/classic/browser/click-to-play-warning-stripes.png
skin/classic/browser/customizableui/background-noise-toolbar.png (customizableui/background-noise-toolbar.png)
skin/classic/browser/customizableui/customize-titleBar-toggle.png (customizableui/customize-titleBar-toggle.png)
skin/classic/browser/customizableui/customize-titleBar-toggle@2x.png (customizableui/customize-titleBar-toggle@2x.png)
skin/classic/browser/customizableui/customizeFavicon.ico (../shared/customizableui/customizeFavicon.ico)
skin/classic/browser/customizableui/customizeMode-gridTexture.png (customizableui/customizeMode-gridTexture.png)
skin/classic/browser/customizableui/customizeMode-separatorHorizontal.png (customizableui/customizeMode-separatorHorizontal.png)
skin/classic/browser/customizableui/customizeMode-separatorVertical.png (customizableui/customizeMode-separatorVertical.png)
skin/classic/browser/customizableui/customizeFavicon.ico (../shared/customizableui/customizeFavicon.ico)
* skin/classic/browser/engineManager.css (engineManager.css)
skin/classic/browser/fullscreen-darknoise.png
skin/classic/browser/Geolocation-16.png

View File

@ -36,8 +36,9 @@
background-color: rgb(247,247,247);
}
#customization-palette-container {
padding: 25px;
#customization-palette,
#customization-empty {
padding: 0 25px 25px;
}
#customization-header {
@ -46,6 +47,7 @@
color: rgb(64,100,128);
font-weight: lighter;
margin-bottom: 1em;
padding: 25px 25px 0;
}
#customization-panel-container {
@ -53,6 +55,46 @@
background-image: linear-gradient(to bottom, #3e86ce, #3878ba);
}
#customization-footer {
background-color: rgb(236,236,236);
border-top: 1px solid rgb(221,221,221);
padding: 15px;
}
.customizationmode-button {
border: 1px solid rgb(192,192,192);
border-radius: 3px;
margin: 0;
padding: 2px 12px;
background-color: rgb(251,251,251);
color: rgb(71,71,71);
box-shadow: 0 1px rgba(255, 255, 255, 0.5),
inset 0 1px rgba(255, 255, 255, 0.5);
-moz-appearance: none;
}
#customization-titlebar-visibility-button {
list-style-image: url("chrome://browser/skin/customizableui/customize-titleBar-toggle.png");
-moz-image-region: rect(0, 24px, 24px, 0);
padding: 2px 7px;
-moz-margin-end: 10px;
}
#customization-titlebar-visibility-button > .button-box > .button-text {
/* Sadly, button.css thinks its margins are perfect for everyone. */
-moz-margin-start: 6px !important;
}
#customization-titlebar-visibility-button[checked] {
-moz-image-region: rect(0, 48px, 24px, 24px);
background-color: rgb(218, 218, 218);
border-color: rgb(168, 168, 168);
text-shadow: 0 1px rgb(236, 236, 236);
box-shadow: 0 1px rgba(255, 255, 255, 0.5),
inset 0 1px rgb(196, 196, 196);
}
#main-window[customize-entered] #customization-panel-container {
background-image: url("chrome://browser/skin/customizableui/customizeMode-separatorHorizontal.png"),
url("chrome://browser/skin/customizableui/customizeMode-separatorVertical.png"),

View File

@ -391,7 +391,6 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
panelview .toolbarbutton-1,
.subviewbutton,
.widget-overflow-list .toolbarbutton-1,
.customizationmode-button,
.panelUI-grid .toolbarbutton-1 > .toolbarbutton-menubutton-button,
#edit-controls@inAnyPanel@ > toolbarbutton,
#zoom-controls@inAnyPanel@ > toolbarbutton {
@ -450,7 +449,6 @@ panelview .toolbarbutton-1,
panelview .toolbarbutton-1@buttonStateHover@,
.subviewbutton@buttonStateHover@,
.widget-overflow-list .toolbarbutton-1@buttonStateHover@,
.customizationmode-button,
#edit-controls@inAnyPanel@ > toolbarbutton@buttonStateHover@,
#zoom-controls@inAnyPanel@ > toolbarbutton@buttonStateHover@ {
background-color: hsla(210,4%,10%,.08);
@ -464,7 +462,6 @@ panelview .toolbarbutton-1@buttonStateHover@,
panelview .toolbarbutton-1@buttonStateActive@,
.subviewbutton@buttonStateActive@,
.customizationmode-button@buttonStateActive@,
.widget-overflow-list .toolbarbutton-1@buttonStateActive@,
#edit-controls@inAnyPanel@ > toolbarbutton@buttonStateActive@,
#zoom-controls@inAnyPanel@ > toolbarbutton@buttonStateActive@ {

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

View File

@ -26,10 +26,11 @@ browser.jar:
* skin/classic/browser/browser-lightweightTheme.css
skin/classic/browser/click-to-play-warning-stripes.png
skin/classic/browser/customizableui/background-noise-toolbar.png (customizableui/background-noise-toolbar.png)
skin/classic/browser/customizableui/customizeFavicon.ico (../shared/customizableui/customizeFavicon.ico)
skin/classic/browser/customizableui/customize-titleBar-toggle.png (customizableui/customize-titleBar-toggle.png)
skin/classic/browser/customizableui/customizeMode-gridTexture.png (customizableui/customizeMode-gridTexture.png)
skin/classic/browser/customizableui/customizeMode-separatorHorizontal.png (customizableui/customizeMode-separatorHorizontal.png)
skin/classic/browser/customizableui/customizeMode-separatorVertical.png (customizableui/customizeMode-separatorVertical.png)
skin/classic/browser/customizableui/customizeFavicon.ico (../shared/customizableui/customizeFavicon.ico)
* skin/classic/browser/engineManager.css
skin/classic/browser/fullscreen-darknoise.png
skin/classic/browser/Geolocation-16.png
@ -352,10 +353,11 @@ browser.jar:
* skin/classic/aero/browser/browser-lightweightTheme.css
skin/classic/aero/browser/click-to-play-warning-stripes.png
skin/classic/aero/browser/customizableui/background-noise-toolbar.png (customizableui/background-noise-toolbar.png)
skin/classic/aero/browser/customizableui/customize-titleBar-toggle.png (customizableui/customize-titleBar-toggle.png)
skin/classic/aero/browser/customizableui/customizeFavicon.ico (../shared/customizableui/customizeFavicon.ico)
skin/classic/aero/browser/customizableui/customizeMode-gridTexture.png (customizableui/customizeMode-gridTexture.png)
skin/classic/aero/browser/customizableui/customizeMode-separatorHorizontal.png (customizableui/customizeMode-separatorHorizontal.png)
skin/classic/aero/browser/customizableui/customizeMode-separatorVertical.png (customizableui/customizeMode-separatorVertical.png)
skin/classic/aero/browser/customizableui/customizeFavicon.ico (../shared/customizableui/customizeFavicon.ico)
* skin/classic/aero/browser/engineManager.css
skin/classic/aero/browser/fullscreen-darknoise.png
skin/classic/aero/browser/Geolocation-16.png

View File

@ -5,8 +5,6 @@
INTERNAL_TOOLS = 1
VPATH += $(topsrcdir)/build
OS_CXXFLAGS := $(filter-out -fno-exceptions,$(OS_CXXFLAGS)) -fexceptions
WRAP_LDFLAGS=

View File

@ -19,7 +19,7 @@ from mozbuild.base import (
def is_valgrind_build(cls):
"""Must be a build with --enable-valgrind and --disable-jemalloc."""
'''Must be a build with --enable-valgrind and --disable-jemalloc.'''
defines = cls.config_environment.defines
return 'MOZ_VALGRIND' in defines and 'MOZ_MEMORY' not in defines
@ -42,6 +42,7 @@ class MachCommands(MachCommandBase):
'files.')
def valgrind_test(self, suppressions):
import json
import re
import sys
import tempfile
@ -91,13 +92,25 @@ class MachCommands(MachCommandBase):
env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
env['XPCOM_DEBUG_BREAK'] = 'warn'
class OutputHandler(object):
def __init__(self):
self.found_errors = False
def __call__(self, line):
print(line)
m = re.match(r'.*ERROR SUMMARY: [1-9]\d* errors from \d+ contexts', line)
if m:
self.found_errors = True
outputHandler = OutputHandler()
kp_kwargs = {'processOutputLine': [outputHandler]}
valgrind = 'valgrind'
if not os.path.exists(valgrind):
valgrind = findInPath(valgrind)
valgrind_args = [
valgrind,
'--error-exitcode=1',
'--smc-check=all-non-file',
'--vex-iropt-register-updates=allregs-at-mem-access',
'--gen-suppressions=all',
@ -121,18 +134,28 @@ class MachCommands(MachCommandBase):
if os.path.isfile(supps_file2):
valgrind_args.append('--suppressions=' + supps_file2)
exitcode = None
try:
runner = FirefoxRunner(profile=profile,
binary=self.get_binary_path(),
cmdargs=firefox_args,
env=env)
env=env,
kp_kwargs=kp_kwargs)
runner.start(debug_args=valgrind_args)
status = runner.wait()
exitcode = runner.wait()
finally:
if not outputHandler.found_errors:
status = 0
print('TEST-PASS | valgrind-test | valgrind found no errors')
else:
status = 1 # turns the TBPL job orange
print('TEST-UNEXPECTED-FAIL | valgrind-test | valgrind found errors')
if exitcode != 0:
status = 2 # turns the TBPL job red
print('TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code from Valgrind')
httpd.stop()
if status != 0:
status = 1 # normalize status, in case it's larger than 127
print('TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code')
return status

View File

@ -3221,7 +3221,7 @@ nsObjectLoadingContent::LegacyCall(JSContext* aCx,
}
JS::Rooted<JS::Value> retval(aCx);
bool ok = JS::Call(aCx, thisVal, pi_obj, args.Length(), rooter.array,
bool ok = JS::Call(aCx, thisVal, pi_obj, rooter.length(), rooter.start(),
&retval);
if (!ok) {
aRv.Throw(NS_ERROR_FAILURE);

View File

@ -900,6 +900,7 @@ protected:
OES_standard_derivatives,
OES_texture_float,
OES_texture_float_linear,
OES_texture_half_float,
OES_vertex_array_object,
WEBGL_compressed_texture_atc,
WEBGL_compressed_texture_pvrtc,

View File

@ -23,6 +23,7 @@ static const char *sExtensionNames[] = {
"OES_standard_derivatives",
"OES_texture_float",
"OES_texture_float_linear",
"OES_texture_half_float",
"OES_vertex_array_object",
"WEBGL_compressed_texture_atc",
"WEBGL_compressed_texture_pvrtc",
@ -86,6 +87,12 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
return gl->IsSupported(GLFeature::texture_float);
case OES_texture_float_linear:
return gl->IsSupported(GLFeature::texture_float_linear);
case OES_texture_half_float:
// If we have Feature::texture_half_float, we must not be on ES2
// and need to translate HALF_FLOAT_OES -> HALF_FLOAT. We do that
// right before making the relevant calls.
return gl->IsExtensionSupported(GLContext::OES_texture_half_float) ||
gl->IsSupported(GLFeature::texture_half_float);
case OES_vertex_array_object:
return WebGLExtensionVertexArray::IsSupported(this);
case EXT_texture_filter_anisotropic:
@ -253,6 +260,9 @@ WebGLContext::EnableExtension(WebGLExtensionID ext)
case OES_texture_float_linear:
obj = new WebGLExtensionTextureFloatLinear(this);
break;
case OES_texture_half_float:
obj = new WebGLExtensionTextureHalfFloat(this);
break;
case WEBGL_draw_buffers:
obj = new WebGLExtensionDrawBuffers(this);
break;

View File

@ -3674,16 +3674,25 @@ GLenum WebGLContext::CheckedTexImage2D(GLenum target,
type != imageInfo.Type();
}
// convert type for half float if not on GLES2
GLenum realType = type;
if (realType == LOCAL_GL_HALF_FLOAT_OES && !gl->IsGLES2()) {
realType = LOCAL_GL_HALF_FLOAT;
}
if (sizeMayChange) {
UpdateWebGLErrorAndClearGLError();
gl->fTexImage2D(target, level, internalFormat, width, height, border, format, type, data);
gl->fTexImage2D(target, level, internalFormat, width, height, border, format, realType, data);
GLenum error = LOCAL_GL_NO_ERROR;
UpdateWebGLErrorAndClearGLError(&error);
return error;
} else {
gl->fTexImage2D(target, level, internalFormat, width, height, border, format, type, data);
return LOCAL_GL_NO_ERROR;
}
gl->fTexImage2D(target, level, internalFormat, width, height, border, format, realType, data);
return LOCAL_GL_NO_ERROR;
}
void
@ -3972,13 +3981,19 @@ WebGLContext::TexSubImage2D_base(GLenum target, GLint level,
// There are checks above to ensure that this won't overflow.
size_t dstStride = RoundedToNextMultipleOf(dstPlainRowSize, mPixelStoreUnpackAlignment).value();
// convert type for half float if not on GLES2
GLenum realType = type;
if (realType == LOCAL_GL_HALF_FLOAT_OES && !gl->IsGLES2()) {
realType = LOCAL_GL_HALF_FLOAT;
}
if (actualSrcFormat == dstFormat &&
srcPremultiplied == mPixelStorePremultiplyAlpha &&
srcStride == dstStride &&
!mPixelStoreFlipY)
{
// no conversion, no flipping, so we avoid copying anything and just pass the source pointer
gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format, realType, pixels);
}
else
{
@ -3989,7 +4004,7 @@ WebGLContext::TexSubImage2D_base(GLenum target, GLint level,
actualSrcFormat, srcPremultiplied,
dstFormat, mPixelStorePremultiplyAlpha, dstTexelSize);
gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, convertedData);
gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format, realType, convertedData);
}
}
@ -4201,6 +4216,23 @@ WebGLTexelFormat mozilla::GetWebGLTexelFormat(GLenum internalformat, GLenum type
}
MOZ_CRASH("Invalid WebGL texture format/type?");
} else if (type == LOCAL_GL_HALF_FLOAT_OES) {
// OES_texture_half_float
switch (internalformat) {
case LOCAL_GL_RGBA:
return WebGLTexelFormat::RGBA16F;
case LOCAL_GL_RGB:
return WebGLTexelFormat::RGB16F;
case LOCAL_GL_ALPHA:
return WebGLTexelFormat::A16F;
case LOCAL_GL_LUMINANCE:
return WebGLTexelFormat::R16F;
case LOCAL_GL_LUMINANCE_ALPHA:
return WebGLTexelFormat::RA16F;
default:
MOZ_ASSERT(false, "Coding mistake?! Should never reach this point.");
return WebGLTexelFormat::BadFormat;
}
}
switch (type) {
@ -4261,6 +4293,21 @@ InternalFormatForFormatAndType(GLenum format, GLenum type, bool isGLES2)
}
break;
case LOCAL_GL_HALF_FLOAT_OES:
switch (format) {
case LOCAL_GL_RGBA:
return LOCAL_GL_RGBA16F;
case LOCAL_GL_RGB:
return LOCAL_GL_RGB16F;
case LOCAL_GL_ALPHA:
return LOCAL_GL_ALPHA16F_ARB;
case LOCAL_GL_LUMINANCE:
return LOCAL_GL_LUMINANCE16F_ARB;
case LOCAL_GL_LUMINANCE_ALPHA:
return LOCAL_GL_LUMINANCE_ALPHA16F_ARB;
}
break;
default:
break;
}

View File

@ -569,44 +569,9 @@ bool WebGLContext::ValidateTexFormatAndType(GLenum format, GLenum type, int jsAr
}
}
const char invalidTypedArray[] = "%s: invalid typed array type for given texture data type";
if (type == LOCAL_GL_UNSIGNED_BYTE ||
(IsExtensionEnabled(OES_texture_float) && type == LOCAL_GL_FLOAT))
{
if (jsArrayType != -1) {
if ((type == LOCAL_GL_UNSIGNED_BYTE && jsArrayType != js::ArrayBufferView::TYPE_UINT8) ||
(type == LOCAL_GL_FLOAT && jsArrayType != js::ArrayBufferView::TYPE_FLOAT32))
{
ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
return false;
}
}
int texMultiplier = type == LOCAL_GL_FLOAT ? 4 : 1;
switch (format) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
*texelSize = 1 * texMultiplier;
return true;
case LOCAL_GL_LUMINANCE_ALPHA:
*texelSize = 2 * texMultiplier;
return true;
case LOCAL_GL_RGB:
case LOCAL_GL_SRGB_EXT:
*texelSize = 3 * texMultiplier;
return true;
case LOCAL_GL_RGBA:
case LOCAL_GL_SRGB_ALPHA_EXT:
*texelSize = 4 * texMultiplier;
return true;
default:
break;
}
ErrorInvalidEnum("%s: invalid format 0x%x", info, format);
return false;
}
// First, we check for packed types
switch (type) {
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
@ -639,7 +604,67 @@ bool WebGLContext::ValidateTexFormatAndType(GLenum format, GLenum type, int jsAr
break;
}
ErrorInvalidEnum("%s: invalid type 0x%x", info, type);
int texMultiplier = 1;
// If not a packed types, then it's might be a standard type.
if (type == LOCAL_GL_UNSIGNED_BYTE) {
if (jsArrayType != -1 && jsArrayType != js::ArrayBufferView::TYPE_UINT8) {
ErrorInvalidEnum(invalidTypedArray, info);
return false;
}
} else if (type == LOCAL_GL_FLOAT) {
if (!IsExtensionEnabled(OES_texture_float)) {
ErrorInvalidEnum("%s: invalid format FLOAT: need OES_texture_float enabled", info);
return false;
}
if (jsArrayType != -1 && jsArrayType != js::ArrayBufferView::TYPE_FLOAT32) {
ErrorInvalidOperation(invalidTypedArray, info);
return false;
}
texMultiplier = 4;
} else if (type == LOCAL_GL_HALF_FLOAT_OES) {
if (!IsExtensionEnabled(OES_texture_half_float)) {
ErrorInvalidEnum("%s: invalid format HALF_FLOAT_OES: need OES_texture_half_float enabled", info);
return false;
}
if (jsArrayType != -1)
{
ErrorInvalidOperation(invalidTypedArray, info);
return false;
}
texMultiplier = 2;
} else {
// We don't know the type
ErrorInvalidEnum("%s: invalid type 0x%x", info, type);
return false;
}
// Ok we know that is a standard type.
switch (format) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
*texelSize = 1 * texMultiplier;
return true;
case LOCAL_GL_LUMINANCE_ALPHA:
*texelSize = 2 * texMultiplier;
return true;
case LOCAL_GL_RGB:
case LOCAL_GL_SRGB_EXT:
*texelSize = 3 * texMultiplier;
return true;
case LOCAL_GL_RGBA:
case LOCAL_GL_SRGB_ALPHA_EXT:
*texelSize = 4 * texMultiplier;
return true;
default:
break;
}
ErrorInvalidEnum("%s: invalid format 0x%x", info, format);
return false;
}

View File

@ -0,0 +1,20 @@
/* 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/. */
#include "WebGLContext.h"
#include "WebGLExtensions.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
using namespace mozilla;
WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* context)
: WebGLExtensionBase(context)
{
}
WebGLExtensionTextureHalfFloat::~WebGLExtensionTextureHalfFloat()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloat)

View File

@ -161,6 +161,16 @@ public:
DECL_WEBGL_EXTENSION_GOOP
};
class WebGLExtensionTextureHalfFloat
: public WebGLExtensionBase
{
public:
WebGLExtensionTextureHalfFloat(WebGLContext*);
virtual ~WebGLExtensionTextureHalfFloat();
DECL_WEBGL_EXTENSION_GOOP
};
class WebGLExtensionDrawBuffers
: public WebGLExtensionBase
{
@ -176,7 +186,7 @@ public:
static const size_t sMinDrawBuffers = 4;
/*
WEBGL_draw_buffers does not give a minal value for GL_MAX_DRAW_BUFFERS. But, we request
for GL_MAX_DRAW_BUFFERS = 4 at least to be able to use all requested color attachements.
for GL_MAX_DRAW_BUFFERS = 4 at least to be able to use all requested color attachments.
See DrawBuffersWEBGL in WebGLExtensionDrawBuffers.cpp inner comments for more informations.
*/

View File

@ -134,6 +134,13 @@ WebGLFramebuffer::Attachment::RectangleObject() const
static inline bool
IsValidFBOTextureColorFormat(GLenum internalFormat)
{
/* These formats are internal formats for each texture -- the actual
* low level format, which we might have to do conversions for when
* running against desktop GL (e.g. GL_RGBA + GL_FLOAT -> GL_RGBA32F).
*
* This function just handles all of them whether desktop GL or ES.
*/
return (
/* linear 8-bit formats */
internalFormat == LOCAL_GL_ALPHA ||
@ -149,7 +156,14 @@ IsValidFBOTextureColorFormat(GLenum internalFormat)
internalFormat == LOCAL_GL_LUMINANCE32F_ARB ||
internalFormat == LOCAL_GL_LUMINANCE_ALPHA32F_ARB ||
internalFormat == LOCAL_GL_RGB32F_ARB ||
internalFormat == LOCAL_GL_RGBA32F_ARB);
internalFormat == LOCAL_GL_RGBA32F_ARB ||
/* texture_half_float formats */
internalFormat == LOCAL_GL_ALPHA16F_ARB ||
internalFormat == LOCAL_GL_LUMINANCE16F_ARB ||
internalFormat == LOCAL_GL_LUMINANCE_ALPHA16F_ARB ||
internalFormat == LOCAL_GL_RGB16F_ARB ||
internalFormat == LOCAL_GL_RGBA16F_ARB
);
}
static inline bool

View File

@ -42,6 +42,8 @@ class WebGLImageConverter
switch (Format) {
case WebGLTexelFormat::R8:
case WebGLTexelFormat::A8:
case WebGLTexelFormat::R16F:
case WebGLTexelFormat::A16F:
case WebGLTexelFormat::R32F:
case WebGLTexelFormat::A32F:
case WebGLTexelFormat::RGBA5551:
@ -49,14 +51,17 @@ class WebGLImageConverter
case WebGLTexelFormat::RGB565:
return 1;
case WebGLTexelFormat::RA8:
case WebGLTexelFormat::RA16F:
case WebGLTexelFormat::RA32F:
return 2;
case WebGLTexelFormat::RGB8:
case WebGLTexelFormat::RGB16F:
case WebGLTexelFormat::RGB32F:
return 3;
case WebGLTexelFormat::RGBA8:
case WebGLTexelFormat::BGRA8:
case WebGLTexelFormat::BGRX8:
case WebGLTexelFormat::RGBA16F:
case WebGLTexelFormat::RGBA32F:
return 4;
default:
@ -243,16 +248,21 @@ class WebGLImageConverter
switch (dstFormat) {
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB565)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB32F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA8)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA5551)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA4444)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA16F)
WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA32F)
default:
MOZ_ASSERT(false, "unhandled case. Coding mistake?");
@ -274,18 +284,23 @@ public:
switch (srcFormat) {
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R32F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A32F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA32F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::BGRX8) // source format only
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB565)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB32F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::BGRA8)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA5551)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA4444)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA16F)
WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA32F)
default:
MOZ_ASSERT(false, "unhandled case. Coding mistake?");

View File

@ -38,6 +38,94 @@
namespace mozilla {
// single precision float
// seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm
// half precision float
// seeeeemmmmmmmmmm
// IEEE 16bits floating point:
const uint16_t kFloat16Value_Zero = 0x0000; // = 0000000000000000b
const uint16_t kFloat16Value_One = 0x3C00; // = 0011110000000000b
const uint16_t kFloat16Value_Infinity = 0x7C00; // = 0111110000000000b
const uint16_t kFloat16Value_NaN = 0x7FFF; // = 011111yyyyyyyyyyb (nonzero y)
MOZ_ALWAYS_INLINE uint16_t
packToFloat16(float v)
{
union {
float f32Value;
uint32_t f32Bits;
};
f32Value = v;
// pull the sign from v into f16bits
uint16_t f16Bits = uint16_t(f32Bits >> 16) & 0x8000;
// handle +/- 0
if ((f32Bits & 0x7FFFFFFF) == 0x00000000) {
return f16Bits;
}
// handle NaN
if (f32Value != f32Value) {
return f16Bits | kFloat16Value_NaN;
}
int32_t exp = int32_t(f32Bits >> 23) - 127;
// too small, we clamp it to -0 or +0
if (exp < -14) {
return f16Bits;
}
// too big, we clamp it to -inf/+inf
if (exp > 15) {
return f16Bits | kFloat16Value_Infinity;
}
f16Bits |= uint16_t(exp + 15) << 10;
f16Bits |= uint16_t(f32Bits >> 13) & 0x03FF;
return f16Bits;
}
MOZ_ALWAYS_INLINE float
unpackFromFloat16(uint16_t v)
{
union
{
float f32Value;
uint32_t f32Bits;
};
// grab sign bit
f32Bits = uint32_t(v & 0x8000) << 16;
if ((v & 0x7FFF) == 0x0000) {
// +0 or -0
return f32Value;
}
uint16_t exp = (v >> 10) & 0x001F;
if (exp == 0x001F) {
if (v & 0x03FF) {
// this is a NaN
f32Bits |= 0x7FFFFFFF;
} else {
// this is -inf or +inf
f32Bits |= 0x7F800000;
}
return f32Value;
}
f32Bits |= uint32_t(exp + (-15 + 127)) << 10;
f32Bits |= uint32_t(v & 0x03FF) << 13;
return f32Value;
}
MOZ_BEGIN_ENUM_CLASS(WebGLTexelPremultiplicationOp, int)
None,
Premultiply,
@ -57,6 +145,17 @@ struct IsFloatFormat
Format == WebGLTexelFormat::A32F;
};
template<MOZ_ENUM_CLASS_ENUM_TYPE(WebGLTexelFormat) Format>
struct IsHalfFloatFormat
{
static const bool Value =
Format == WebGLTexelFormat::RGBA16F ||
Format == WebGLTexelFormat::RGB16F ||
Format == WebGLTexelFormat::RA16F ||
Format == WebGLTexelFormat::R16F ||
Format == WebGLTexelFormat::A16F;
};
template<MOZ_ENUM_CLASS_ENUM_TYPE(WebGLTexelFormat) Format>
struct Is16bppFormat
{
@ -68,20 +167,27 @@ struct Is16bppFormat
template<MOZ_ENUM_CLASS_ENUM_TYPE(WebGLTexelFormat) Format,
bool IsFloat = IsFloatFormat<Format>::Value,
bool Is16bpp = Is16bppFormat<Format>::Value>
bool Is16bpp = Is16bppFormat<Format>::Value,
bool IsHalfFloat = IsHalfFloatFormat<Format>::Value>
struct DataTypeForFormat
{
typedef uint8_t Type;
};
template<MOZ_ENUM_CLASS_ENUM_TYPE(WebGLTexelFormat) Format>
struct DataTypeForFormat<Format, true, false>
struct DataTypeForFormat<Format, true, false, false>
{
typedef float Type;
};
template<MOZ_ENUM_CLASS_ENUM_TYPE(WebGLTexelFormat) Format>
struct DataTypeForFormat<Format, false, true>
struct DataTypeForFormat<Format, false, true, false>
{
typedef uint16_t Type;
};
template<MOZ_ENUM_CLASS_ENUM_TYPE(WebGLTexelFormat) Format>
struct DataTypeForFormat<Format, false, false, true>
{
typedef uint16_t Type;
};
@ -92,7 +198,8 @@ struct IntermediateFormat
static const MOZ_ENUM_CLASS_ENUM_TYPE(WebGLTexelFormat) Value
= IsFloatFormat<Format>::Value
? WebGLTexelFormat::RGBA32F
: WebGLTexelFormat::RGBA8;
: IsHalfFloatFormat<Format>::Value ? WebGLTexelFormat::RGBA16F
: WebGLTexelFormat::RGBA8;
};
inline GLenum
@ -116,6 +223,11 @@ GLFormatForTexelFormat(WebGLTexelFormat format) {
case WebGLTexelFormat::RA32F: return LOCAL_GL_LUMINANCE_ALPHA;
case WebGLTexelFormat::RGB32F: return LOCAL_GL_RGB;
case WebGLTexelFormat::RGBA32F: return LOCAL_GL_RGBA;
case WebGLTexelFormat::R16F: return LOCAL_GL_LUMINANCE;
case WebGLTexelFormat::A16F: return LOCAL_GL_ALPHA;
case WebGLTexelFormat::RA16F: return LOCAL_GL_LUMINANCE_ALPHA;
case WebGLTexelFormat::RGB16F: return LOCAL_GL_RGB;
case WebGLTexelFormat::RGBA16F: return LOCAL_GL_RGBA;
default:
MOZ_CRASH("Unknown texel format. Coding mistake?");
return LOCAL_GL_INVALID_ENUM;
@ -131,6 +243,8 @@ inline size_t TexelBytesForFormat(WebGLTexelFormat format) {
case WebGLTexelFormat::RGBA5551:
case WebGLTexelFormat::RGBA4444:
case WebGLTexelFormat::RGB565:
case WebGLTexelFormat::R16F:
case WebGLTexelFormat::A16F:
case WebGLTexelFormat::D16:
return 2;
case WebGLTexelFormat::RGB8:
@ -142,7 +256,11 @@ inline size_t TexelBytesForFormat(WebGLTexelFormat format) {
case WebGLTexelFormat::A32F:
case WebGLTexelFormat::D32:
case WebGLTexelFormat::D24S8:
case WebGLTexelFormat::RA16F:
return 4;
case WebGLTexelFormat::RGB16F:
return 6;
case WebGLTexelFormat::RGBA16F:
case WebGLTexelFormat::RA32F:
return 8;
case WebGLTexelFormat::RGB32F:
@ -157,11 +275,14 @@ inline size_t TexelBytesForFormat(WebGLTexelFormat format) {
MOZ_ALWAYS_INLINE bool HasAlpha(WebGLTexelFormat format) {
return format == WebGLTexelFormat::A8 ||
format == WebGLTexelFormat::A16F ||
format == WebGLTexelFormat::A32F ||
format == WebGLTexelFormat::RA8 ||
format == WebGLTexelFormat::RA16F ||
format == WebGLTexelFormat::RA32F ||
format == WebGLTexelFormat::RGBA8 ||
format == WebGLTexelFormat::BGRA8 ||
format == WebGLTexelFormat::RGBA16F ||
format == WebGLTexelFormat::RGBA32F ||
format == WebGLTexelFormat::RGBA4444 ||
format == WebGLTexelFormat::RGBA5551;
@ -169,15 +290,19 @@ MOZ_ALWAYS_INLINE bool HasAlpha(WebGLTexelFormat format) {
MOZ_ALWAYS_INLINE bool HasColor(WebGLTexelFormat format) {
return format == WebGLTexelFormat::R8 ||
format == WebGLTexelFormat::R16F ||
format == WebGLTexelFormat::R32F ||
format == WebGLTexelFormat::RA8 ||
format == WebGLTexelFormat::RA16F ||
format == WebGLTexelFormat::RA32F ||
format == WebGLTexelFormat::RGB8 ||
format == WebGLTexelFormat::BGRX8 ||
format == WebGLTexelFormat::RGB565 ||
format == WebGLTexelFormat::RGB16F ||
format == WebGLTexelFormat::RGB32F ||
format == WebGLTexelFormat::RGBA8 ||
format == WebGLTexelFormat::BGRA8 ||
format == WebGLTexelFormat::RGBA16F ||
format == WebGLTexelFormat::RGBA32F ||
format == WebGLTexelFormat::RGBA4444 ||
format == WebGLTexelFormat::RGBA5551;
@ -348,6 +473,51 @@ unpack<WebGLTexelFormat::A32F, float, float>(const float* __restrict src, float*
dst[3] = src[0];
}
template<> MOZ_ALWAYS_INLINE void
unpack<WebGLTexelFormat::RGBA16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
unpack<WebGLTexelFormat::RGB16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = kFloat16Value_One;
}
template<> MOZ_ALWAYS_INLINE void
unpack<WebGLTexelFormat::R16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
dst[0] = src[0];
dst[1] = src[0];
dst[2] = src[0];
dst[3] = kFloat16Value_One;
}
template<> MOZ_ALWAYS_INLINE void
unpack<WebGLTexelFormat::RA16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
dst[0] = src[0];
dst[1] = src[0];
dst[2] = src[0];
dst[3] = src[1];
}
template<> MOZ_ALWAYS_INLINE void
unpack<WebGLTexelFormat::A16F, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
dst[0] = kFloat16Value_Zero;
dst[1] = kFloat16Value_Zero;
dst[2] = kFloat16Value_Zero;
dst[3] = src[0];
}
//----------------------------------------------------------------------
// Pixel packing routines.
//
@ -678,6 +848,82 @@ pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::Premultiply, float,
dst[1] = scaleFactor;
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RGB16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RGB16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
float scaleFactor = unpackFromFloat16(src[3]);
dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor);
dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor);
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RGBA16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RGBA16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
float scaleFactor = unpackFromFloat16(src[3]);
dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor);
dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor);
dst[3] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::A16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
dst[0] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::A16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
dst[0] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::R16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
dst[0] = src[0];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::R16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
float scaleFactor = unpackFromFloat16(src[3]);
dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RA16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
dst[0] = src[0];
dst[1] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RA16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
float scaleFactor = unpackFromFloat16(src[3]);
dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
dst[1] = scaleFactor;
}
/****** END CODE SHARED WITH WEBKIT ******/
template<typename SrcType, typename DstType> MOZ_ALWAYS_INLINE void
@ -695,6 +941,15 @@ convertType<uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict
dst[3] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
convertType<uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
convertType<float, float>(const float* __restrict src, float* __restrict dst)
{
@ -714,6 +969,16 @@ convertType<uint8_t, float>(const uint8_t* __restrict src, float* __restrict dst
dst[3] = src[3] * scaleFactor;
}
template<> MOZ_ALWAYS_INLINE void
convertType<uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
{
const float scaleFactor = 1.f / 255.0f;
dst[0] = packToFloat16(src[0] * scaleFactor);
dst[1] = packToFloat16(src[1] * scaleFactor);
dst[2] = packToFloat16(src[2] * scaleFactor);
dst[3] = packToFloat16(src[3] * scaleFactor);
}
} // end namespace WebGLTexelConversions
} // end namespace mozilla

View File

@ -351,6 +351,26 @@ WebGLTexture::ResolvedFakeBlackStatus() {
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
}
}
else if (ImageInfoBase().mType == LOCAL_GL_HALF_FLOAT_OES)
{
if (mMinFilter == LOCAL_GL_LINEAR ||
mMinFilter == LOCAL_GL_LINEAR_MIPMAP_LINEAR ||
mMinFilter == LOCAL_GL_LINEAR_MIPMAP_NEAREST ||
mMinFilter == LOCAL_GL_NEAREST_MIPMAP_LINEAR)
{
mContext->GenerateWarning("%s is a texture with a linear minification filter, "
"which is not compatible with gl.HALF_FLOAT by default. "
"Try enabling the OES_texture_half_float_linear extension if supported.", msg_rendering_as_black);
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
}
else if (mMagFilter == LOCAL_GL_LINEAR)
{
mContext->GenerateWarning("%s is a texture with a linear magnification filter, "
"which is not compatible with gl.HALF_FLOAT by default. "
"Try enabling the OES_texture_half_float_linear extension if supported.", msg_rendering_as_black);
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
}
}
// We have exhausted all cases of incomplete textures, where we would need opaque black.
// We may still need transparent black in case of uninitialized image data.

View File

@ -108,25 +108,30 @@ MOZ_BEGIN_ENUM_CLASS(WebGLTexelFormat, int)
// 1-channel formats
R8,
A8,
D16, // used for WEBGL_depth_texture extension
D32, // used for WEBGL_depth_texture extension
R32F, // used for OES_texture_float extension
A32F, // used for OES_texture_float extension
D16, // WEBGL_depth_texture
D32, // WEBGL_depth_texture
R16F, // OES_texture_half_float
A16F, // OES_texture_half_float
R32F, // OES_texture_float
A32F, // OES_texture_float
// 2-channel formats
RA8,
RA32F,
D24S8, // used for WEBGL_depth_texture extension
RA16F, // OES_texture_half_float
RA32F, // OES_texture_float
D24S8, // WEBGL_depth_texture
// 3-channel formats
RGB8,
BGRX8, // used for DOM elements. Source format only.
RGB565,
RGB32F, // used for OES_texture_float extension
RGB16F, // OES_texture_half_float
RGB32F, // OES_texture_float
// 4-channel formats
RGBA8,
BGRA8, // used for DOM elements
RGBA5551,
RGBA4444,
RGBA32F // used for OES_texture_float extension
RGBA16F, // OES_texture_half_float
RGBA32F // OES_texture_float
MOZ_END_ENUM_CLASS(WebGLTexelFormat)
} // namespace mozilla

View File

@ -58,6 +58,7 @@ if CONFIG['MOZ_WEBGL']:
'WebGLExtensionTextureFilterAnisotropic.cpp',
'WebGLExtensionTextureFloat.cpp',
'WebGLExtensionTextureFloatLinear.cpp',
'WebGLExtensionTextureHalfFloat.cpp',
'WebGLExtensionVertexArray.cpp',
'WebGLFramebuffer.cpp',
'WebGLObjectModel.cpp',

View File

@ -20,7 +20,6 @@ SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
function() {
var video = document.createElement("video");
video.src = "seek.webm";
isnot(video.textTracks, undefined, "HTMLMediaElement::TextTrack() property should be available.")

View File

@ -587,10 +587,6 @@ class nsOuterWindowProxy : public js::Wrapper
public:
nsOuterWindowProxy() : js::Wrapper(0) { }
virtual bool isOuterWindow() {
return true;
}
virtual bool finalizeInBackground(JS::Value priv) {
return false;
}
@ -678,6 +674,20 @@ protected:
JS::AutoIdVector &props);
};
const js::Class OuterWindowProxyClass =
PROXY_CLASS_WITH_EXT(
"Proxy",
0, /* additional slots */
0, /* additional class flags */
nullptr, /* call */
nullptr, /* construct */
PROXY_MAKE_EXT(
nullptr, /* outerObject */
js::proxy_innerObject,
nullptr, /* iteratorObject */
false /* isWrappedNative */
));
bool
nsOuterWindowProxy::isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy,
bool *extensible)
@ -1024,9 +1034,13 @@ static JSObject*
NewOuterWindowProxy(JSContext *cx, JS::Handle<JSObject*> parent, bool isChrome)
{
JSAutoCompartment ac(cx, parent);
js::WrapperOptions options;
options.setClass(&OuterWindowProxyClass);
options.setSingleton(true);
JSObject *obj = js::Wrapper::New(cx, parent, parent,
isChrome ? &nsChromeOuterWindowProxy::singleton
: &nsOuterWindowProxy::singleton);
: &nsOuterWindowProxy::singleton,
&options);
NS_ASSERTION(js::GetObjectClass(obj)->ext.innerObject, "bad class");
return obj;

View File

@ -1182,7 +1182,7 @@ nsJSContext::SetProperty(JS::Handle<JSObject*> aTarget, const char* aPropName, n
}
}
JSObject *args = ::JS_NewArrayObject(mContext, argc, array.array);
JSObject *args = ::JS_NewArrayObject(mContext, argc, array.start());
if (!args) {
return NS_ERROR_FAILURE;
}

View File

@ -1407,6 +1407,11 @@ DOMInterfaces = {
'headerFile': 'WebGLExtensions.h'
},
'WebGLExtensionTextureHalfFloat': {
'nativeType': 'mozilla::WebGLExtensionTextureHalfFloat',
'headerFile': 'WebGLExtensions.h'
},
'WebGLExtensionDrawBuffers': {
'nativeType': 'mozilla::WebGLExtensionDrawBuffers',
'headerFile': 'WebGLExtensions.h'

View File

@ -895,6 +895,12 @@ interface WebGLExtensionTextureFloatLinear
{
};
[NoInterfaceObject]
interface WebGLExtensionTextureHalfFloat
{
const GLenum HALF_FLOAT_OES = 0x8D61;
};
[NoInterfaceObject]
interface WebGLExtensionVertexArray {
const GLenum VERTEX_ARRAY_BINDING_OES = 0x85B5;

View File

@ -1070,7 +1070,7 @@ Proxy::HandleEvent(nsIDOMEvent* aEvent)
nsRefPtr<LoadStartDetectionRunnable> runnable =
new LoadStartDetectionRunnable(this, mXMLHttpRequestPrivate);
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
if (!runnable->RegisterAndDispatch()) {
NS_WARNING("Failed to dispatch LoadStartDetectionRunnable!");
}
}

View File

@ -31,6 +31,30 @@ function promiseResolve() {
});
}
function promiseResolveNoArg() {
var promise = new Promise(function(resolve, reject) {
ok(resolve, "Promise.resolve exists");
ok(reject, "Promise.reject exists");
resolve();
}).then(function(what) {
ok(true, "Then - resolveCb has been called");
is(what, undefined, "ResolveCb received undefined");
runTest();
}, function() {
ok(false, "Then - rejectCb has been called");
runTest();
});
}
function promiseRejectNoHandler() {
// This test only checks that the code that reports unhandled errors in the
// Promises implementation does not crash or leak.
var promise = new Promise(function(res, rej) {
noSuchMethod();
});
runTest();
}
function promiseReject() {
var promise = new Promise(function(resolve, reject) {
@ -45,6 +69,19 @@ function promiseReject() {
});
}
function promiseRejectNoArg() {
var promise = new Promise(function(resolve, reject) {
reject();
}).then(function(what) {
ok(false, "Then - resolveCb has been called");
runTest();
}, function(what) {
ok(true, "Then - rejectCb has been called");
is(what, undefined, "RejectCb received undefined");
runTest();
});
}
function promiseException() {
var promise = new Promise(function(resolve, reject) {
throw 42;
@ -260,6 +297,66 @@ function promiseThenCatchOrderingReject() {
});
}
function promiseThenNoArg() {
var promise = new Promise(function(resolve, reject) {
resolve(42);
});
var clone = promise.then();
isnot(promise, clone, "These 2 promise objs are different");
promise.then(function(v) {
clone.then(function(cv) {
is(v, cv, "Both resolve to the same value");
runTest();
});
});
}
function promiseThenUndefinedResolveFunction() {
var promise = new Promise(function(resolve, reject) {
reject(42);
});
try {
promise.then(undefined, function(v) {
is(v, 42, "Promise rejected with 42");
runTest();
});
} catch (e) {
ok(false, "then should not throw on undefined resolve function");
}
}
function promiseThenNullResolveFunction() {
var promise = new Promise(function(resolve, reject) {
reject(42);
});
try {
promise.then(null, function(v) {
is(v, 42, "Promise rejected with 42");
runTest();
});
} catch (e) {
ok(false, "then should not throw on null resolve function");
}
}
function promiseCatchNoArg() {
var promise = new Promise(function(resolve, reject) {
reject(42);
});
var clone = promise.catch();
isnot(promise, clone, "These 2 promise objs are different");
promise.catch(function(v) {
clone.catch(function(cv) {
is(v, cv, "Both reject to the same value");
runTest();
});
});
}
function promiseNestedPromise() {
new Promise(function(resolve, reject) {
resolve(new Promise(function(resolve, reject) {
@ -357,6 +454,217 @@ function promiseRejectNoHandler() {
runTest();
}
function promiseUtilitiesDefined() {
ok(Promise.all, "Promise.all must be defined when Promise is enabled.");
ok(Promise.cast, "Promise.cast must be defined when Promise is enabled.");
ok(Promise.race, "Promise.race must be defined when Promise is enabled.");
runTest();
}
function promiseAllArray() {
var p = Promise.all([1, new Date(), Promise.resolve("firefox")]);
ok(p instanceof Promise, "Return value of Promise.all should be a Promise.");
p.then(function(values) {
ok(Array.isArray(values), "Resolved value should be an array.");
is(values.length, 3, "Resolved array length should match iterable's length.");
is(values[0], 1, "Array values should match.");
ok(values[1] instanceof Date, "Array values should match.");
is(values[2], "firefox", "Array values should match.");
runTest();
}, function() {
ok(false, "Promise.all shouldn't fail when iterable has no rejected Promises.");
runTest();
});
}
function promiseAllWaitsForAllPromises() {
var arr = [
new Promise(function(resolve) {
setTimeout(resolve.bind(undefined, 1), 50);
}),
new Promise(function(resolve) {
setTimeout(resolve.bind(undefined, 2), 10);
}),
new Promise(function(resolve) {
setTimeout(resolve.bind(undefined, new Promise(function(resolve2) {
resolve2(3);
})), 10);
}),
new Promise(function(resolve) {
setTimeout(resolve.bind(undefined, 4), 20);
})
];
var p = Promise.all(arr);
p.then(function(values) {
ok(Array.isArray(values), "Resolved value should be an array.");
is(values.length, 4, "Resolved array length should match iterable's length.");
is(values[0], 1, "Array values should match.");
is(values[1], 2, "Array values should match.");
is(values[2], 3, "Array values should match.");
is(values[3], 4, "Array values should match.");
runTest();
}, function() {
ok(false, "Promise.all shouldn't fail when iterable has no rejected Promises.");
runTest();
});
}
function promiseAllRejectFails() {
var arr = [
new Promise(function(resolve) {
setTimeout(resolve.bind(undefined, 1), 50);
}),
new Promise(function(resolve, reject) {
setTimeout(reject.bind(undefined, 2), 10);
}),
new Promise(function(resolve) {
setTimeout(resolve.bind(undefined, 3), 10);
}),
new Promise(function(resolve) {
setTimeout(resolve.bind(undefined, 4), 20);
})
];
var p = Promise.all(arr);
p.then(function(values) {
ok(false, "Promise.all shouldn't resolve when iterable has rejected Promises.");
runTest();
}, function(e) {
ok(true, "Promise.all should reject when iterable has rejected Promises.");
is(e, 2, "Rejection value should match.");
runTest();
});
}
function promiseCastNoArg() {
var p = Promise.cast();
ok(p instanceof Promise, "Should cast to a Promise.");
p.then(function(v) {
is(v, undefined, "Resolved value should be undefined.");
runTest();
});
}
function promiseCastInteger() {
var p = Promise.cast(5);
ok(p instanceof Promise, "Should cast to a Promise.");
p.then(function(v) {
is(v, 5, "Resolved value should match original.");
runTest();
});
}
function promiseCastArray() {
var p = Promise.cast([1,2,3]);
ok(p instanceof Promise, "Should cast to a Promise.");
p.then(runTest);
}
// We don't support thenables, but if we did
// they'd have to be cast to a trusted Promise.
function promiseCastThenable() {
var p = Promise.cast({ then: function(onFulfill, onReject) { onFulfill(2); } });
ok(p instanceof Promise, "Should cast to a Promise.");
p.then(function(v) {
is(v, 2, "Should resolve to 2.");
runTest();
}, function(e) {
ok(false, "promiseCastThenable should've resolved");
runTest();
});
}
function promiseCastPromise() {
var original = Promise.resolve(true);
var cast = Promise.cast(original);
ok(cast instanceof Promise, "Should cast to a Promise.");
is(cast, original, "Should return original Promise.");
runTest();
}
function promiseRaceEmpty() {
var p = Promise.race([]);
ok(p instanceof Promise, "Should return a Promise.");
// An empty race never resolves!
runTest();
}
function promiseRaceValuesArray() {
var p = Promise.race([true, new Date(), 3]);
ok(p instanceof Promise, "Should return a Promise.");
p.then(function(winner) {
is(winner, true, "First value should win.");
runTest();
}, function(err) {
ok(false, "Should not fail " + err + ".");
runTest();
});
}
function promiseRacePromiseArray() {
function timeoutPromise(n) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(n);
}, n);
});
}
var arr = [
timeoutPromise(50),
timeoutPromise(20),
timeoutPromise(30),
timeoutPromise(100)
];
var p = Promise.race(arr);
p.then(function(winner) {
is(winner, 20, "Fastest timeout should win.");
runTest();
});
}
function promiseRaceReject() {
var p = Promise.race([
Promise.reject(new Error("Fail bad!")),
new Promise(function(resolve) {
setTimeout(resolve, 0);
})
]);
p.then(function() {
ok(false, "Should not resolve when winning Promise rejected.");
runTest();
}, function(e) {
ok(true, "Should be rejected");
ok(e instanceof Error, "Should reject with Error.");
ok(e.message == "Fail bad!", "Message should match.");
runTest();
});
}
function promiseRaceThrow() {
var p = Promise.race([
new Promise(function(resolve) {
nonExistent();
}),
new Promise(function(resolve) {
setTimeout(resolve, 0);
})
]);
p.then(function() {
ok(false, "Should not resolve when winning Promise had an error.");
runTest();
}, function(e) {
ok(true, "Should be rejected");
ok(e instanceof ReferenceError, "Should reject with ReferenceError for function nonExistent().");
runTest();
});
}
var tests = [
promiseResolve,
promiseReject,
@ -377,7 +685,32 @@ var tests = [
promiseStaticReject,
promiseStaticResolve,
promiseResolveNestedPromise,
promiseResolveNoArg,
promiseRejectNoArg,
promiseThenNoArg,
promiseThenUndefinedResolveFunction,
promiseThenNullResolveFunction,
promiseCatchNoArg,
promiseRejectNoHandler,
promiseUtilitiesDefined,
promiseAllArray,
promiseAllWaitsForAllPromises,
promiseAllRejectFails,
promiseCastNoArg,
promiseCastInteger,
promiseCastArray,
promiseCastThenable,
promiseCastPromise,
promiseRaceEmpty,
promiseRaceValuesArray,
promiseRacePromiseArray,
promiseRaceReject,
promiseRaceThrow,
];
function runTest() {

View File

@ -83,6 +83,8 @@ static const char *sExtensionNames[] = {
"GL_OES_texture_float",
"GL_OES_texture_float_linear",
"GL_ARB_texture_float",
"GL_OES_texture_half_float",
"GL_NV_half_float",
"GL_EXT_unpack_subimage",
"GL_OES_standard_derivatives",
"GL_EXT_texture_filter_anisotropic",

View File

@ -106,6 +106,7 @@ MOZ_BEGIN_ENUM_CLASS(GLFeature)
standard_derivatives,
texture_float,
texture_float_linear,
texture_half_float,
texture_non_power_of_two,
transform_feedback,
vertex_array_object,
@ -358,6 +359,8 @@ public:
OES_texture_float,
OES_texture_float_linear,
ARB_texture_float,
OES_texture_half_float,
NV_half_float,
EXT_unpack_subimage,
OES_standard_derivatives,
EXT_texture_filter_anisotropic,

View File

@ -291,6 +291,24 @@ static const FeatureInfo sFeatureInfoArr[] = {
GLContext::Extensions_End
}
},
{
"texture_half_float",
310, // OpenGL version
300, // OpenGL ES version
{
GLContext::ARB_texture_float,
GLContext::NV_half_float,
GLContext::Extensions_End
}
/**
* We are not including OES_texture_half_float in this feature, because:
* GL_HALF_FLOAT = 0x140B
* GL_HALF_FLOAT_ARB = 0x140B == GL_HALF_FLOAT
* GL_HALF_FLOAT_NV = 0x140B == GL_HALF_FLOAT
* GL_HALF_FLOAT_OES = 0x8D61 != GL_HALF_FLOAT
* WebGL handles this specifically with an OES_texture_half_float check.
*/
},
{
"texture_non_power_of_two",
200, // OpenGL version

View File

@ -526,10 +526,27 @@ CompositorParent::NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint,
// DEFAULT_FRAME_RATE in nsRefreshDriver.cpp.
static const int32_t kDefaultFrameRate = 60;
static int32_t
CalculateCompositionFrameRate()
{
int32_t compositionFrameRatePref = gfxPlatform::GetPrefLayersCompositionFrameRate();
if (compositionFrameRatePref < 0) {
// Use the same frame rate for composition as for layout.
int32_t layoutFrameRatePref = gfxPlatform::GetPrefLayoutFrameRate();
if (layoutFrameRatePref < 0) {
// TODO: The main thread frame scheduling code consults the actual
// monitor refresh rate in this case. We should do the same.
return kDefaultFrameRate;
}
return layoutFrameRatePref;
}
return compositionFrameRatePref;
}
void
CompositorParent::ScheduleComposition()
{
if (mCurrentCompositeTask) {
if (mCurrentCompositeTask || mPaused) {
return;
}
@ -538,12 +555,7 @@ CompositorParent::ScheduleComposition()
if (!initialComposition)
delta = TimeStamp::Now() - mLastCompose;
int32_t rate = gfxPlatform::GetPrefLayoutFrameRate();
if (rate < 0) {
// TODO: The main thread frame scheduling code consults the actual monitor
// refresh rate in this case. We should do the same.
rate = kDefaultFrameRate;
}
int32_t rate = CalculateCompositionFrameRate();
// If rate == 0 (ASAP mode), minFrameDelta must be 0 so there's no delay.
TimeDuration minFrameDelta = TimeDuration::FromMilliseconds(
@ -630,6 +642,13 @@ CompositorParent::CompositeInTransaction()
15 + (int)(TimeStamp::Now() - mExpectedComposeTime).ToMilliseconds());
}
#endif
// 0 -> Full-tilt composite
if (gfxPlatform::GetPrefLayersCompositionFrameRate() == 0) {
// Special full-tilt composite mode for performance testing
ScheduleComposition();
}
profiler_tracing("Paint", "Composite", TRACING_INTERVAL_END);
}

View File

@ -678,10 +678,12 @@ CompositorOGL::PrepareViewport(const gfx::IntSize& aSize,
void
CompositorOGL::SetLayerProgramProjectionMatrix(const Matrix4x4& aMatrix)
{
// Update the projection matrix in all of the programs, without activating them.
// The uniform will actually be set the next time the program is activated.
for (unsigned int i = 0; i < mPrograms.Length(); ++i) {
for (uint32_t mask = MaskNone; mask < NumMaskTypes; ++mask) {
if (mPrograms[i].mVariations[mask]) {
mPrograms[i].mVariations[mask]->CheckAndSetProjectionMatrix(aMatrix);
mPrograms[i].mVariations[mask]->DelayedSetProjectionMatrix(aMatrix);
}
}
}

View File

@ -21,23 +21,43 @@ namespace layers {
typedef ProgramProfileOGL::Argument Argument;
// helper methods for GetProfileFor
void
AddUniforms(ProgramProfileOGL& aProfile)
{
static const char *sKnownUniformNames[] = {
"uLayerTransform",
"uMaskQuadTransform",
"uLayerQuadTransform",
"uMatrixProj",
"uTextureTransform",
"uRenderTargetOffset",
"uLayerOpacity",
"uTexture",
"uYTexture",
"uCbTexture",
"uCrTexture",
"uBlackTexture",
"uWhiteTexture",
"uMaskTexture",
"uRenderColor",
"uTexCoordMultiplier",
nullptr
};
for (int i = 0; sKnownUniformNames[i] != nullptr; ++i) {
aProfile.mUniforms[i].mNameString = sKnownUniformNames[i];
aProfile.mUniforms[i].mName = (KnownUniform::KnownUniformName) i;
}
}
void
AddCommonArgs(ProgramProfileOGL& aProfile)
{
aProfile.mUniforms.AppendElement(Argument("uLayerTransform"));
aProfile.mUniforms.AppendElement(Argument("uLayerQuadTransform"));
aProfile.mUniforms.AppendElement(Argument("uMatrixProj"));
aProfile.mHasMatrixProj = true;
aProfile.mUniforms.AppendElement(Argument("uRenderTargetOffset"));
aProfile.mAttributes.AppendElement(Argument("aVertexCoord"));
}
void
AddCommonTextureArgs(ProgramProfileOGL& aProfile)
{
aProfile.mUniforms.AppendElement(Argument("uLayerOpacity"));
aProfile.mUniforms.AppendElement(Argument("uTexture"));
aProfile.mUniforms.AppendElement(Argument("uTextureTransform"));
aProfile.mAttributes.AppendElement(Argument("aTexCoord"));
}
@ -48,6 +68,8 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
NS_ASSERTION(ProgramExists(aType, aMask), "Invalid program type.");
ProgramProfileOGL result;
AddUniforms(result);
switch (aType) {
case RGBALayerProgramType:
if (aMask == Mask3d) {
@ -162,7 +184,6 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
result.mFragmentShaderString = sSolidColorLayerFS;
}
AddCommonArgs(result);
result.mUniforms.AppendElement(Argument("uRenderColor"));
break;
case YCbCrLayerProgramType:
if (aMask == Mask2d) {
@ -173,11 +194,6 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
result.mFragmentShaderString = sYCbCrTextureLayerFS;
}
AddCommonArgs(result);
result.mUniforms.AppendElement(Argument("uLayerOpacity"));
result.mUniforms.AppendElement(Argument("uYTexture"));
result.mUniforms.AppendElement(Argument("uCbTexture"));
result.mUniforms.AppendElement(Argument("uCrTexture"));
result.mUniforms.AppendElement(Argument("uTextureTransform"));
result.mAttributes.AppendElement(Argument("aTexCoord"));
result.mTextureCount = 3;
break;
@ -190,10 +206,6 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
result.mFragmentShaderString = sComponentPass1FS;
}
AddCommonArgs(result);
result.mUniforms.AppendElement(Argument("uLayerOpacity"));
result.mUniforms.AppendElement(Argument("uBlackTexture"));
result.mUniforms.AppendElement(Argument("uWhiteTexture"));
result.mUniforms.AppendElement(Argument("uTextureTransform"));
result.mAttributes.AppendElement(Argument("aTexCoord"));
result.mTextureCount = 2;
break;
@ -206,10 +218,6 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
result.mFragmentShaderString = sComponentPass1RGBFS;
}
AddCommonArgs(result);
result.mUniforms.AppendElement(Argument("uLayerOpacity"));
result.mUniforms.AppendElement(Argument("uBlackTexture"));
result.mUniforms.AppendElement(Argument("uWhiteTexture"));
result.mUniforms.AppendElement(Argument("uTextureTransform"));
result.mAttributes.AppendElement(Argument("aTexCoord"));
result.mTextureCount = 2;
break;
@ -222,10 +230,6 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
result.mFragmentShaderString = sComponentPass2FS;
}
AddCommonArgs(result);
result.mUniforms.AppendElement(Argument("uLayerOpacity"));
result.mUniforms.AppendElement(Argument("uBlackTexture"));
result.mUniforms.AppendElement(Argument("uWhiteTexture"));
result.mUniforms.AppendElement(Argument("uTextureTransform"));
result.mAttributes.AppendElement(Argument("aTexCoord"));
result.mTextureCount = 2;
break;
@ -238,10 +242,6 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
result.mFragmentShaderString = sComponentPass2RGBFS;
}
AddCommonArgs(result);
result.mUniforms.AppendElement(Argument("uLayerOpacity"));
result.mUniforms.AppendElement(Argument("uBlackTexture"));
result.mUniforms.AppendElement(Argument("uWhiteTexture"));
result.mUniforms.AppendElement(Argument("uTextureTransform"));
result.mAttributes.AppendElement(Argument("aTexCoord"));
result.mTextureCount = 2;
break;
@ -249,8 +249,6 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
NS_ASSERTION(!aMask, "Program does not have masked variant.");
result.mVertexShaderString = sCopyVS;
result.mFragmentShaderString = sCopy2DFS;
result.mUniforms.AppendElement(Argument("uTexture"));
result.mUniforms.AppendElement(Argument("uTextureTransform"));
result.mAttributes.AppendElement(Argument("aVertexCoord"));
result.mAttributes.AppendElement(Argument("aTexCoord"));
result.mTextureCount = 1;
@ -259,8 +257,6 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
NS_ASSERTION(!aMask, "Program does not have masked variant.");
result.mVertexShaderString = sCopyVS;
result.mFragmentShaderString = sCopy2DRectFS;
result.mUniforms.AppendElement(Argument("uTexture"));
result.mUniforms.AppendElement(Argument("uTextureTransform"));
result.mAttributes.AppendElement(Argument("aVertexCoord"));
result.mAttributes.AppendElement(Argument("aTexCoord"));
result.mTextureCount = 1;
@ -270,8 +266,6 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
}
if (aMask > MaskNone) {
result.mUniforms.AppendElement(Argument("uMaskTexture"));
result.mUniforms.AppendElement(Argument("uMaskQuadTransform"));
result.mTextureCount += 1;
}
@ -287,7 +281,8 @@ ShaderProgramOGL::ShaderProgramOGL(GLContext* aGL, const ProgramProfileOGL& aPro
, mProgram(0)
, mProfile(aProfile)
, mProgramState(STATE_NEW)
{}
{
}
ShaderProgramOGL::~ShaderProgramOGL()
{
@ -316,10 +311,9 @@ ShaderProgramOGL::Initialize()
mProgramState = STATE_OK;
for (uint32_t i = 0; i < mProfile.mUniforms.Length(); ++i) {
for (uint32_t i = 0; i < KnownUniform::KnownUniformCount; ++i) {
mProfile.mUniforms[i].mLocation =
mGL->fGetUniformLocation(mProgram, mProfile.mUniforms[i].mName);
NS_ASSERTION(mProfile.mUniforms[i].mLocation >= 0, "Bad uniform location.");
mGL->fGetUniformLocation(mProgram, mProfile.mUniforms[i].mNameString);
}
for (uint32_t i = 0; i < mProfile.mAttributes.Length(); ++i) {
@ -328,9 +322,7 @@ ShaderProgramOGL::Initialize()
NS_ASSERTION(mProfile.mAttributes[i].mLocation >= 0, "Bad attribute location.");
}
// this is a one-off that's present in the 2DRect versions of some shaders.
mTexCoordMultiplierUniformLocation =
mGL->fGetUniformLocation(mProgram, "uTexCoordMultiplier");
mProfile.mHasMatrixProj = mProfile.mUniforms[KnownUniform::MatrixProj].mLocation != -1;
return true;
}
@ -448,82 +440,11 @@ ShaderProgramOGL::Activate()
NS_ASSERTION(HasInitialized(), "Attempting to activate a program that's not in use!");
mGL->fUseProgram(mProgram);
// check and set the projection matrix
// check if we need to set the projection matrix
if (mIsProjectionMatrixStale) {
SetProjectionMatrix(mProjectionMatrix);
}
}
void
ShaderProgramOGL::SetUniform(GLint aLocation, float aFloatValue)
{
ASSERT_THIS_PROGRAM;
NS_ASSERTION(aLocation >= 0, "Invalid location");
mGL->fUniform1f(aLocation, aFloatValue);
}
void
ShaderProgramOGL::SetUniform(GLint aLocation, const gfxRGBA& aColor)
{
ASSERT_THIS_PROGRAM;
NS_ASSERTION(aLocation >= 0, "Invalid location");
mGL->fUniform4f(aLocation, float(aColor.r), float(aColor.g), float(aColor.b), float(aColor.a));
}
void
ShaderProgramOGL::SetUniform(GLint aLocation, int aLength, float *aFloatValues)
{
ASSERT_THIS_PROGRAM;
NS_ASSERTION(aLocation >= 0, "Invalid location");
if (aLength == 1) {
mGL->fUniform1fv(aLocation, 1, aFloatValues);
} else if (aLength == 2) {
mGL->fUniform2fv(aLocation, 1, aFloatValues);
} else if (aLength == 3) {
mGL->fUniform3fv(aLocation, 1, aFloatValues);
} else if (aLength == 4) {
mGL->fUniform4fv(aLocation, 1, aFloatValues);
} else {
NS_NOTREACHED("Bogus aLength param");
}
}
void
ShaderProgramOGL::SetUniform(GLint aLocation, GLint aIntValue)
{
ASSERT_THIS_PROGRAM;
NS_ASSERTION(aLocation >= 0, "Invalid location");
mGL->fUniform1i(aLocation, aIntValue);
}
void
ShaderProgramOGL::SetMatrixUniform(GLint aLocation, const gfx3DMatrix& aMatrix)
{
SetMatrixUniform(aLocation, &aMatrix._11);
}
void
ShaderProgramOGL::SetMatrixUniform(GLint aLocation, const float *aFloatValues)
{
ASSERT_THIS_PROGRAM;
NS_ASSERTION(aLocation >= 0, "Invalid location");
mGL->fUniformMatrix4fv(aLocation, 1, false, aFloatValues);
}
void
ShaderProgramOGL::SetUniform(GLint aLocation, const gfx::Color& aColor) {
ASSERT_THIS_PROGRAM;
NS_ASSERTION(aLocation >= 0, "Invalid location");
mGL->fUniform4f(aLocation, float(aColor.r), float(aColor.g), float(aColor.b), float(aColor.a));
}
} /* layers */
} /* mozilla */

View File

@ -6,7 +6,7 @@
#ifndef GFX_OGLSHADERPROGRAM_H
#define GFX_OGLSHADERPROGRAM_H
#include "GLDefs.h" // for GLint, GLenum, GLuint, etc
#include "GLContext.h" // for fast inlines of glUniform*
#include "gfx3DMatrix.h" // for gfx3DMatrix
#include "gfxTypes.h"
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
@ -23,9 +23,6 @@ struct gfxRGBA;
struct nsIntRect;
namespace mozilla {
namespace gl {
class GLContext;
}
namespace layers {
class Layer;
@ -50,6 +47,115 @@ enum ShaderProgramType {
NumProgramTypes
};
class KnownUniform {
public:
enum KnownUniformName {
NotAKnownUniform = -1,
LayerTransform = 0,
MaskQuadTransform,
LayerQuadTransform,
MatrixProj,
TextureTransform,
RenderTargetOffset,
LayerOpacity,
Texture,
YTexture,
CbTexture,
CrTexture,
BlackTexture,
WhiteTexture,
MaskTexture,
RenderColor,
TexCoordMultiplier,
KnownUniformCount
};
KnownUniform()
{
mName = NotAKnownUniform;
mNameString = nullptr;
mLocation = -1;
memset(&mValue, 0, sizeof(mValue));
}
bool UpdateUniform(int32_t i1) {
if (mLocation == -1) return false;
if (mValue.i1 != i1) {
mValue.i1 = i1;
return true;
}
return false;
}
bool UpdateUniform(float f1) {
if (mLocation == -1) return false;
if (mValue.f1 != f1) {
mValue.f1 = f1;
return true;
}
return false;
}
bool UpdateUniform(float f1, float f2) {
if (mLocation == -1) return false;
if (mValue.f16v[0] != f1 ||
mValue.f16v[1] != f2)
{
mValue.f16v[0] = f1;
mValue.f16v[1] = f2;
return true;
}
return false;
}
bool UpdateUniform(float f1, float f2, float f3, float f4) {
if (mLocation == -1) return false;
if (mValue.f16v[0] != f1 ||
mValue.f16v[1] != f2 ||
mValue.f16v[2] != f3 ||
mValue.f16v[3] != f4)
{
mValue.f16v[0] = f1;
mValue.f16v[1] = f2;
mValue.f16v[2] = f3;
mValue.f16v[3] = f4;
return true;
}
return false;
}
bool UpdateUniform(int cnt, const float *fp) {
if (mLocation == -1) return false;
switch (cnt) {
case 1:
case 2:
case 3:
case 4:
case 16:
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt) != 0) {
memcpy(mValue.f16v, fp, sizeof(float) * cnt);
return true;
}
return false;
}
NS_NOTREACHED("cnt must be 1 2 3 4 or 16");
return false;
}
KnownUniformName mName;
const char *mNameString;
int32_t mLocation;
union {
int i1;
float f1;
float f16v[16];
} mValue;
};
static inline ShaderProgramType
ShaderProgramFromSurfaceFormat(gfx::SurfaceFormat aFormat)
{
@ -149,17 +255,6 @@ struct ProgramProfileOGL
* respectively. Returns -1 if the named uniform/attribute does not
* have a location for the shaders represented by this profile.
*/
GLint LookupUniformLocation(const char* aName)
{
for (uint32_t i = 0; i < mUniforms.Length(); ++i) {
if (strcmp(mUniforms[i].mName, aName) == 0) {
return mUniforms[i].mLocation;
}
}
return -1;
}
GLint LookupAttributeLocation(const char* aName)
{
for (uint32_t i = 0; i < mAttributes.Length(); ++i) {
@ -184,7 +279,7 @@ struct ProgramProfileOGL
const char *mVertexShaderString;
const char *mFragmentShaderString;
nsTArray<Argument> mUniforms;
KnownUniform mUniforms[KnownUniform::KnownUniformCount];
nsTArray<Argument> mAttributes;
uint32_t mTextureCount;
bool mHasMatrixProj;
@ -247,7 +342,7 @@ public:
}
GLint GetTexCoordMultiplierUniformLocation() {
return mTexCoordMultiplierUniformLocation;
return mProfile.mUniforms[KnownUniform::TexCoordMultiplier].mLocation;
}
/**
@ -256,11 +351,11 @@ public:
* an assertion.
*/
void SetLayerTransform(const gfx::Matrix4x4& aMatrix) {
SetMatrixUniform(mProfile.LookupUniformLocation("uLayerTransform"), aMatrix);
SetMatrixUniform(KnownUniform::LayerTransform, aMatrix);
}
void SetMaskLayerTransform(const gfx::Matrix4x4& aMatrix) {
SetMatrixUniform(mProfile.LookupUniformLocation("uMaskQuadTransform"), aMatrix);
SetMatrixUniform(KnownUniform::MaskQuadTransform, aMatrix);
}
void SetLayerQuadRect(const nsIntRect& aRect) {
@ -269,7 +364,7 @@ public:
m._22 = float(aRect.height);
m._41 = float(aRect.x);
m._42 = float(aRect.y);
SetMatrixUniform(mProfile.LookupUniformLocation("uLayerQuadTransform"), m);
SetMatrixUniform(KnownUniform::LayerQuadTransform, m);
}
void SetLayerQuadRect(const gfx::Rect& aRect) {
@ -278,86 +373,85 @@ public:
m._22 = aRect.height;
m._41 = aRect.x;
m._42 = aRect.y;
SetMatrixUniform(mProfile.LookupUniformLocation("uLayerQuadTransform"), m);
SetMatrixUniform(KnownUniform::LayerQuadTransform, m);
}
// activates this program and sets its projection matrix, if the program uses one
void CheckAndSetProjectionMatrix(const gfx::Matrix4x4& aMatrix)
// Set a projection matrix on the program to be set the next time
// the program is activated.
void DelayedSetProjectionMatrix(const gfx::Matrix4x4& aMatrix)
{
if (mProfile.mHasMatrixProj) {
mIsProjectionMatrixStale = true;
mProjectionMatrix = aMatrix;
}
mIsProjectionMatrixStale = true;
mProjectionMatrix = aMatrix;
}
void SetProjectionMatrix(const gfx::Matrix4x4& aMatrix) {
SetMatrixUniform(mProfile.LookupUniformLocation("uMatrixProj"), aMatrix);
SetMatrixUniform(KnownUniform::MatrixProj, aMatrix);
mIsProjectionMatrixStale = false;
}
// sets this program's texture transform, if it uses one
void SetTextureTransform(const gfx::Matrix4x4& aMatrix) {
SetMatrixUniform(mProfile.LookupUniformLocation("uTextureTransform"), aMatrix);
SetMatrixUniform(KnownUniform::TextureTransform, aMatrix);
}
void SetRenderOffset(const nsIntPoint& aOffset) {
float vals[4] = { float(aOffset.x), float(aOffset.y), 0.0f, 0.0f };
SetUniform(mProfile.LookupUniformLocation("uRenderTargetOffset"), 4, vals);
SetUniform(KnownUniform::RenderTargetOffset, 4, vals);
}
void SetRenderOffset(float aX, float aY) {
float vals[4] = { aX, aY, 0.0f, 0.0f };
SetUniform(mProfile.LookupUniformLocation("uRenderTargetOffset"), 4, vals);
SetUniform(KnownUniform::RenderTargetOffset, 4, vals);
}
void SetLayerOpacity(float aOpacity) {
SetUniform(mProfile.LookupUniformLocation("uLayerOpacity"), aOpacity);
SetUniform(KnownUniform::LayerOpacity, aOpacity);
}
void SetTextureUnit(GLint aUnit) {
SetUniform(mProfile.LookupUniformLocation("uTexture"), aUnit);
SetUniform(KnownUniform::Texture, aUnit);
}
void SetYTextureUnit(GLint aUnit) {
SetUniform(mProfile.LookupUniformLocation("uYTexture"), aUnit);
SetUniform(KnownUniform::YTexture, aUnit);
}
void SetCbTextureUnit(GLint aUnit) {
SetUniform(mProfile.LookupUniformLocation("uCbTexture"), aUnit);
SetUniform(KnownUniform::CbTexture, aUnit);
}
void SetCrTextureUnit(GLint aUnit) {
SetUniform(mProfile.LookupUniformLocation("uCrTexture"), aUnit);
SetUniform(KnownUniform::CrTexture, aUnit);
}
void SetYCbCrTextureUnits(GLint aYUnit, GLint aCbUnit, GLint aCrUnit) {
SetUniform(mProfile.LookupUniformLocation("uYTexture"), aYUnit);
SetUniform(mProfile.LookupUniformLocation("uCbTexture"), aCbUnit);
SetUniform(mProfile.LookupUniformLocation("uCrTexture"), aCrUnit);
SetUniform(KnownUniform::YTexture, aYUnit);
SetUniform(KnownUniform::CbTexture, aCbUnit);
SetUniform(KnownUniform::CrTexture, aCrUnit);
}
void SetBlackTextureUnit(GLint aUnit) {
SetUniform(mProfile.LookupUniformLocation("uBlackTexture"), aUnit);
SetUniform(KnownUniform::BlackTexture, aUnit);
}
void SetWhiteTextureUnit(GLint aUnit) {
SetUniform(mProfile.LookupUniformLocation("uWhiteTexture"), aUnit);
SetUniform(KnownUniform::WhiteTexture, aUnit);
}
void SetMaskTextureUnit(GLint aUnit) {
SetUniform(mProfile.LookupUniformLocation("uMaskTexture"), aUnit);
SetUniform(KnownUniform::MaskTexture, aUnit);
}
void SetRenderColor(const gfxRGBA& aColor) {
SetUniform(mProfile.LookupUniformLocation("uRenderColor"), aColor);
SetUniform(KnownUniform::RenderColor, aColor);
}
void SetRenderColor(const gfx::Color& aColor) {
SetUniform(mProfile.LookupUniformLocation("uRenderColor"), aColor);
SetUniform(KnownUniform::RenderColor, aColor);
}
void SetTexCoordMultiplier(float aWidth, float aHeight) {
float f[] = {aWidth, aHeight};
SetUniform(mTexCoordMultiplierUniformLocation, 2, f);
SetUniform(KnownUniform::TexCoordMultiplier, 2, f);
}
// the names of attributes
@ -379,18 +473,82 @@ protected:
STATE_ERROR
} mProgramState;
GLint mTexCoordMultiplierUniformLocation;
void SetUniform(KnownUniform::KnownUniformName aKnownUniform, float aFloatValue)
{
ASSERT_THIS_PROGRAM;
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
void SetUniform(GLint aLocation, float aFloatValue);
void SetUniform(GLint aLocation, const gfxRGBA& aColor);
void SetUniform(GLint aLocation, int aLength, float *aFloatValues);
void SetUniform(GLint aLocation, GLint aIntValue);
void SetMatrixUniform(GLint aLocation, const gfx3DMatrix& aMatrix);
void SetMatrixUniform(GLint aLocation, const float *aFloatValues);
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
if (ku.UpdateUniform(aFloatValue)) {
mGL->fUniform1f(ku.mLocation, aFloatValue);
}
}
void SetUniform(GLint aLocation, const gfx::Color& aColor);
void SetMatrixUniform(GLint aLocation, const gfx::Matrix4x4& aMatrix) {
SetMatrixUniform(aLocation, &aMatrix._11);
void SetUniform(KnownUniform::KnownUniformName aKnownUniform, const gfxRGBA& aColor)
{
ASSERT_THIS_PROGRAM;
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
if (ku.UpdateUniform(aColor.r, aColor.g, aColor.b, aColor.a)) {
mGL->fUniform4fv(ku.mLocation, 1, ku.mValue.f16v);
}
}
void SetUniform(KnownUniform::KnownUniformName aKnownUniform, const gfx::Color& aColor) {
ASSERT_THIS_PROGRAM;
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
if (ku.UpdateUniform(aColor.r, aColor.g, aColor.b, aColor.a)) {
mGL->fUniform4fv(ku.mLocation, 1, ku.mValue.f16v);
}
}
void SetUniform(KnownUniform::KnownUniformName aKnownUniform, int aLength, float *aFloatValues)
{
ASSERT_THIS_PROGRAM;
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
if (ku.UpdateUniform(aLength, aFloatValues)) {
switch (aLength) {
case 1: mGL->fUniform1fv(ku.mLocation, 1, ku.mValue.f16v); break;
case 2: mGL->fUniform2fv(ku.mLocation, 1, ku.mValue.f16v); break;
case 3: mGL->fUniform3fv(ku.mLocation, 1, ku.mValue.f16v); break;
case 4: mGL->fUniform4fv(ku.mLocation, 1, ku.mValue.f16v); break;
default:
NS_NOTREACHED("Bogus aLength param");
}
}
}
void SetUniform(KnownUniform::KnownUniformName aKnownUniform, GLint aIntValue) {
ASSERT_THIS_PROGRAM;
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
if (ku.UpdateUniform(aIntValue)) {
mGL->fUniform1i(ku.mLocation, aIntValue);
}
}
void SetMatrixUniform(KnownUniform::KnownUniformName aKnownUniform, const float *aFloatValues) {
ASSERT_THIS_PROGRAM;
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
if (ku.UpdateUniform(16, aFloatValues)) {
mGL->fUniformMatrix4fv(ku.mLocation, 1, false, ku.mValue.f16v);
}
}
void SetMatrixUniform(KnownUniform::KnownUniformName aKnownUniform, const gfx3DMatrix& aMatrix) {
SetMatrixUniform(aKnownUniform, &aMatrix._11);
}
void SetMatrixUniform(KnownUniform::KnownUniformName aKnownUniform, const gfx::Matrix4x4& aMatrix) {
SetMatrixUniform(aKnownUniform, &aMatrix._11);
}
};

View File

@ -2070,6 +2070,7 @@ static bool sPrefLayersScrollGraph = false;
static bool sPrefLayersEnableTiles = false;
static bool sLayersSupportsD3D9 = false;
static int sPrefLayoutFrameRate = -1;
static int sPrefLayersCompositionFrameRate = -1;
static bool sBufferRotationEnabled = false;
static bool sComponentAlphaEnabled = true;
static bool sPrefBrowserTabsRemote = false;
@ -2098,6 +2099,7 @@ InitLayersAccelerationPrefs()
sPrefLayersScrollGraph = Preferences::GetBool("layers.scroll-graph", false);
sPrefLayersEnableTiles = Preferences::GetBool("layers.enable-tiles", false);
sPrefLayoutFrameRate = Preferences::GetInt("layout.frame_rate", -1);
sPrefLayersCompositionFrameRate = Preferences::GetInt("layers.offmainthreadcomposition.frame-rate", -1);
sBufferRotationEnabled = Preferences::GetBool("layers.bufferrotation.enabled", true);
sComponentAlphaEnabled = Preferences::GetBool("layers.componentalpha.enabled", true);
sPrefBrowserTabsRemote = BrowserTabsRemote();
@ -2217,6 +2219,13 @@ gfxPlatform::GetPrefLayersEnableTiles()
return sPrefLayersEnableTiles;
}
int
gfxPlatform::GetPrefLayersCompositionFrameRate()
{
InitLayersAccelerationPrefs();
return sPrefLayersCompositionFrameRate;
}
bool
gfxPlatform::BufferRotationEnabled()
{

View File

@ -510,6 +510,7 @@ public:
static bool GetPrefLayersPreferD3D9();
static bool CanUseDirect3D9();
static int GetPrefLayoutFrameRate();
static int GetPrefLayersCompositionFrameRate();
static bool GetPrefLayersDump();
static bool GetPrefLayersScrollGraph();
static bool GetPrefLayersEnableTiles();

View File

@ -11,6 +11,10 @@ if [ $# -lt 1 ]; then
exit 1
fi
# Ensure that $Date$ in the checked-out svn files expands timezone-agnostically,
# so that this script's behavior is consistent when run from any time zone.
export TZ=UTC
icu_dir=`dirname $0`/icu
rm -rf ${icu_dir}
svn export $1 ${icu_dir}
@ -35,8 +39,12 @@ rm ${icu_dir}/source/data/region/*.mk
rm ${icu_dir}/source/data/region/*.txt
rm ${icu_dir}/source/data/translit/*
# Record `svn info`
svn info $1 > ${icu_dir}/SVN-INFO
# Record `svn info`, eliding the line that changes every time the entire ICU
# repository (not just the path within it we care about) receives a commit.
# (This ensures that if ICU modifications are performed properly, it's always
# possible to run the command at the top of this script and make no changes to
# the tree.)
svn info $1 | grep -v '^Revision: [[:digit:]]\+$' > ${icu_dir}/SVN-INFO
patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/bug-724533
patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/bug-853706

View File

@ -102,6 +102,9 @@
#elif defined(__alpha__)
#define ARCH_CPU_ALPHA 1
#define ARCH_CPU_64_BITS 1
#elif defined(__aarch64__)
#define ARCH_CPU_AARCH64 1
#define ARCH_CPU_64_BITS 1
#else
#error Please add support for your architecture in build/build_config.h
#endif

View File

@ -574,7 +574,7 @@ JavaScriptParent::unwrap(JSContext *cx, ObjectId objId)
RootedValue v(cx, UndefinedValue());
ProxyOptions options;
options.setCallable(callable);
options.selectDefaultClass(callable);
obj = NewProxyObject(cx,
&CPOWProxyHandler::singleton,
v,

View File

@ -541,9 +541,9 @@ struct JSClass {
#define JSCLASS_INTERNAL_FLAG2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+2))
#define JSCLASS_INTERNAL_FLAG3 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3))
// Indicate whether the proto or ctor should be frozen.
#define JSCLASS_FREEZE_PROTO (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4))
#define JSCLASS_FREEZE_CTOR (1<<(JSCLASS_HIGH_FLAGS_SHIFT+5))
#define JSCLASS_IS_PROXY (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4))
// Bit 22 unused.
// Reserved for embeddings.
#define JSCLASS_USERBIT2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+6))
@ -616,6 +616,10 @@ struct Class
return this == js::FunctionClassPtr || call;
}
bool isProxy() const {
return flags & JSCLASS_IS_PROXY;
}
static size_t offsetOfFlags() { return offsetof(Class, flags); }
};

View File

@ -2908,29 +2908,28 @@ EmitDestructuringDecl(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp,
}
static bool
EmitDestructuringDecls(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn)
EmitDestructuringDecls(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp,
ParseNode *pattern)
{
ParseNode *pn2, *pn3;
DestructuringDeclEmitter emitter;
if (pn->isKind(PNK_ARRAY)) {
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
if (pn2->isKind(PNK_ELISION))
if (pattern->isKind(PNK_ARRAY)) {
for (ParseNode *element = pattern->pn_head; element; element = element->pn_next) {
if (element->isKind(PNK_ELISION))
continue;
emitter = (pn2->isKind(PNK_NAME))
? EmitDestructuringDecl
: EmitDestructuringDecls;
if (!emitter(cx, bce, prologOp, pn2))
return false;
}
} else {
JS_ASSERT(pn->isKind(PNK_OBJECT));
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
pn3 = pn2->pn_right;
emitter = pn3->isKind(PNK_NAME) ? EmitDestructuringDecl : EmitDestructuringDecls;
if (!emitter(cx, bce, prologOp, pn3))
DestructuringDeclEmitter emitter =
element->isKind(PNK_NAME) ? EmitDestructuringDecl : EmitDestructuringDecls;
if (!emitter(cx, bce, prologOp, element))
return false;
}
return true;
}
MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
for (ParseNode *member = pattern->pn_head; member; member = member->pn_next) {
ParseNode *target = member->pn_right;
DestructuringDeclEmitter emitter =
target->isKind(PNK_NAME) ? EmitDestructuringDecl : EmitDestructuringDecls;
if (!emitter(cx, bce, prologOp, target))
return false;
}
return true;
}
@ -3127,25 +3126,29 @@ EmitDestructuringOpsHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode
} else {
JS_ASSERT(pn->isKind(PNK_OBJECT));
JS_ASSERT(pn2->isKind(PNK_COLON));
pn3 = pn2->pn_left;
if (pn3->isKind(PNK_NUMBER)) {
if (!EmitNumberOp(cx, pn3->pn_dval, bce))
ParseNode *key = pn2->pn_left;
if (key->isKind(PNK_NUMBER)) {
if (!EmitNumberOp(cx, key->pn_dval, bce))
return false;
} else {
MOZ_ASSERT(key->isKind(PNK_STRING) || key->isKind(PNK_NAME));
PropertyName *name = key->pn_atom->asPropertyName();
// The parser already checked for atoms representing indexes and
// used PNK_NUMBER instead, but also watch for ids which TI treats
// as indexes for simpliciation of downstream analysis.
JS_ASSERT(pn3->isKind(PNK_STRING) || pn3->isKind(PNK_NAME));
jsid id = NameToId(pn3->pn_atom->asPropertyName());
// as indexes for simplification of downstream analysis.
jsid id = NameToId(name);
if (id != types::IdToTypeId(id)) {
if (!EmitTree(cx, bce, pn3))
if (!EmitTree(cx, bce, key))
return false;
} else {
if (!EmitAtomOp(cx, pn3, JSOP_GETPROP, bce))
if (!EmitAtomOp(cx, name, JSOP_GETPROP, bce))
return false;
doElemOp = false;
}
}
pn3 = pn2->pn_right;
}
@ -5894,11 +5897,8 @@ EmitObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
/*
* Emit code for {p:a, '%q':b, 2:c} that is equivalent to constructing
* a new object and in source order evaluating each property value and
* adding the property to the object, without invoking latent setters.
* We use the JSOP_NEWINIT and JSOP_INITELEM/JSOP_INITPROP bytecodes to
* ignore setters and to avoid dup'ing and popping the object as each
* property is added, as JSOP_SETELEM/JSOP_SETPROP would do.
* a new object and defining (in source order) each property on the object
* (or mutating the object's [[Prototype]], in the case of __proto__).
*/
ptrdiff_t offset = bce->offset();
if (!EmitNewInit(cx, bce, JSProto_Object))
@ -5917,16 +5917,6 @@ EmitObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
/* Handle __proto__ specially because it's not binary. */
if (pn2->isKind(PNK_MUTATEPROTO)) {
if (!EmitTree(cx, bce, pn2->pn_kid))
return false;
obj = nullptr;
if (!Emit1(cx, bce, JSOP_MUTATEPROTO))
return false;
continue;
}
/* Emit an index for t[2] for later consumption by JSOP_INITELEM. */
ParseNode *pn3 = pn2->pn_left;
bool isIndex = false;
@ -5971,13 +5961,22 @@ EmitObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return false;
} else {
JS_ASSERT(pn3->isKind(PNK_NAME) || pn3->isKind(PNK_STRING));
// If we have { __proto__: expr }, implement prototype mutation.
if (op == JSOP_INITPROP && pn3->pn_atom == cx->names().proto) {
obj = nullptr;
if (Emit1(cx, bce, JSOP_MUTATEPROTO) < 0)
return false;
continue;
}
jsatomid index;
if (!bce->makeAtomIndex(pn3->pn_atom, &index))
return false;
MOZ_ASSERT((op == JSOP_INITPROP_GETTER || op == JSOP_INITPROP_SETTER) ||
pn3->pn_atom != cx->names().proto,
"__proto__ shouldn't have been generated as an initprop");
MOZ_ASSERT(op == JSOP_INITPROP ||
op == JSOP_INITPROP_GETTER ||
op == JSOP_INITPROP_SETTER);
if (obj) {
JS_ASSERT(!obj->inDictionaryMode());

View File

@ -235,14 +235,6 @@ class FullParseHandler
return literal;
}
bool addPrototypeMutation(ParseNode *literal, uint32_t begin, ParseNode *expr) {
ParseNode *mutation = newUnary(PNK_MUTATEPROTO, JSOP_NOP, begin, expr);
if (!mutation)
return false;
literal->append(mutation);
return true;
}
bool addPropertyDefinition(ParseNode *literal, ParseNode *name, ParseNode *expr) {
ParseNode *propdef = newBinary(PNK_COLON, name, expr, JSOP_INITPROP);
if (!propdef)
@ -254,12 +246,7 @@ class FullParseHandler
bool addShorthandPropertyDefinition(ParseNode *literal, ParseNode *name) {
JS_ASSERT(literal->isArity(PN_LIST));
literal->pn_xflags |= PNX_DESTRUCT | PNX_NONCONST; // XXX why PNX_DESTRUCT?
ParseNode *propdef = newBinary(PNK_COLON, name, name, JSOP_INITPROP);
if (!propdef)
return false;
literal->append(propdef);
return true;
return addPropertyDefinition(literal, name, name);
}
bool addAccessorPropertyDefinition(ParseNode *literal, ParseNode *name, ParseNode *fn, JSOp op)

View File

@ -139,7 +139,6 @@ class UpvarCookie
F(FORHEAD) \
F(ARGSBODY) \
F(SPREAD) \
F(MUTATEPROTO) \
\
/* Unary operators. */ \
F(TYPEOF) \

View File

@ -3099,32 +3099,31 @@ Parser<FullParseHandler>::checkDestructuring(BindData<FullParseHandler> *data,
}
} else {
JS_ASSERT(left->isKind(PNK_OBJECT));
for (ParseNode *pair = left->pn_head; pair; pair = pair->pn_next) {
JS_ASSERT(pair->isKind(PNK_COLON));
ParseNode *pn = pair->pn_right;
for (ParseNode *member = left->pn_head; member; member = member->pn_next) {
MOZ_ASSERT(member->isKind(PNK_COLON));
ParseNode *expr = member->pn_right;
if (pn->isKind(PNK_ARRAY) || pn->isKind(PNK_OBJECT)) {
ok = checkDestructuring(data, pn, false);
if (expr->isKind(PNK_ARRAY) || expr->isKind(PNK_OBJECT)) {
ok = checkDestructuring(data, expr, false);
} else if (data) {
if (!pn->isKind(PNK_NAME)) {
report(ParseError, false, pn, JSMSG_NO_VARIABLE_NAME);
if (!expr->isKind(PNK_NAME)) {
report(ParseError, false, expr, JSMSG_NO_VARIABLE_NAME);
return false;
}
ok = bindDestructuringVar(data, pn);
ok = bindDestructuringVar(data, expr);
} else {
/*
* If right and left point to the same node, then this is
* destructuring shorthand ({x} = ...). In that case,
* identifierName was not used to parse 'x' so 'x' has not been
* officially linked to its def or registered in lexdeps. Do
* that now.
* If this is a destructuring shorthand ({x} = ...), then
* identifierName wasn't used to parse |x|. As a result, |x|
* hasn't been officially linked to its def or registered in
* lexdeps. Do that now.
*/
if (pair->pn_right == pair->pn_left) {
RootedPropertyName name(context, pn->pn_atom->asPropertyName());
if (!noteNameUse(name, pn))
if (member->pn_right == member->pn_left) {
RootedPropertyName name(context, expr->pn_atom->asPropertyName());
if (!noteNameUse(name, expr))
return false;
}
ok = checkAndMarkAsAssignmentLhs(pn, KeyedDestructuringAssignment);
ok = checkAndMarkAsAssignmentLhs(expr, KeyedDestructuringAssignment);
}
if (!ok)
return false;
@ -3659,8 +3658,9 @@ Parser<FullParseHandler>::letStatement()
JS_ASSERT_IF(pn, pn->isKind(PNK_LET) || pn->isKind(PNK_SEMI));
JS_ASSERT_IF(pn && pn->isKind(PNK_LET) && pn->pn_expr->getOp() != JSOP_POPNV,
pn->pn_expr->isOp(JSOP_POPN));
} else
} else {
pn = letDeclaration();
}
return pn;
}
@ -6807,7 +6807,6 @@ Parser<ParseHandler>::objectLiteral()
JSOp op = JSOP_INITPROP;
Node propname;
uint32_t begin;
switch (ltok) {
case TOK_NUMBER:
atom = DoubleToAtom(context, tokenStream.currentToken().number());
@ -6826,10 +6825,6 @@ Parser<ParseHandler>::objectLiteral()
propname = handler.newIdentifier(atom, pos());
if (!propname)
return null();
if (atom == context->names().proto) {
begin = pos().begin;
op = JSOP_MUTATEPROTO;
}
break;
}
@ -6898,7 +6893,7 @@ Parser<ParseHandler>::objectLiteral()
return null();
}
if (op == JSOP_INITPROP || op == JSOP_MUTATEPROTO) {
if (op == JSOP_INITPROP) {
TokenKind tt = tokenStream.getToken();
Node propexpr;
if (tt == TOK_COLON) {
@ -6914,15 +6909,11 @@ Parser<ParseHandler>::objectLiteral()
* so that we can later assume singleton objects delegate to
* the default Object.prototype.
*/
if (!handler.isConstant(propexpr) || op == JSOP_MUTATEPROTO)
if (!handler.isConstant(propexpr) || atom == context->names().proto)
handler.setListFlag(literal, PNX_NONCONST);
if (op == JSOP_MUTATEPROTO
? !handler.addPrototypeMutation(literal, begin, propexpr)
: !handler.addPropertyDefinition(literal, propname, propexpr))
{
if (!handler.addPropertyDefinition(literal, propname, propexpr))
return null();
}
}
#if JS_HAS_DESTRUCTURING_SHORTHAND
else if (ltok == TOK_NAME && (tt == TOK_COMMA || tt == TOK_RC)) {
@ -6968,7 +6959,7 @@ Parser<ParseHandler>::objectLiteral()
* any part of an accessor property.
*/
AssignmentType assignType;
if (op == JSOP_INITPROP || op == JSOP_MUTATEPROTO)
if (op == JSOP_INITPROP)
assignType = VALUE;
else if (op == JSOP_INITPROP_GETTER)
assignType = GET;

View File

@ -75,6 +75,7 @@ assertEq(exp.f(), 3);
assertEq(Object.keys(exp).join(), 'f');
assertAsmTypeFail(USE_ASM + "function f() { return 3 } return {1:f}");
assertAsmTypeFail(USE_ASM + "function f() { return 3 } return {__proto__:f}");
assertAsmTypeFail(USE_ASM + "function f() { return 3 } return {get x() {} }");
var exp = asmLink(asmCompile(USE_ASM + 'function internal() { return ((g()|0)+2)|0 } function f() { return 1 } function g() { return 2 } function h() { return internal()|0 } return {f:f,g1:g,h1:h}'));

View File

@ -549,7 +549,7 @@ ICMonitoredFallbackStub::initMonitoringChain(JSContext *cx, ICStubSpace *space)
}
bool
ICMonitoredFallbackStub::addMonitorStubForValue(JSContext *cx, HandleScript script, HandleValue val)
ICMonitoredFallbackStub::addMonitorStubForValue(JSContext *cx, JSScript *script, HandleValue val)
{
return fallbackMonitorStub_->addMonitorStubForValue(cx, script, val);
}
@ -1123,7 +1123,7 @@ ICProfiler_PushFunction::Compiler::generateStubCode(MacroAssembler &masm)
//
bool
ICTypeMonitor_Fallback::addMonitorStubForValue(JSContext *cx, HandleScript script, HandleValue val)
ICTypeMonitor_Fallback::addMonitorStubForValue(JSContext *cx, JSScript *script, HandleValue val)
{
bool wasDetachedMonitorChain = lastMonitorStubPtrAddr_ == nullptr;
JS_ASSERT_IF(wasDetachedMonitorChain, numOptimizedMonitorStubs_ == 0);
@ -1605,10 +1605,10 @@ DoCallNativeGetter(JSContext *cx, HandleFunction callee, HandleObject obj,
Value vp[2] = { ObjectValue(*callee.get()), ObjectValue(*obj.get()) };
AutoValueArray rootVp(cx, vp, 2);
if (!natfun(cx, 0, vp))
if (!natfun(cx, 0, rootVp.start()))
return false;
result.set(vp[0]);
result.set(rootVp[0]);
return true;
}
@ -3826,7 +3826,7 @@ TypedArrayRequiresFloatingPoint(TypedArrayObject *tarr)
}
static bool
TryAttachGetElemStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICGetElem_Fallback *stub,
TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_Fallback *stub,
HandleValue lhs, HandleValue rhs, HandleValue res)
{
bool isCallElem = (JSOp(*pc) == JSOP_CALLELEM);
@ -3904,8 +3904,10 @@ TryAttachGetElemStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICGetEl
// Check for NativeObject[id] shape-optimizable accesses.
if (rhs.isString()) {
if (!TryAttachNativeGetElemStub(cx, script, pc, stub, obj, rhs))
RootedScript rootedScript(cx, script);
if (!TryAttachNativeGetElemStub(cx, rootedScript, pc, stub, obj, rhs))
return false;
script = rootedScript;
}
}
@ -3919,7 +3921,7 @@ TryAttachGetElemStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICGetEl
return true;
#endif
Rooted<TypedArrayObject*> tarr(cx, &obj->as<TypedArrayObject>());
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
if (!cx->runtime()->jitSupportsFloatingPoint &&
(TypedArrayRequiresFloatingPoint(tarr) || rhs.isDouble()))
{
@ -3955,8 +3957,7 @@ static bool
DoGetElemFallback(JSContext *cx, BaselineFrame *frame, ICGetElem_Fallback *stub, HandleValue lhs,
HandleValue rhs, MutableHandleValue res)
{
RootedScript script(cx, frame->script());
jsbytecode *pc = stub->icEntry()->pc(script);
jsbytecode *pc = stub->icEntry()->pc(frame->script());
JSOp op = JSOp(*pc);
FallbackICSpew(cx, stub, "GetElem(%s)", js_CodeName[op]);
@ -3971,17 +3972,17 @@ DoGetElemFallback(JSContext *cx, BaselineFrame *frame, ICGetElem_Fallback *stub,
if (!GetElemOptimizedArguments(cx, frame, &lhsCopy, rhs, res, &isOptimizedArgs))
return false;
if (isOptimizedArgs)
types::TypeScript::Monitor(cx, script, pc, res);
types::TypeScript::Monitor(cx, frame->script(), pc, res);
}
if (!isOptimizedArgs) {
if (!GetElementOperation(cx, op, &lhsCopy, rhs, res))
return false;
types::TypeScript::Monitor(cx, script, pc, res);
types::TypeScript::Monitor(cx, frame->script(), pc, res);
}
// Add a type monitor stub for the resulting value.
if (!stub->addMonitorStubForValue(cx, script, res))
if (!stub->addMonitorStubForValue(cx, frame->script(), res))
return false;
if (stub->numOptimizedStubs() >= ICGetElem_Fallback::MAX_OPTIMIZED_STUBS) {
@ -3991,7 +3992,7 @@ DoGetElemFallback(JSContext *cx, BaselineFrame *frame, ICGetElem_Fallback *stub,
}
// Try to attach an optimized stub.
if (!TryAttachGetElemStub(cx, script, pc, stub, lhs, rhs, res))
if (!TryAttachGetElemStub(cx, frame->script(), pc, stub, lhs, rhs, res))
return false;
return true;
@ -5969,7 +5970,7 @@ ICGetIntrinsic_Constant::Compiler::generateStubCode(MacroAssembler &masm)
//
static bool
TryAttachLengthStub(JSContext *cx, HandleScript script, ICGetProp_Fallback *stub, HandleValue val,
TryAttachLengthStub(JSContext *cx, JSScript *script, ICGetProp_Fallback *stub, HandleValue val,
HandleValue res, bool *attached)
{
JS_ASSERT(!*attached);
@ -6284,15 +6285,13 @@ static bool
DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub,
MutableHandleValue val, MutableHandleValue res)
{
RootedScript script(cx, frame->script());
jsbytecode *pc = stub->icEntry()->pc(script);
jsbytecode *pc = stub->icEntry()->pc(frame->script());
JSOp op = JSOp(*pc);
FallbackICSpew(cx, stub, "GetProp(%s)", js_CodeName[op]);
JS_ASSERT(op == JSOP_GETPROP || op == JSOP_CALLPROP || op == JSOP_LENGTH || op == JSOP_GETXPROP);
RootedPropertyName name(cx, script->getName(pc));
RootedId id(cx, NameToId(name));
RootedPropertyName name(cx, frame->script()->getName(pc));
if (op == JSOP_LENGTH && val.isMagic(JS_OPTIMIZED_ARGUMENTS)) {
// Handle arguments.length access.
@ -6300,12 +6299,12 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub,
res.setInt32(frame->numActualArgs());
// Monitor result
types::TypeScript::Monitor(cx, script, pc, res);
if (!stub->addMonitorStubForValue(cx, script, res))
types::TypeScript::Monitor(cx, frame->script(), pc, res);
if (!stub->addMonitorStubForValue(cx, frame->script(), res))
return false;
bool attached = false;
if (!TryAttachLengthStub(cx, script, stub, val, res, &attached))
if (!TryAttachLengthStub(cx, frame->script(), stub, val, res, &attached))
return false;
JS_ASSERT(attached);
@ -6317,6 +6316,7 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub,
if (!obj)
return false;
RootedId id(cx, NameToId(name));
if (!JSObject::getGeneric(cx, obj, obj, id, res))
return false;
@ -6328,10 +6328,10 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub,
}
#endif
types::TypeScript::Monitor(cx, script, pc, res);
types::TypeScript::Monitor(cx, frame->script(), pc, res);
// Add a type monitor stub for the resulting value.
if (!stub->addMonitorStubForValue(cx, script, res))
if (!stub->addMonitorStubForValue(cx, frame->script(), res))
return false;
if (stub->numOptimizedStubs() >= ICGetProp_Fallback::MAX_OPTIMIZED_STUBS) {
@ -6342,12 +6342,14 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub,
bool attached = false;
if (op == JSOP_LENGTH) {
if (!TryAttachLengthStub(cx, script, stub, val, res, &attached))
if (!TryAttachLengthStub(cx, frame->script(), stub, val, res, &attached))
return false;
if (attached)
return true;
}
RootedScript script(cx, frame->script());
if (!TryAttachNativeGetPropStub(cx, script, pc, stub, name, val, res, &attached))
return false;
if (attached)
@ -7248,8 +7250,9 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub,
RootedShape oldShape(cx, obj->lastProperty());
uint32_t oldSlots = obj->numDynamicSlots();
if (op == JSOP_INITPROP && name != cx->names().proto) {
JS_ASSERT(obj->is<JSObject>());
if (op == JSOP_INITPROP) {
MOZ_ASSERT(name != cx->names().proto, "should have used JSOP_MUTATEPROTO");
MOZ_ASSERT(obj->is<JSObject>());
if (!DefineNativeProperty(cx, obj, id, rhs, nullptr, nullptr, JSPROP_ENUMERATE, 0, 0, 0))
return false;
} else if (op == JSOP_SETNAME || op == JSOP_SETGNAME) {
@ -7257,12 +7260,15 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub,
return false;
} else if (op == JSOP_SETALIASEDVAR) {
obj->as<ScopeObject>().setAliasedVar(cx, pc, name, rhs);
} else if (script->strict()) {
if (!js::SetProperty<true>(cx, obj, id, rhs))
return false;
} else {
if (!js::SetProperty<false>(cx, obj, id, rhs))
return false;
MOZ_ASSERT(op == JSOP_SETPROP);
if (script->strict()) {
if (!js::SetProperty<true>(cx, obj, id, rhs))
return false;
} else {
if (!js::SetProperty<false>(cx, obj, id, rhs))
return false;
}
}
// Leave the RHS on the stack.

View File

@ -917,7 +917,7 @@ class ICMonitoredFallbackStub : public ICFallbackStub
public:
bool initMonitoringChain(JSContext *cx, ICStubSpace *space);
bool addMonitorStubForValue(JSContext *cx, HandleScript script, HandleValue val);
bool addMonitorStubForValue(JSContext *cx, JSScript *script, HandleValue val);
inline ICTypeMonitor_Fallback *fallbackMonitorStub() const {
return fallbackMonitorStub_;
@ -1453,7 +1453,7 @@ class ICTypeMonitor_Fallback : public ICStub
// Create a new monitor stub for the type of the given value, and
// add it to this chain.
bool addMonitorStubForValue(JSContext *cx, HandleScript script, HandleValue val);
bool addMonitorStubForValue(JSContext *cx, JSScript *script, HandleValue val);
void resetMonitorStubChain(Zone *zone);

View File

@ -1528,17 +1528,10 @@ static void
GenerateProxyClassGuards(MacroAssembler &masm, Register object, Register scratchReg,
Label *failures)
{
Label success;
// Ensure that the incoming object has one of the magic class pointers, i.e,
// that it is one of an ObjectProxy, FunctionProxy, or OuterWindowProxy.
// This is equivalent to obj->is<ProxyObject>().
masm.branchTestObjClass(Assembler::Equal, object, scratchReg,
CallableProxyClassPtr, &success);
masm.branchTestObjClass(Assembler::Equal, object, scratchReg,
UncallableProxyClassPtr, &success);
masm.branchTestObjClass(Assembler::NotEqual, object, scratchReg,
OuterWindowProxyClassPtr, failures);
masm.bind(&success);
masm.loadObjClass(object, scratchReg);
masm.branchTest32(Assembler::Zero,
Address(scratchReg, Class::offsetOfFlags()),
Imm32(JSCLASS_IS_PROXY), failures);
}
bool

View File

@ -912,11 +912,11 @@ class MacroAssembler : public MacroAssemblerSpecific
// of the JSObject::isWrapper test performed in EmulatesUndefined. If none
// of the branches are taken, we can check class flags directly.
loadObjClass(objReg, scratch);
branchPtr(Assembler::Equal, scratch, ImmPtr(&ProxyObject::callableClass_), slowCheck);
branchPtr(Assembler::Equal, scratch, ImmPtr(&ProxyObject::uncallableClass_), slowCheck);
branchPtr(Assembler::Equal, scratch, ImmPtr(&OuterWindowProxyObject::class_), slowCheck);
Address flags(scratch, Class::offsetOfFlags());
test32(Address(scratch, Class::offsetOfFlags()), Imm32(JSCLASS_EMULATES_UNDEFINED));
branchTest32(Assembler::NonZero, flags, Imm32(JSCLASS_IS_PROXY), slowCheck);
test32(flags, Imm32(JSCLASS_EMULATES_UNDEFINED));
return truthy ? Assembler::Zero : Assembler::NonZero;
}

View File

@ -365,12 +365,12 @@ ArrayPopDense(JSContext *cx, HandleObject obj, MutableHandleValue rval)
Value argv[] = { UndefinedValue(), ObjectValue(*obj) };
AutoValueArray ava(cx, argv, 2);
if (!js::array_pop(cx, 0, argv))
if (!js::array_pop(cx, 0, ava.start()))
return false;
// If the result is |undefined|, the array was probably empty and we
// have to monitor the return value.
rval.set(argv[0]);
rval.set(ava[0]);
if (rval.isUndefined())
types::TypeScript::Monitor(cx, rval);
return true;
@ -383,10 +383,10 @@ ArrayPushDense(JSContext *cx, HandleObject obj, HandleValue v, uint32_t *length)
Value argv[] = { UndefinedValue(), ObjectValue(*obj), v };
AutoValueArray ava(cx, argv, 3);
if (!js::array_push(cx, 1, argv))
if (!js::array_push(cx, 1, ava.start()))
return false;
*length = argv[0].toInt32();
*length = ava[0].toInt32();
return true;
}
@ -399,12 +399,12 @@ ArrayShiftDense(JSContext *cx, HandleObject obj, MutableHandleValue rval)
Value argv[] = { UndefinedValue(), ObjectValue(*obj) };
AutoValueArray ava(cx, argv, 2);
if (!js::array_shift(cx, 0, argv))
if (!js::array_shift(cx, 0, ava.start()))
return false;
// If the result is |undefined|, the array was probably empty and we
// have to monitor the return value.
rval.set(argv[0]);
rval.set(ava[0]);
if (rval.isUndefined())
types::TypeScript::Monitor(cx, rval);
return true;
@ -426,9 +426,9 @@ ArrayConcatDense(JSContext *cx, HandleObject obj1, HandleObject obj2, HandleObje
Value argv[] = { UndefinedValue(), ObjectValue(*arr1), ObjectValue(*arr2) };
AutoValueArray ava(cx, argv, 3);
if (!js::array_concat(cx, 1, argv))
if (!js::array_concat(cx, 1, ava.start()))
return nullptr;
return &argv[0].toObject();
return &ava[0].toObject();
}
bool

View File

@ -1791,6 +1791,7 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
stack[stackDepth - 2].v = code->poppedValues[0];
break;
case JSOP_MUTATEPROTO:
case JSOP_INITPROP:
case JSOP_INITPROP_GETTER:
case JSOP_INITPROP_SETTER:

View File

@ -85,12 +85,13 @@ ExhaustiveTest(const char funcode[])
EVAL(CALL_CODES[ArgCount], v.address());
Rooted<ArgumentsObject*> argsobj(cx, &JSVAL_TO_OBJECT(v)->as<ArgumentsObject>());
Value elems[MAX_ELEMS];
Value elems_[MAX_ELEMS];
AutoValueArray elems(cx, elems_, MAX_ELEMS);
for (size_t i = 0; i <= ArgCount; i++) {
for (size_t j = 0; j <= ArgCount - i; j++) {
ClearElements(elems);
CHECK(argsobj->maybeGetElements(i, j, elems));
CHECK(argsobj->maybeGetElements(i, j, elems.start()));
for (size_t k = 0; k < j; k++)
CHECK_SAME(elems[k], INT_TO_JSVAL(i + k));
for (size_t k = j; k < MAX_ELEMS - 1; k++)
@ -103,10 +104,10 @@ ExhaustiveTest(const char funcode[])
}
static void
ClearElements(Value elems[MAX_ELEMS])
ClearElements(AutoValueArray &elems)
{
for (size_t i = 0; i < MAX_ELEMS - 1; i++)
elems[i] = NullValue();
elems[MAX_ELEMS - 1] = Int32Value(42);
for (size_t i = 0; i < elems.length() - 1; i++)
elems[i].setNull();
elems[elems.length() - 1].setInt32(42);
}
END_TEST(testArgumentsObject)

View File

@ -14,23 +14,19 @@
#include "vm/ProxyObject.h"
struct OuterWrapper : js::Wrapper
{
OuterWrapper() : Wrapper(0) {}
virtual bool isOuterWindow() {
return true;
}
virtual bool finalizeInBackground(JS::Value priv) {
return false;
}
static OuterWrapper singleton;
};
OuterWrapper
OuterWrapper::singleton;
const js::Class OuterWrapperClass =
PROXY_CLASS_WITH_EXT(
"Proxy",
0, /* additional slots */
0, /* additional class flags */
nullptr, /* call */
nullptr, /* construct */
PROXY_MAKE_EXT(
nullptr, /* outerObject */
js::proxy_innerObject,
nullptr, /* iteratorObject */
false /* isWrappedNative */
));
static JSObject *
wrap(JSContext *cx, JS::HandleObject toWrap, JS::HandleObject target)
@ -71,7 +67,10 @@ static const JSWrapObjectCallbacks WrapObjectCallbacks = {
BEGIN_TEST(testBug604087)
{
JS::RootedObject outerObj(cx, js::Wrapper::New(cx, global, global, &OuterWrapper::singleton));
js::WrapperOptions options;
options.setClass(&OuterWrapperClass);
options.setSingleton(true);
JS::RootedObject outerObj(cx, js::Wrapper::New(cx, global, global, &js::Wrapper::singleton, &options));
JS::RootedObject compartment2(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr, JS::FireOnNewGlobalHook));
JS::RootedObject compartment3(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr, JS::FireOnNewGlobalHook));
JS::RootedObject compartment4(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr, JS::FireOnNewGlobalHook));
@ -92,7 +91,7 @@ BEGIN_TEST(testBug604087)
JS::RootedObject next(cx);
{
JSAutoCompartment ac(cx, compartment2);
next = js::Wrapper::New(cx, compartment2, compartment2, &OuterWrapper::singleton);
next = js::Wrapper::New(cx, compartment2, compartment2, &js::Wrapper::singleton, &options);
CHECK(next);
}

View File

@ -55,12 +55,8 @@ constructHook(JSContext *cx, unsigned argc, jsval *vp)
BEGIN_TEST(testNewObject_1)
{
static const size_t N = 1000;
jsval argv[N];
// Root the global argv test array. Only the first 2 entries really need to
// be rooted, since we're only putting integers in the rest.
CHECK(JS_AddNamedValueRoot(cx, &argv[0], "argv0"));
CHECK(JS_AddNamedValueRoot(cx, &argv[1], "argv1"));
JS::Value argv_[N];
JS::AutoArrayRooter argv(cx, N, argv_);
JS::RootedValue v(cx);
EVAL("Array", v.address());
@ -76,8 +72,8 @@ BEGIN_TEST(testNewObject_1)
CHECK_EQUAL(len, 0);
// With one argument.
argv[0] = INT_TO_JSVAL(4);
obj = JS_New(cx, Array, 1, argv);
argv[0].setInt32(4);
obj = JS_New(cx, Array, 1, argv.start());
CHECK(obj);
rt = OBJECT_TO_JSVAL(obj);
CHECK(JS_IsArrayObject(cx, obj));
@ -86,8 +82,8 @@ BEGIN_TEST(testNewObject_1)
// With N arguments.
for (size_t i = 0; i < N; i++)
argv[i] = INT_TO_JSVAL(i);
obj = JS_New(cx, Array, N, argv);
argv[i].setInt32(i);
obj = JS_New(cx, Array, N, argv.start());
CHECK(obj);
rt = OBJECT_TO_JSVAL(obj);
CHECK(JS_IsArrayObject(cx, obj));
@ -107,14 +103,11 @@ BEGIN_TEST(testNewObject_1)
JS::RootedObject ctor(cx, JS_NewObject(cx, &cls, JS::NullPtr(), JS::NullPtr()));
CHECK(ctor);
JS::RootedValue rt2(cx, OBJECT_TO_JSVAL(ctor));
obj = JS_New(cx, ctor, 3, argv);
obj = JS_New(cx, ctor, 3, argv.start());
CHECK(obj);
CHECK(JS_GetElement(cx, ctor, 0, &v));
CHECK_SAME(v, JSVAL_ZERO);
JS_RemoveValueRoot(cx, &argv[0]);
JS_RemoveValueRoot(cx, &argv[1]);
return true;
}
END_TEST(testNewObject_1)

View File

@ -183,7 +183,8 @@ class AutoStringRooter : private AutoGCRooter {
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class AutoArrayRooter : private AutoGCRooter {
class AutoArrayRooter : private AutoGCRooter
{
public:
AutoArrayRooter(JSContext *cx, size_t len, Value *vec
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
@ -203,15 +204,28 @@ class AutoArrayRooter : private AutoGCRooter {
array = newArray;
}
Value *array;
Value *start() {
return array;
}
MutableHandleValue handleAt(size_t i)
{
size_t length() {
JS_ASSERT(tag_ >= 0);
return size_t(tag_);
}
MutableHandleValue handleAt(size_t i) {
JS_ASSERT(i < size_t(tag_));
return MutableHandleValue::fromMarkedLocation(&array[i]);
}
HandleValue handleAt(size_t i) const
{
HandleValue handleAt(size_t i) const {
JS_ASSERT(i < size_t(tag_));
return HandleValue::fromMarkedLocation(&array[i]);
}
MutableHandleValue operator[](size_t i) {
JS_ASSERT(i < size_t(tag_));
return MutableHandleValue::fromMarkedLocation(&array[i]);
}
HandleValue operator[](size_t i) const {
JS_ASSERT(i < size_t(tag_));
return HandleValue::fromMarkedLocation(&array[i]);
}
@ -219,9 +233,9 @@ class AutoArrayRooter : private AutoGCRooter {
friend void AutoGCRooter::trace(JSTracer *trc);
private:
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
Value *array;
js::SkipRoot skip;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
template<class T>

View File

@ -920,13 +920,19 @@ class AutoValueArray : public AutoGCRooter
Value *start() { return start_; }
unsigned length() const { return length_; }
MutableHandleValue handleAt(unsigned i)
{
MutableHandleValue handleAt(unsigned i) {
JS_ASSERT(i < length_);
return MutableHandleValue::fromMarkedLocation(&start_[i]);
}
HandleValue handleAt(unsigned i) const
{
HandleValue handleAt(unsigned i) const {
JS_ASSERT(i < length_);
return HandleValue::fromMarkedLocation(&start_[i]);
}
MutableHandleValue operator[](unsigned i) {
JS_ASSERT(i < length_);
return MutableHandleValue::fromMarkedLocation(&start_[i]);
}
HandleValue operator[](unsigned i) const {
JS_ASSERT(i < length_);
return HandleValue::fromMarkedLocation(&start_[i]);
}

View File

@ -226,6 +226,173 @@ JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *obj, const JSFunctionSpecWit
namespace js {
/*
* Helper Macros for creating JSClasses that function as proxies.
*
* NB: The macro invocation must be surrounded by braces, so as to
* allow for potention JSClass extensions.
*/
#define PROXY_MAKE_EXT(outerObject, innerObject, iteratorObject, \
isWrappedNative) \
{ \
outerObject, \
innerObject, \
iteratorObject, \
isWrappedNative, \
js::proxy_WeakmapKeyDelegate \
}
#define PROXY_CLASS_WITH_EXT(name, extraSlots, flags, callOp, constructOp, ext) \
{ \
name, \
js::Class::NON_NATIVE | \
JSCLASS_IS_PROXY | \
JSCLASS_IMPLEMENTS_BARRIERS | \
JSCLASS_HAS_RESERVED_SLOTS(js::PROXY_MINIMUM_SLOTS + (extraSlots)) | \
flags, \
JS_PropertyStub, /* addProperty */ \
JS_DeletePropertyStub, /* delProperty */ \
JS_PropertyStub, /* getProperty */ \
JS_StrictPropertyStub, /* setProperty */ \
JS_EnumerateStub, \
JS_ResolveStub, \
js::proxy_Convert, \
js::proxy_Finalize, /* finalize */ \
callOp, /* call */ \
js::proxy_HasInstance, /* hasInstance */ \
constructOp, /* construct */ \
js::proxy_Trace, /* trace */ \
ext, \
{ \
js::proxy_LookupGeneric, \
js::proxy_LookupProperty, \
js::proxy_LookupElement, \
js::proxy_LookupSpecial, \
js::proxy_DefineGeneric, \
js::proxy_DefineProperty, \
js::proxy_DefineElement, \
js::proxy_DefineSpecial, \
js::proxy_GetGeneric, \
js::proxy_GetProperty, \
js::proxy_GetElement, \
js::proxy_GetSpecial, \
js::proxy_SetGeneric, \
js::proxy_SetProperty, \
js::proxy_SetElement, \
js::proxy_SetSpecial, \
js::proxy_GetGenericAttributes, \
js::proxy_SetGenericAttributes, \
js::proxy_DeleteProperty, \
js::proxy_DeleteElement, \
js::proxy_DeleteSpecial, \
js::proxy_Watch, js::proxy_Unwatch, \
js::proxy_Slice, \
nullptr, /* enumerate */ \
nullptr, /* thisObject */ \
} \
}
#define PROXY_CLASS_DEF(name, extraSlots, flags, callOp, constructOp) \
PROXY_CLASS_WITH_EXT(name, extraSlots, flags, callOp, constructOp, \
PROXY_MAKE_EXT( \
nullptr, /* outerObject */ \
nullptr, /* innerObject */ \
nullptr, /* iteratorObject */ \
false /* isWrappedNative */ \
))
/*
* Proxy stubs, similar to JS_*Stub, for embedder proxy class definitions.
*
* NB: Should not be called directly.
*/
extern JS_FRIEND_API(bool)
proxy_LookupGeneric(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleObject objp,
JS::MutableHandle<Shape*> propp);
extern JS_FRIEND_API(bool)
proxy_LookupProperty(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
extern JS_FRIEND_API(bool)
proxy_LookupElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleObject objp,
JS::MutableHandle<Shape*> propp);
extern JS_FRIEND_API(bool)
proxy_LookupSpecial(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid,
JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
extern JS_FRIEND_API(bool)
proxy_DefineGeneric(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
extern JS_FRIEND_API(bool)
proxy_DefineProperty(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
JS::HandleValue value, JSPropertyOp getter, JSStrictPropertyOp setter,
unsigned attrs);
extern JS_FRIEND_API(bool)
proxy_DefineElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
extern JS_FRIEND_API(bool)
proxy_DefineSpecial(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid,
JS::HandleValue value, JSPropertyOp getter, JSStrictPropertyOp setter,
unsigned attrs);
extern JS_FRIEND_API(bool)
proxy_GetGeneric(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
JS::MutableHandleValue vp);
extern JS_FRIEND_API(bool)
proxy_GetProperty(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver,
JS::Handle<PropertyName*> name, JS::MutableHandleValue vp);
extern JS_FRIEND_API(bool)
proxy_GetElement(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, uint32_t index,
JS::MutableHandleValue vp);
extern JS_FRIEND_API(bool)
proxy_GetSpecial(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver,
HandleSpecialId sid, JS::MutableHandleValue vp);
extern JS_FRIEND_API(bool)
proxy_SetGeneric(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandleValue bp, bool strict);
extern JS_FRIEND_API(bool)
proxy_SetProperty(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
JS::MutableHandleValue bp, bool strict);
extern JS_FRIEND_API(bool)
proxy_SetElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleValue vp,
bool strict);
extern JS_FRIEND_API(bool)
proxy_SetSpecial(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid,
JS::MutableHandleValue vp, bool strict);
extern JS_FRIEND_API(bool)
proxy_GetGenericAttributes(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned *attrsp);
extern JS_FRIEND_API(bool)
proxy_SetGenericAttributes(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned *attrsp);
extern JS_FRIEND_API(bool)
proxy_DeleteProperty(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
bool *succeeded);
extern JS_FRIEND_API(bool)
proxy_DeleteElement(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *succeeded);
extern JS_FRIEND_API(bool)
proxy_DeleteSpecial(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid, bool *succeeded);
extern JS_FRIEND_API(void)
proxy_Trace(JSTracer *trc, JSObject *obj);
extern JS_FRIEND_API(JSObject *)
proxy_WeakmapKeyDelegate(JSObject *obj);
extern JS_FRIEND_API(bool)
proxy_Convert(JSContext *cx, JS::HandleObject proxy, JSType hint, JS::MutableHandleValue vp);
extern JS_FRIEND_API(void)
proxy_Finalize(FreeOp *fop, JSObject *obj);
extern JS_FRIEND_API(bool)
proxy_HasInstance(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleValue v, bool *bp);
extern JS_FRIEND_API(bool)
proxy_Call(JSContext *cx, unsigned argc, JS::Value *vp);
extern JS_FRIEND_API(bool)
proxy_Construct(JSContext *cx, unsigned argc, JS::Value *vp);
extern JS_FRIEND_API(JSObject *)
proxy_innerObject(JSContext *cx, JS::HandleObject obj);
extern JS_FRIEND_API(bool)
proxy_Watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable);
extern JS_FRIEND_API(bool)
proxy_Unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
extern JS_FRIEND_API(bool)
proxy_Slice(JSContext *cx, JS::HandleObject proxy, uint32_t begin, uint32_t end,
JS::HandleObject result);
/*
* A class of objects that return source code on demand.
*

View File

@ -130,7 +130,7 @@ fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValu
* Censor the caller if we don't have full access to it.
*/
RootedObject caller(cx, &vp.toObject());
if (caller->is<WrapperObject>() && !Wrapper::wrapperHandler(caller)->isSafeToUnwrap()) {
if (caller->is<WrapperObject>() && Wrapper::wrapperHandler(caller)->hasSecurityPolicy()) {
vp.setNull();
} else if (caller->is<JSFunction>()) {
JSFunction *callerFun = &caller->as<JSFunction>();

View File

@ -1254,8 +1254,7 @@ stopiter_hasInstance(JSContext *cx, HandleObject obj, MutableHandleValue v, bool
const Class StopIterationObject::class_ = {
"StopIteration",
JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration) |
JSCLASS_FREEZE_PROTO,
JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */

View File

@ -2584,14 +2584,6 @@ js::DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey ke
goto bad;
}
if (clasp->flags & (JSCLASS_FREEZE_PROTO|JSCLASS_FREEZE_CTOR)) {
JS_ASSERT_IF(ctor == proto, !(clasp->flags & JSCLASS_FREEZE_CTOR));
if (proto && (clasp->flags & JSCLASS_FREEZE_PROTO) && !JSObject::freeze(cx, proto))
goto bad;
if (ctor && (clasp->flags & JSCLASS_FREEZE_CTOR) && !JSObject::freeze(cx, ctor))
goto bad;
}
/* If this is a standard class, cache its prototype. */
if (!cached && key != JSProto_Null)
SetClassObject(obj, key, ctor, proto);

View File

@ -79,7 +79,7 @@ js::assertEnteredPolicy(JSContext *cx, JSObject *proxy, jsid id)
BaseProxyHandler::BaseProxyHandler(const void *family)
: mFamily(family),
mHasPrototype(false),
mHasPolicy(false)
mHasSecurityPolicy(false)
{
}
@ -976,7 +976,7 @@ ScriptedIndirectProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObjec
return false;
if (!js_IsCallable(fval))
return BaseProxyHandler::get(cx, proxy, receiver, id, vp);
return Trap(cx, handler, fval, 2, argv, vp);
return Trap(cx, handler, fval, 2, ava.start(), vp);
}
bool
@ -996,7 +996,7 @@ ScriptedIndirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObjec
return false;
if (!js_IsCallable(fval))
return BaseProxyHandler::set(cx, proxy, receiver, id, strict, vp);
return Trap(cx, handler, fval, 3, argv, &value);
return Trap(cx, handler, fval, 3, ava.start(), &value);
}
bool
@ -2781,15 +2781,15 @@ Proxy::slice(JSContext *cx, HandleObject proxy, uint32_t begin, uint32_t end,
return handler->slice(cx, proxy, begin, end, result);
}
static JSObject *
proxy_innerObject(JSContext *cx, HandleObject obj)
JSObject *
js::proxy_innerObject(JSContext *cx, HandleObject obj)
{
return obj->as<ProxyObject>().private_().toObjectOrNull();
}
static bool
proxy_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleObject objp, MutableHandleShape propp)
bool
js::proxy_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleObject objp, MutableHandleShape propp)
{
bool found;
if (!Proxy::has(cx, obj, id, &found))
@ -2805,17 +2805,17 @@ proxy_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
return true;
}
static bool
proxy_LookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
MutableHandleObject objp, MutableHandleShape propp)
bool
js::proxy_LookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
MutableHandleObject objp, MutableHandleShape propp)
{
RootedId id(cx, NameToId(name));
return proxy_LookupGeneric(cx, obj, id, objp, propp);
}
static bool
proxy_LookupElement(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleObject objp, MutableHandleShape propp)
bool
js::proxy_LookupElement(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleObject objp, MutableHandleShape propp)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
@ -2823,17 +2823,17 @@ proxy_LookupElement(JSContext *cx, HandleObject obj, uint32_t index,
return proxy_LookupGeneric(cx, obj, id, objp, propp);
}
static bool
proxy_LookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
MutableHandleObject objp, MutableHandleShape propp)
bool
js::proxy_LookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
MutableHandleObject objp, MutableHandleShape propp)
{
RootedId id(cx, SPECIALID_TO_JSID(sid));
return proxy_LookupGeneric(cx, obj, id, objp, propp);
}
static bool
proxy_DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
bool
js::proxy_DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
Rooted<PropertyDescriptor> desc(cx);
desc.object().set(obj);
@ -2845,17 +2845,17 @@ proxy_DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue va
return Proxy::defineProperty(cx, obj, id, &desc);
}
static bool
proxy_DefineProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
bool
js::proxy_DefineProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
Rooted<jsid> id(cx, NameToId(name));
return proxy_DefineGeneric(cx, obj, id, value, getter, setter, attrs);
}
static bool
proxy_DefineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
bool
js::proxy_DefineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
@ -2863,32 +2863,32 @@ proxy_DefineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue
return proxy_DefineGeneric(cx, obj, id, value, getter, setter, attrs);
}
static bool
proxy_DefineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
bool
js::proxy_DefineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
return proxy_DefineGeneric(cx, obj, id, value, getter, setter, attrs);
}
static bool
proxy_GetGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp)
bool
js::proxy_GetGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp)
{
return Proxy::get(cx, obj, receiver, id, vp);
}
static bool
proxy_GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name,
MutableHandleValue vp)
bool
js::proxy_GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name,
MutableHandleValue vp)
{
Rooted<jsid> id(cx, NameToId(name));
return proxy_GetGeneric(cx, obj, receiver, id, vp);
}
static bool
proxy_GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index,
MutableHandleValue vp)
bool
js::proxy_GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index,
MutableHandleValue vp)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
@ -2896,32 +2896,32 @@ proxy_GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_
return proxy_GetGeneric(cx, obj, receiver, id, vp);
}
static bool
proxy_GetSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid,
MutableHandleValue vp)
bool
js::proxy_GetSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid,
MutableHandleValue vp)
{
Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
return proxy_GetGeneric(cx, obj, receiver, id, vp);
}
static bool
proxy_SetGeneric(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleValue vp, bool strict)
bool
js::proxy_SetGeneric(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleValue vp, bool strict)
{
return Proxy::set(cx, obj, obj, id, strict, vp);
}
static bool
proxy_SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
MutableHandleValue vp, bool strict)
bool
js::proxy_SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
MutableHandleValue vp, bool strict)
{
Rooted<jsid> id(cx, NameToId(name));
return proxy_SetGeneric(cx, obj, id, vp, strict);
}
static bool
proxy_SetElement(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleValue vp, bool strict)
bool
js::proxy_SetElement(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleValue vp, bool strict)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
@ -2929,16 +2929,16 @@ proxy_SetElement(JSContext *cx, HandleObject obj, uint32_t index,
return proxy_SetGeneric(cx, obj, id, vp, strict);
}
static bool
proxy_SetSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
MutableHandleValue vp, bool strict)
bool
js::proxy_SetSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
MutableHandleValue vp, bool strict)
{
Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
return proxy_SetGeneric(cx, obj, id, vp, strict);
}
static bool
proxy_GetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
bool
js::proxy_GetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
{
Rooted<PropertyDescriptor> desc(cx);
if (!Proxy::getOwnPropertyDescriptor(cx, obj, id, &desc, 0))
@ -2947,8 +2947,8 @@ proxy_GetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigne
return true;
}
static bool
proxy_SetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
bool
js::proxy_SetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
{
/* Lookup the current property descriptor so we have setter/getter/value. */
Rooted<PropertyDescriptor> desc(cx);
@ -2968,15 +2968,15 @@ proxy_DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succeede
return js_SuppressDeletedProperty(cx, obj, id);
}
static bool
proxy_DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, bool *succeeded)
bool
js::proxy_DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, bool *succeeded)
{
RootedId id(cx, NameToId(name));
return proxy_DeleteGeneric(cx, obj, id, succeeded);
}
static bool
proxy_DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, bool *succeeded)
bool
js::proxy_DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, bool *succeeded)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
@ -2984,13 +2984,20 @@ proxy_DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, bool *succe
return proxy_DeleteGeneric(cx, obj, id, succeeded);
}
static bool
proxy_DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, bool *succeeded)
bool
js::proxy_DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, bool *succeeded)
{
RootedId id(cx, SPECIALID_TO_JSID(sid));
return proxy_DeleteGeneric(cx, obj, id, succeeded);
}
void
js::proxy_Trace(JSTracer *trc, JSObject *obj)
{
JS_ASSERT(obj->is<ProxyObject>());
ProxyObject::trace(trc, obj);
}
/* static */ void
ProxyObject::trace(JSTracer *trc, JSObject *obj)
{
@ -3022,31 +3029,39 @@ ProxyObject::trace(JSTracer *trc, JSObject *obj)
*/
if (!proxy->is<CrossCompartmentWrapperObject>())
MarkSlot(trc, proxy->slotOfExtra(1), "extra1");
/*
* Allow for people to add extra slots to "proxy" classes, without allowing
* them to set their own trace hook. Trace the extras.
*/
unsigned numSlots = JSCLASS_RESERVED_SLOTS(proxy->getClass());
for (unsigned i = PROXY_MINIMUM_SLOTS; i < numSlots; i++)
MarkSlot(trc, proxy->slotOfClassSpecific(i), "class-specific");
}
static JSObject *
proxy_WeakmapKeyDelegate(JSObject *obj)
JSObject *
js::proxy_WeakmapKeyDelegate(JSObject *obj)
{
JS_ASSERT(obj->is<ProxyObject>());
return obj->as<ProxyObject>().handler()->weakmapKeyDelegate(obj);
}
static bool
proxy_Convert(JSContext *cx, HandleObject proxy, JSType hint, MutableHandleValue vp)
bool
js::proxy_Convert(JSContext *cx, HandleObject proxy, JSType hint, MutableHandleValue vp)
{
JS_ASSERT(proxy->is<ProxyObject>());
return Proxy::defaultValue(cx, proxy, hint, vp);
}
static void
proxy_Finalize(FreeOp *fop, JSObject *obj)
void
js::proxy_Finalize(FreeOp *fop, JSObject *obj)
{
JS_ASSERT(obj->is<ProxyObject>());
obj->as<ProxyObject>().handler()->finalize(fop, obj);
}
static bool
proxy_HasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool *bp)
bool
js::proxy_HasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool *bp)
{
bool b;
if (!Proxy::hasInstance(cx, proxy, v, &b))
@ -3055,8 +3070,8 @@ proxy_HasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool
return true;
}
static bool
proxy_Call(JSContext *cx, unsigned argc, Value *vp)
bool
js::proxy_Call(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject proxy(cx, &args.callee());
@ -3064,8 +3079,8 @@ proxy_Call(JSContext *cx, unsigned argc, Value *vp)
return Proxy::call(cx, proxy, args);
}
static bool
proxy_Construct(JSContext *cx, unsigned argc, Value *vp)
bool
js::proxy_Construct(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject proxy(cx, &args.callee());
@ -3073,81 +3088,31 @@ proxy_Construct(JSContext *cx, unsigned argc, Value *vp)
return Proxy::construct(cx, proxy, args);
}
static bool
proxy_Watch(JSContext *cx, HandleObject obj, HandleId id, HandleObject callable)
bool
js::proxy_Watch(JSContext *cx, HandleObject obj, HandleId id, HandleObject callable)
{
return Proxy::watch(cx, obj, id, callable);
}
static bool
proxy_Unwatch(JSContext *cx, HandleObject obj, HandleId id)
bool
js::proxy_Unwatch(JSContext *cx, HandleObject obj, HandleId id)
{
return Proxy::unwatch(cx, obj, id);
}
static bool
proxy_Slice(JSContext *cx, HandleObject proxy, uint32_t begin, uint32_t end,
HandleObject result)
bool
js::proxy_Slice(JSContext *cx, HandleObject proxy, uint32_t begin, uint32_t end,
HandleObject result)
{
return Proxy::slice(cx, proxy, begin, end, result);
}
#define PROXY_CLASS_EXT \
{ \
nullptr, /* outerObject */ \
nullptr, /* innerObject */ \
nullptr, /* iteratorObject */ \
false, /* isWrappedNative */ \
proxy_WeakmapKeyDelegate \
}
#define PROXY_CLASS(callOp, constructOp) { \
"Proxy", \
Class::NON_NATIVE | \
JSCLASS_IMPLEMENTS_BARRIERS | \
JSCLASS_HAS_RESERVED_SLOTS(4) | \
JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy), \
JS_PropertyStub, /* addProperty */ \
JS_DeletePropertyStub, /* delProperty */ \
JS_PropertyStub, /* getProperty */ \
JS_StrictPropertyStub, /* setProperty */ \
JS_EnumerateStub, \
JS_ResolveStub, \
proxy_Convert, \
proxy_Finalize, /* finalize */ \
callOp, /* call */ \
proxy_HasInstance, /* hasInstance */ \
constructOp, /* construct */ \
ProxyObject::trace, /* trace */ \
PROXY_CLASS_EXT, \
{ \
proxy_LookupGeneric, \
proxy_LookupProperty, \
proxy_LookupElement, \
proxy_LookupSpecial, \
proxy_DefineGeneric, \
proxy_DefineProperty, \
proxy_DefineElement, \
proxy_DefineSpecial, \
proxy_GetGeneric, \
proxy_GetProperty, \
proxy_GetElement, \
proxy_GetSpecial, \
proxy_SetGeneric, \
proxy_SetProperty, \
proxy_SetElement, \
proxy_SetSpecial, \
proxy_GetGenericAttributes, \
proxy_SetGenericAttributes, \
proxy_DeleteProperty, \
proxy_DeleteElement, \
proxy_DeleteSpecial, \
proxy_Watch, proxy_Unwatch, \
proxy_Slice, \
nullptr, /* enumerate */ \
nullptr, /* thisObject */ \
} \
}
#define PROXY_CLASS(callOp, constructOp) \
PROXY_CLASS_DEF("Proxy", \
0, /* additional slots */ \
JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy), \
callOp, \
constructOp)
const Class js::ProxyObject::uncallableClass_ = PROXY_CLASS(nullptr, nullptr);
const Class js::ProxyObject::callableClass_ = PROXY_CLASS(proxy_Call, proxy_Construct);
@ -3155,59 +3120,6 @@ const Class js::ProxyObject::callableClass_ = PROXY_CLASS(proxy_Call, proxy_Cons
const Class* const js::CallableProxyClassPtr = &ProxyObject::callableClass_;
const Class* const js::UncallableProxyClassPtr = &ProxyObject::uncallableClass_;
const Class js::OuterWindowProxyObject::class_ = {
"Proxy",
Class::NON_NATIVE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(4),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
proxy_Finalize, /* finalize */
nullptr, /* call */
nullptr, /* hasInstance */
nullptr, /* construct */
ProxyObject::trace, /* trace */
{
nullptr, /* outerObject */
proxy_innerObject,
nullptr, /* iteratorObject */
false, /* isWrappedNative */
proxy_WeakmapKeyDelegate
},
{
proxy_LookupGeneric,
proxy_LookupProperty,
proxy_LookupElement,
proxy_LookupSpecial,
proxy_DefineGeneric,
proxy_DefineProperty,
proxy_DefineElement,
proxy_DefineSpecial,
proxy_GetGeneric,
proxy_GetProperty,
proxy_GetElement,
proxy_GetSpecial,
proxy_SetGeneric,
proxy_SetProperty,
proxy_SetElement,
proxy_SetSpecial,
proxy_GetGenericAttributes,
proxy_SetGenericAttributes,
proxy_DeleteProperty,
proxy_DeleteElement,
proxy_DeleteSpecial,
proxy_Watch, proxy_Unwatch,
proxy_Slice,
nullptr, /* enumerate */
nullptr, /* thisObject */
}
};
const Class* const js::OuterWindowProxyClassPtr = &OuterWindowProxyObject::class_;
JS_FRIEND_API(JSObject *)
js::NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, JSObject *proto_,
JSObject *parent_, const ProxyOptions &options)
@ -3222,11 +3134,8 @@ ProxyObject::renew(JSContext *cx, BaseProxyHandler *handler, Value priv)
JS_ASSERT_IF(IsCrossCompartmentWrapper(this), IsDeadProxyObject(this));
JS_ASSERT(getParent() == cx->global());
JS_ASSERT(getClass() == &uncallableClass_);
JS_ASSERT(!getClass()->ext.innerObject);
JS_ASSERT(getTaggedProto().isLazy());
#ifdef DEBUG
AutoSuppressGC suppressGC(cx);
JS_ASSERT(!handler->isOuterWindow());
#endif
setSlot(HANDLER_SLOT, PrivateValue(handler));
setCrossCompartmentSlot(PRIVATE_SLOT, priv);
@ -3251,7 +3160,7 @@ proxy(JSContext *cx, unsigned argc, jsval *vp)
return false;
RootedValue priv(cx, ObjectValue(*target));
ProxyOptions options;
options.setCallable(target->isCallable());
options.selectDefaultClass(target->isCallable());
ProxyObject *proxy =
ProxyObject::New(cx, &ScriptedDirectProxyHandler::singleton,
priv, TaggedProto(TaggedProto::LazyProto), cx->global(),
@ -3336,7 +3245,7 @@ proxy_createFunction(JSContext *cx, unsigned argc, Value *vp)
RootedValue priv(cx, ObjectValue(*handler));
ProxyOptions options;
options.setCallable(true);
options.selectDefaultClass(true);
JSObject *proxy =
ProxyObject::New(cx, &ScriptedIndirectProxyHandler::singleton,
priv, TaggedProto(proto), parent, options);

View File

@ -89,11 +89,19 @@ class JS_FRIEND_API(BaseProxyHandler)
{
const void *mFamily;
bool mHasPrototype;
bool mHasPolicy;
/*
* All proxies indicate whether they have any sort of interesting security
* policy that might prevent the caller from doing something it wants to
* the object. In the case of wrappers, this distinction is used to
* determine whether the caller may strip off the wrapper if it so desires.
*/
bool mHasSecurityPolicy;
protected:
// Subclasses may set this in their constructor.
void setHasPrototype(bool aHasPrototype) { mHasPrototype = aHasPrototype; }
void setHasPolicy(bool aHasPolicy) { mHasPolicy = aHasPolicy; }
void setHasSecurityPolicy(bool aHasPolicy) { mHasSecurityPolicy = aHasPolicy; }
public:
explicit BaseProxyHandler(const void *family);
@ -103,8 +111,8 @@ class JS_FRIEND_API(BaseProxyHandler)
return mHasPrototype;
}
bool hasPolicy() {
return mHasPolicy;
bool hasSecurityPolicy() {
return mHasSecurityPolicy;
}
inline const void *family() {
@ -114,10 +122,6 @@ class JS_FRIEND_API(BaseProxyHandler)
return offsetof(BaseProxyHandler, mFamily);
}
virtual bool isOuterWindow() {
return false;
}
virtual bool finalizeInBackground(Value priv) {
/*
* Called on creation of a proxy to determine whether its finalize
@ -329,13 +333,10 @@ class Proxy
// Use these in places where you don't want to #include vm/ProxyObject.h.
extern JS_FRIEND_DATA(const js::Class* const) CallableProxyClassPtr;
extern JS_FRIEND_DATA(const js::Class* const) UncallableProxyClassPtr;
extern JS_FRIEND_DATA(const js::Class* const) OuterWindowProxyClassPtr;
inline bool IsProxyClass(const Class *clasp)
{
return clasp == CallableProxyClassPtr ||
clasp == UncallableProxyClassPtr ||
clasp == OuterWindowProxyClassPtr;
return clasp->isProxy();
}
inline bool IsProxy(JSObject *obj)
@ -362,9 +363,10 @@ inline bool IsScriptedProxy(JSObject *obj)
* needs to store one slot's worth of data doesn't need to branch on what sort
* of object it has.
*/
const uint32_t PROXY_PRIVATE_SLOT = 0;
const uint32_t PROXY_HANDLER_SLOT = 1;
const uint32_t PROXY_EXTRA_SLOT = 2;
const uint32_t PROXY_PRIVATE_SLOT = 0;
const uint32_t PROXY_HANDLER_SLOT = 1;
const uint32_t PROXY_EXTRA_SLOT = 2;
const uint32_t PROXY_MINIMUM_SLOTS = 4;
inline BaseProxyHandler *
GetProxyHandler(JSObject *obj)
@ -410,16 +412,17 @@ SetProxyExtra(JSObject *obj, size_t n, const Value &extra)
}
class MOZ_STACK_CLASS ProxyOptions {
public:
ProxyOptions() : callable_(false),
singleton_(false)
protected:
/* protected constructor for subclass */
ProxyOptions(bool singletonArg, const Class *claspArg)
: singleton_(singletonArg),
clasp_(claspArg)
{}
bool callable() const { return callable_; }
ProxyOptions &setCallable(bool flag) {
callable_ = flag;
return *this;
}
public:
ProxyOptions() : singleton_(false),
clasp_(UncallableProxyClassPtr)
{}
bool singleton() const { return singleton_; }
ProxyOptions &setSingleton(bool flag) {
@ -427,9 +430,22 @@ class MOZ_STACK_CLASS ProxyOptions {
return *this;
}
const Class *clasp() const {
return clasp_;
}
ProxyOptions &setClass(const Class *claspArg) {
clasp_ = claspArg;
return *this;
}
ProxyOptions &selectDefaultClass(bool callable) {
const Class *classp = callable? CallableProxyClassPtr :
UncallableProxyClassPtr;
return setClass(classp);
}
private:
bool callable_;
bool singleton_;
const Class *clasp_;
};
JS_FRIEND_API(JSObject *)
@ -449,8 +465,8 @@ class JS_FRIEND_API(AutoEnterPolicy)
: context(nullptr)
#endif
{
allow = handler->hasPolicy() ? handler->enter(cx, wrapper, id, act, &rv)
: true;
allow = handler->hasSecurityPolicy() ? handler->enter(cx, wrapper, id, act, &rv)
: true;
recordEnter(cx, wrapper, id);
// We want to throw an exception if all of the following are true:
// * The policy disallowed access.

View File

@ -153,17 +153,16 @@ class NodeBuilder
bool saveLoc; /* save source location information? */
char const *src; /* source filename or null */
RootedValue srcval; /* source filename JS value or null */
Value callbacks[AST_LIMIT]; /* user-specified callbacks */
AutoValueArray callbacksRoots; /* for rooting |callbacks| */
Value callbacks_[AST_LIMIT]; /* user-specified callbacks */
AutoValueArray callbacks; /* for rooting |callbacks| */
RootedValue userv; /* user-specified builder object or null */
RootedValue undefinedVal; /* a rooted undefined val, used by opt() */
public:
NodeBuilder(JSContext *c, bool l, char const *s)
: cx(c), tokenStream(nullptr), saveLoc(l), src(s), srcval(c),
callbacksRoots(c, callbacks, AST_LIMIT), userv(c), undefinedVal(c, UndefinedValue())
callbacks(c, callbacks_, AST_LIMIT), userv(c)
{
MakeRangeGCSafe(callbacks, mozilla::ArrayLength(callbacks));
MakeRangeGCSafe(callbacks.start(), callbacks.length());
}
bool init(HandleObject userobj = js::NullPtr()) {
@ -206,7 +205,7 @@ class NodeBuilder
return false;
}
callbacks[i] = funv;
callbacks[i].set(funv);
}
return true;
@ -312,12 +311,12 @@ class NodeBuilder
}
// WARNING: Returning a Handle is non-standard, but it works in this case
// because both |v| and |undefinedVal| are definitely rooted on a previous
// stack frame (i.e. we're just choosing between two already-rooted
// values).
// because both |v| and |UndefinedHandleValue| are definitely rooted on a
// previous stack frame (i.e. we're just choosing between two
// already-rooted values).
HandleValue opt(HandleValue v) {
JS_ASSERT_IF(v.isMagic(), v.whyMagic() == JS_SERIALIZE_NO_NODE);
return v.isMagic(JS_SERIALIZE_NO_NODE) ? undefinedVal : v;
return v.isMagic(JS_SERIALIZE_NO_NODE) ? JS::UndefinedHandleValue : v;
}
bool atomValue(const char *s, MutableHandleValue dst) {

View File

@ -39,16 +39,21 @@ Wrapper::defaultValue(JSContext *cx, HandleObject proxy, JSType hint, MutableHan
}
JSObject *
Wrapper::New(JSContext *cx, JSObject *obj, JSObject *parent, Wrapper *handler)
Wrapper::New(JSContext *cx, JSObject *obj, JSObject *parent, Wrapper *handler,
const WrapperOptions *options)
{
JS_ASSERT(parent);
AutoMarkInDeadZone amd(cx->zone());
RootedValue priv(cx, ObjectValue(*obj));
ProxyOptions options;
options.setCallable(obj->isCallable());
return NewProxyObject(cx, handler, priv, TaggedProto::LazyProto, parent, options);
mozilla::Maybe<WrapperOptions> opts;
if (!options) {
opts.construct();
opts.ref().selectDefaultClass(obj->isCallable());
options = opts.addr();
}
return NewProxyObject(cx, handler, priv, options->proto(), parent, *options);
}
JSObject *
@ -115,7 +120,7 @@ js::UnwrapOneChecked(JSObject *obj, bool stopAtOuter)
}
Wrapper *handler = Wrapper::wrapperHandler(obj);
return handler->isSafeToUnwrap() ? Wrapper::wrappedObject(obj) : nullptr;
return handler->hasSecurityPolicy() ? nullptr : Wrapper::wrappedObject(obj);
}
bool
@ -127,7 +132,6 @@ js::IsCrossCompartmentWrapper(JSObject *obj)
Wrapper::Wrapper(unsigned flags, bool hasPrototype) : DirectProxyHandler(&sWrapperFamily)
, mFlags(flags)
, mSafeToUnwrap(true)
{
setHasPrototype(hasPrototype);
}
@ -138,6 +142,7 @@ Wrapper::~Wrapper()
Wrapper Wrapper::singleton((unsigned)0);
Wrapper Wrapper::singletonWithPrototype((unsigned)0, true);
JSObject *Wrapper::defaultProto = TaggedProto::LazyProto;
/* Compartments. */
@ -517,7 +522,7 @@ CrossCompartmentWrapper::nativeCall(JSContext *cx, IsAcceptableThis test, Native
if ((src == srcArgs.base() + 1) && dst->isObject()) {
RootedObject thisObj(cx, &dst->toObject());
if (thisObj->is<WrapperObject>() &&
!Wrapper::wrapperHandler(thisObj)->isSafeToUnwrap())
Wrapper::wrapperHandler(thisObj)->hasSecurityPolicy())
{
JS_ASSERT(!thisObj->is<CrossCompartmentWrapperObject>());
*dst = ObjectValue(*Wrapper::wrappedObject(thisObj));
@ -617,8 +622,7 @@ template <class Base>
SecurityWrapper<Base>::SecurityWrapper(unsigned flags)
: Base(flags)
{
Base::setSafeToUnwrap(false);
BaseProxyHandler::setHasPolicy(true);
BaseProxyHandler::setHasSecurityPolicy(true);
}
template <class Base>
@ -870,14 +874,6 @@ DeadObjectProxy::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandle
DeadObjectProxy DeadObjectProxy::singleton;
const char DeadObjectProxy::sDeadObjectFamily = 0;
JSObject *
js::NewDeadProxyObject(JSContext *cx, JSObject *parent,
const ProxyOptions &options)
{
return NewProxyObject(cx, &DeadObjectProxy::singleton, JS::NullHandleValue,
nullptr, parent, options);
}
bool
js::IsDeadProxyObject(JSObject *obj)
{

View File

@ -15,6 +15,35 @@ namespace js {
class DummyFrameGuard;
/*
* Helper for Wrapper::New default options.
*
* Callers of Wrapper::New() who wish to specify a prototype for the created
* Wrapper, *MUST* construct a WrapperOptions with a JSContext.
*/
class MOZ_STACK_CLASS WrapperOptions : public ProxyOptions {
public:
WrapperOptions() : ProxyOptions(false, nullptr),
proto_()
{}
WrapperOptions(JSContext *cx) : ProxyOptions(false, nullptr),
proto_()
{
proto_.construct(cx);
}
inline JSObject *proto() const;
WrapperOptions &setProto(JSObject *protoArg) {
JS_ASSERT(!proto_.empty());
proto_.ref() = protoArg;
return *this;
}
private:
mozilla::Maybe<JS::RootedObject> proto_;
};
/*
* A wrapper is a proxy with a target object to which it generally forwards
* operations, but may restrict access to certain operations or instrument
@ -27,7 +56,6 @@ class DummyFrameGuard;
class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
{
unsigned mFlags;
bool mSafeToUnwrap;
public:
using BaseProxyHandler::Action;
@ -40,16 +68,8 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
virtual bool defaultValue(JSContext *cx, HandleObject obj, JSType hint,
MutableHandleValue vp) MOZ_OVERRIDE;
/*
* Wrappers can explicitly specify that they are unsafe to unwrap from a
* security perspective (as is the case for SecurityWrappers). If a wrapper
* is not safe to unwrap, operations requiring full access to the underlying
* object (via CheckedUnwrap) will throw. Otherwise, they will succeed.
*/
void setSafeToUnwrap(bool safe) { mSafeToUnwrap = safe; }
bool isSafeToUnwrap() { return mSafeToUnwrap; }
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *parent, Wrapper *handler);
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *parent, Wrapper *handler,
const WrapperOptions *options = nullptr);
static JSObject *Renew(JSContext *cx, JSObject *existing, JSObject *obj, Wrapper *handler);
@ -69,8 +89,16 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
static Wrapper singleton;
static Wrapper singletonWithPrototype;
static JSObject *defaultProto;
};
inline JSObject *
WrapperOptions::proto() const
{
return proto_.empty() ? Wrapper::defaultProto : proto_.ref();
}
/* Base class for all cross compartment wrapper handlers. */
class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
{

View File

@ -3764,34 +3764,6 @@ ThisFilename(JSContext *cx, unsigned argc, Value *vp)
return true;
}
/*
* Internal class for testing hasPrototype easily.
* Uses passed in prototype instead of target's.
*/
class WrapperWithProto : public Wrapper
{
public:
explicit WrapperWithProto(unsigned flags)
: Wrapper(flags, true)
{ }
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
Wrapper *handler);
};
/* static */ JSObject *
WrapperWithProto::New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
Wrapper *handler)
{
JS_ASSERT(parent);
AutoMarkInDeadZone amd(cx->zone());
RootedValue priv(cx, ObjectValue(*obj));
ProxyOptions options;
options.setCallable(obj->isCallable());
return NewProxyObject(cx, handler, priv, proto, parent, options);
}
static bool
Wrap(JSContext *cx, unsigned argc, jsval *vp)
{
@ -3825,9 +3797,11 @@ WrapWithProto(JSContext *cx, unsigned argc, jsval *vp)
return false;
}
JSObject *wrapped = WrapperWithProto::New(cx, &obj.toObject(), proto.toObjectOrNull(),
&obj.toObject().global(),
&Wrapper::singletonWithPrototype);
WrapperOptions options(cx);
options.setProto(proto.toObjectOrNull());
options.selectDefaultClass(obj.toObject().isCallable());
JSObject *wrapped = Wrapper::New(cx, &obj.toObject(), &obj.toObject().global(),
&Wrapper::singletonWithPrototype, &options);
if (!wrapped)
return false;

View File

@ -0,0 +1,49 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var gTestfile = 'destructuring-__proto__-shorthand-assignment-before-var.js';
var BUGNUMBER = 963641;
var summary = "{ __proto__ } should work as a destructuring assignment pattern";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
function objectWithProtoProperty(v)
{
var obj = {};
return Object.defineProperty(obj, "__proto__",
{
enumerable: true,
configurable: true,
writable: true,
value: v
});
}
({ __proto__ } = objectWithProtoProperty(17));
assertEq(__proto__, 17);
var { __proto__ } = objectWithProtoProperty(42);
assertEq(__proto__, 42);
function nested()
{
({ __proto__ } = objectWithProtoProperty(undefined));
assertEq(__proto__, undefined);
var { __proto__ } = objectWithProtoProperty("fnord");
assertEq(__proto__, "fnord");
}
nested();
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("Tests complete");

View File

@ -0,0 +1,49 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var gTestfile = 'destructuring-__proto__-shorthand-assignment.js';
var BUGNUMBER = 963641;
var summary = "{ __proto__ } should work as a destructuring assignment pattern";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
function objectWithProtoProperty(v)
{
var obj = {};
return Object.defineProperty(obj, "__proto__",
{
enumerable: true,
configurable: true,
writable: true,
value: v
});
}
var { __proto__ } = objectWithProtoProperty(42);
assertEq(__proto__, 42);
({ __proto__ } = objectWithProtoProperty(17));
assertEq(__proto__, 17);
function nested()
{
var { __proto__ } = objectWithProtoProperty("fnord");
assertEq(__proto__, "fnord");
({ __proto__ } = objectWithProtoProperty(undefined));
assertEq(__proto__, undefined);
}
nested();
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("Tests complete");

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