mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to b2g-inbound
This commit is contained in:
commit
ee3229a280
1
.clang-format
Normal file
1
.clang-format
Normal file
@ -0,0 +1 @@
|
||||
BasedOnStyle: Mozilla
|
@ -1,2 +1,3 @@
|
||||
\mfbt/
|
||||
\js/
|
||||
\media/
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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],
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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']
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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',
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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) {}
|
||||
},
|
||||
|
||||
|
@ -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 () {
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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 & more.">
|
||||
<!ENTITY aboutAccountsSetup.startButton.label "Get started">
|
||||
<!ENTITY aboutAccountsSetup.useOldSync.label "Using an older version of Sync?">
|
||||
|
@ -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">
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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':
|
||||
|
@ -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 }
|
||||
]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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] {
|
||||
|
BIN
browser/themes/osx/customizableui/customize-titleBar-toggle.png
Normal file
BIN
browser/themes/osx/customizableui/customize-titleBar-toggle.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 317 B |
Binary file not shown.
After Width: | Height: | Size: 538 B |
@ -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
|
||||
|
@ -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"),
|
||||
|
@ -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 |
@ -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
|
||||
|
@ -5,8 +5,6 @@
|
||||
|
||||
INTERNAL_TOOLS = 1
|
||||
|
||||
VPATH += $(topsrcdir)/build
|
||||
|
||||
OS_CXXFLAGS := $(filter-out -fno-exceptions,$(OS_CXXFLAGS)) -fexceptions
|
||||
|
||||
WRAP_LDFLAGS=
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
20
content/canvas/src/WebGLExtensionTextureHalfFloat.cpp
Normal file
20
content/canvas/src/WebGLExtensionTextureHalfFloat.cpp
Normal 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)
|
@ -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.
|
||||
*/
|
||||
|
||||
|
@ -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
|
||||
|
@ -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?");
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -58,6 +58,7 @@ if CONFIG['MOZ_WEBGL']:
|
||||
'WebGLExtensionTextureFilterAnisotropic.cpp',
|
||||
'WebGLExtensionTextureFloat.cpp',
|
||||
'WebGLExtensionTextureFloatLinear.cpp',
|
||||
'WebGLExtensionTextureHalfFloat.cpp',
|
||||
'WebGLExtensionVertexArray.cpp',
|
||||
'WebGLFramebuffer.cpp',
|
||||
'WebGLObjectModel.cpp',
|
||||
|
@ -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.")
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -1407,6 +1407,11 @@ DOMInterfaces = {
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionTextureHalfFloat': {
|
||||
'nativeType': 'mozilla::WebGLExtensionTextureHalfFloat',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
},
|
||||
|
||||
'WebGLExtensionDrawBuffers': {
|
||||
'nativeType': 'mozilla::WebGLExtensionDrawBuffers',
|
||||
'headerFile': 'WebGLExtensions.h'
|
||||
|
@ -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;
|
||||
|
@ -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!");
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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); }
|
||||
};
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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)
|
||||
|
@ -139,7 +139,6 @@ class UpvarCookie
|
||||
F(FORHEAD) \
|
||||
F(ARGSBODY) \
|
||||
F(SPREAD) \
|
||||
F(MUTATEPROTO) \
|
||||
\
|
||||
/* Unary operators. */ \
|
||||
F(TYPEOF) \
|
||||
|
@ -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;
|
||||
|
@ -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}'));
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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>();
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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");
|
@ -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
Loading…
Reference in New Issue
Block a user