mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to fx-team
This commit is contained in:
commit
2f49c3b34b
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;
|
||||
}
|
||||
|
@ -12,13 +12,13 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0bc0e703df197d46dfffb9ac65cb85d2e3e10c4a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="61866f17977a440a3297aa8ade8f410c68d2cdd7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ff2eb11982b9d3c7a3333900cf0d3a5c0f77e32"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
||||
|
@ -11,10 +11,10 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0bc0e703df197d46dfffb9ac65cb85d2e3e10c4a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="61866f17977a440a3297aa8ade8f410c68d2cdd7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ff2eb11982b9d3c7a3333900cf0d3a5c0f77e32"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
|
||||
<!-- Stock Android things -->
|
||||
|
@ -12,13 +12,13 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0bc0e703df197d46dfffb9ac65cb85d2e3e10c4a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="61866f17977a440a3297aa8ade8f410c68d2cdd7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ff2eb11982b9d3c7a3333900cf0d3a5c0f77e32"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "621040ee199cdde3bdd2aeaf2a016ff7806875bb",
|
||||
"revision": "d369bbb3b7c415097c7c1fa303843cf5683cd843",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -11,12 +11,12 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0bc0e703df197d46dfffb9ac65cb85d2e3e10c4a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="61866f17977a440a3297aa8ade8f410c68d2cdd7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ff2eb11982b9d3c7a3333900cf0d3a5c0f77e32"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0bc0e703df197d46dfffb9ac65cb85d2e3e10c4a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="61866f17977a440a3297aa8ade8f410c68d2cdd7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
|
@ -12,12 +12,12 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0bc0e703df197d46dfffb9ac65cb85d2e3e10c4a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="61866f17977a440a3297aa8ade8f410c68d2cdd7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ff2eb11982b9d3c7a3333900cf0d3a5c0f77e32"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
<project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
|
||||
|
@ -11,12 +11,12 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0bc0e703df197d46dfffb9ac65cb85d2e3e10c4a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="61866f17977a440a3297aa8ade8f410c68d2cdd7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ff2eb11982b9d3c7a3333900cf0d3a5c0f77e32"/>
|
||||
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
|
@ -11,10 +11,10 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="0bc0e703df197d46dfffb9ac65cb85d2e3e10c4a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="61866f17977a440a3297aa8ade8f410c68d2cdd7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ff2eb11982b9d3c7a3333900cf0d3a5c0f77e32"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
|
||||
<!-- Stock Android things -->
|
||||
|
@ -11,12 +11,12 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0bc0e703df197d46dfffb9ac65cb85d2e3e10c4a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="61866f17977a440a3297aa8ade8f410c68d2cdd7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="e33ea242b4328fb0d1824c951f379332b5021512"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0ff2eb11982b9d3c7a3333900cf0d3a5c0f77e32"/>
|
||||
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
|
||||
<!-- Stock Android things -->
|
||||
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
|
||||
|
@ -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'
|
||||
|
@ -62,7 +62,8 @@ public:
|
||||
SendFileBatch(const nsAString& aDeviceAddress, BlobParent* aActor)
|
||||
: mDeviceAddress(aDeviceAddress)
|
||||
{
|
||||
mBlobs.AppendElement(aActor->GetBlob().get());
|
||||
nsCOMPtr<nsIDOMBlob> blob = aActor->GetBlob();
|
||||
mBlobs.AppendElement(blob);
|
||||
}
|
||||
|
||||
nsString mDeviceAddress;
|
||||
@ -374,7 +375,8 @@ BluetoothOppManager::AppendBlobToSend(const nsAString& aDeviceAddress,
|
||||
SendFileBatch batch(aDeviceAddress, aActor);
|
||||
mBatches.AppendElement(batch);
|
||||
} else {
|
||||
mBatches[indexTail].mBlobs.AppendElement(aActor->GetBlob().get());
|
||||
nsCOMPtr<nsIDOMBlob> blob = aActor->GetBlob();
|
||||
mBatches[indexTail].mBlobs.AppendElement(blob);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,8 @@ public:
|
||||
SendFileBatch(const nsAString& aDeviceAddress, BlobParent* aActor)
|
||||
: mDeviceAddress(aDeviceAddress)
|
||||
{
|
||||
mBlobs.AppendElement(aActor->GetBlob().get());
|
||||
nsCOMPtr<nsIDOMBlob> blob = aActor->GetBlob();
|
||||
mBlobs.AppendElement(blob);
|
||||
}
|
||||
|
||||
nsString mDeviceAddress;
|
||||
@ -390,7 +391,8 @@ BluetoothOppManager::AppendBlobToSend(const nsAString& aDeviceAddress,
|
||||
SendFileBatch batch(aDeviceAddress, aActor);
|
||||
mBatches.AppendElement(batch);
|
||||
} else {
|
||||
mBatches[indexTail].mBlobs.AppendElement(aActor->GetBlob().get());
|
||||
nsCOMPtr<nsIDOMBlob> blob = aActor->GetBlob();
|
||||
mBatches[indexTail].mBlobs.AppendElement(blob);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,12 +189,16 @@ GetAppPrincipal(uint32_t aAppId)
|
||||
{
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
|
||||
nsString manifestURL;
|
||||
nsresult rv = appsService->GetManifestURLByLocalId(aAppId, manifestURL);
|
||||
nsCOMPtr<mozIApplication> app;
|
||||
nsresult rv = appsService->GetAppByLocalId(aAppId, getter_AddRefs(app));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
nsString origin;
|
||||
rv = app->GetOrigin(origin);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NS_NewURI(getter_AddRefs(uri), manifestURL);
|
||||
NS_NewURI(getter_AddRefs(uri), origin);
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
|
||||
|
@ -164,25 +164,27 @@ mozNfc.prototype = {
|
||||
init: function init(aWindow) {
|
||||
debug("mozNfc init called");
|
||||
this._window = aWindow;
|
||||
let origin = this._window.document.nodePrincipal.origin;
|
||||
// Only System Process should listen on 'nfc-p2p-user-accept' event
|
||||
if (origin !== 'app://system.gaiamobile.org') {
|
||||
return;
|
||||
}
|
||||
let self = this;
|
||||
this._window.addEventListener("nfc-p2p-user-accept", function (event) {
|
||||
let appID = appsService.getAppLocalIdByManifestURL(event.detail.manifestUrl);
|
||||
// Notify Chrome process of User's acknowledgement
|
||||
self._nfcContentHelper.notifyUserAcceptedP2P(self._window, appID);
|
||||
});
|
||||
},
|
||||
|
||||
// Only System Process can call the following interfaces
|
||||
// 'checkP2PRegistration' , 'notifyUserAcceptedP2P' , 'notifySendFileStatus'
|
||||
checkP2PRegistration: function checkP2PRegistration(manifestUrl) {
|
||||
// Get the AppID and pass it to ContentHelper
|
||||
let appID = appsService.getAppLocalIdByManifestURL(manifestUrl);
|
||||
return this._nfcContentHelper.checkP2PRegistration(this._window, appID);
|
||||
},
|
||||
|
||||
notifyUserAcceptedP2P: function notifyUserAcceptedP2P(manifestUrl) {
|
||||
let appID = appsService.getAppLocalIdByManifestURL(manifestUrl);
|
||||
// Notify chrome process of user's acknowledgement
|
||||
this._nfcContentHelper.notifyUserAcceptedP2P(this._window, appID);
|
||||
},
|
||||
|
||||
notifySendFileStatus: function notifySendFileStatus(status, requestId) {
|
||||
this._nfcContentHelper.notifySendFileStatus(this._window,
|
||||
status, requestId);
|
||||
},
|
||||
|
||||
getNFCTag: function getNFCTag(sessionToken) {
|
||||
let obj = new MozNFCTag();
|
||||
let nfcTag = this._window.MozNFCTag._create(this._window, obj);
|
||||
|
@ -59,7 +59,8 @@ const NFC_IPC_PEER_MSG_NAMES = [
|
||||
"NFC:RegisterPeerTarget",
|
||||
"NFC:UnregisterPeerTarget",
|
||||
"NFC:CheckP2PRegistration",
|
||||
"NFC:NotifyUserAcceptedP2P"
|
||||
"NFC:NotifyUserAcceptedP2P",
|
||||
"NFC:NotifySendFileStatus"
|
||||
];
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
|
||||
@ -309,10 +310,12 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Add extra permission check for below IPC Peer events:
|
||||
// 'NFC:CheckP2PRegistration' , 'NFC:NotifyUserAcceptedP2P'
|
||||
// Add extra permission check for below events:
|
||||
// 'NFC:CheckP2PRegistration' , 'NFC:NotifyUserAcceptedP2P',
|
||||
// 'NFC:NotifySendFileStatus'
|
||||
if ((msg.name == "NFC:CheckP2PRegistration") ||
|
||||
(msg.name == "NFC:NotifyUserAcceptedP2P")) {
|
||||
(msg.name == "NFC:NotifyUserAcceptedP2P") ||
|
||||
(msg.name == "NFC:NotifySendFileStatus")) {
|
||||
// ONLY privileged Content can send these events
|
||||
if (!msg.target.assertPermission("nfc-manager")) {
|
||||
debug("NFC message " + message.name +
|
||||
@ -356,6 +359,11 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
// Notify the 'NFC_PEER_EVENT_READY' since user has acknowledged
|
||||
this.notifyPeerEvent(msg.json.appId, NFC.NFC_PEER_EVENT_READY);
|
||||
break;
|
||||
case "NFC:NotifySendFileStatus":
|
||||
// Upon receiving the status of sendFile operation, send the response
|
||||
// to appropriate content process.
|
||||
this.sendNfcResponseMessage(msg.name + "Response", msg.json);
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
@ -52,7 +52,9 @@ const NFC_IPC_MSG_NAMES = [
|
||||
"NFC:ConnectResponse",
|
||||
"NFC:CloseResponse",
|
||||
"NFC:CheckP2PRegistrationResponse",
|
||||
"NFC:PeerEvent"
|
||||
"NFC:PeerEvent",
|
||||
"NFC:NotifySendFileStatusResponse",
|
||||
"NFC:SendFileResponse"
|
||||
];
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
@ -235,6 +237,19 @@ NfcContentHelper.prototype = {
|
||||
return request;
|
||||
},
|
||||
|
||||
notifySendFileStatus: function notifySendFileStatus(window, status,
|
||||
requestId) {
|
||||
if (window == null) {
|
||||
throw Components.Exception("Can't get window object",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
cpmm.sendAsyncMessage("NFC:NotifySendFileStatus", {
|
||||
status: status,
|
||||
requestId: requestId
|
||||
});
|
||||
},
|
||||
|
||||
registerTargetForPeerEvent: function registerTargetForPeerEvent(window,
|
||||
appId, event, callback) {
|
||||
if (window == null) {
|
||||
@ -341,6 +356,7 @@ NfcContentHelper.prototype = {
|
||||
case "NFC:MakeReadOnlyNDEFResponse":
|
||||
case "NFC:GetDetailsNDEFResponse":
|
||||
case "NFC:CheckP2PRegistrationResponse":
|
||||
case "NFC:NotifySendFileStatusResponse":
|
||||
this.handleResponse(message.json);
|
||||
break;
|
||||
case "NFC:PeerEvent":
|
||||
|
@ -24,7 +24,7 @@ interface nsINfcPeerCallback : nsISupports
|
||||
in DOMString sessionToken);
|
||||
};
|
||||
|
||||
[scriptable, uuid(91c2760a-f41c-4174-ad68-614840d4e201)]
|
||||
[scriptable, uuid(70cac000-7e3c-11e3-baa7-0800200c9a66)]
|
||||
interface nsINfcContentHelper : nsISupports
|
||||
{
|
||||
const long NFC_EVENT_PEER_READY = 0x01;
|
||||
@ -118,4 +118,21 @@ interface nsINfcContentHelper : nsISupports
|
||||
* Application ID that is capable of handling NFC_EVENT_PEER_READY event
|
||||
*/
|
||||
void notifyUserAcceptedP2P(in nsIDOMWindow window, in unsigned long appId);
|
||||
|
||||
/**
|
||||
* Notify the status of sendFile operation to Chrome process
|
||||
*
|
||||
* @param window
|
||||
* Current window
|
||||
*
|
||||
* @param status
|
||||
* Status of sendFile operation
|
||||
* (GECKO_NFC_ERROR_SUCCESS, GECKO_NFC_ERROR_GENERIC_FAILURE)
|
||||
*
|
||||
* @param requestId
|
||||
* Request ID of SendFile DOM Request
|
||||
*/
|
||||
void notifySendFileStatus(in nsIDOMWindow window,
|
||||
in octet status,
|
||||
in DOMString requestId);
|
||||
};
|
||||
|
@ -218,8 +218,7 @@ Telephony::HasDialingCall()
|
||||
{
|
||||
for (uint32_t i = 0; i < mCalls.Length(); i++) {
|
||||
const nsRefPtr<TelephonyCall>& call = mCalls[i];
|
||||
if (call->IsOutgoing() &&
|
||||
call->CallState() > nsITelephonyProvider::CALL_STATE_UNKNOWN &&
|
||||
if (call->CallState() > nsITelephonyProvider::CALL_STATE_UNKNOWN &&
|
||||
call->CallState() < nsITelephonyProvider::CALL_STATE_CONNECTED) {
|
||||
return true;
|
||||
}
|
||||
|
@ -46,8 +46,7 @@ TelephonyCall::TelephonyCall(nsPIDOMWindow* aOwner)
|
||||
: nsDOMEventTargetHelper(aOwner),
|
||||
mCallIndex(kOutgoingPlaceholderCallIndex),
|
||||
mCallState(nsITelephonyProvider::CALL_STATE_UNKNOWN),
|
||||
mLive(false),
|
||||
mOutgoing(false)
|
||||
mLive(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -105,10 +104,6 @@ TelephonyCall::ChangeStateInternal(uint16_t aCallState, bool aFireEvents)
|
||||
mState = stateString;
|
||||
mCallState = aCallState;
|
||||
|
||||
if (aCallState == nsITelephonyProvider::CALL_STATE_DIALING) {
|
||||
mOutgoing = true;
|
||||
}
|
||||
|
||||
if (aCallState == nsITelephonyProvider::CALL_STATE_DISCONNECTED) {
|
||||
NS_ASSERTION(mLive, "Should be live!");
|
||||
if (mGroup) {
|
||||
|
@ -31,7 +31,6 @@ class TelephonyCall MOZ_FINAL : public nsDOMEventTargetHelper
|
||||
uint32_t mCallIndex;
|
||||
uint16_t mCallState;
|
||||
bool mLive;
|
||||
bool mOutgoing;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
@ -157,12 +156,6 @@ public:
|
||||
mSecondNumber = aNumber;
|
||||
}
|
||||
|
||||
bool
|
||||
IsOutgoing() const
|
||||
{
|
||||
return mOutgoing;
|
||||
}
|
||||
|
||||
void
|
||||
NotifyError(const nsAString& aError);
|
||||
|
||||
|
@ -13,11 +13,18 @@ interface MozNfcManager {
|
||||
*
|
||||
* Returns success if given manifestUrl is registered for 'onpeerready',
|
||||
* otherwise error
|
||||
*
|
||||
* Users of this API should have valid permissions 'nfc-manager'
|
||||
* and 'nfc-write'
|
||||
*/
|
||||
DOMRequest checkP2PRegistration(DOMString manifestUrl);
|
||||
|
||||
/**
|
||||
* Notify that user has accepted to share nfc message on P2P UI
|
||||
*/
|
||||
void notifyUserAcceptedP2P(DOMString manifestUrl);
|
||||
|
||||
/**
|
||||
* Notify the status of sendFile operation
|
||||
*/
|
||||
void notifySendFileStatus(octet status, DOMString requestId);
|
||||
};
|
||||
|
||||
[JSImplementation="@mozilla.org/navigatorNfc;1",
|
||||
|
@ -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();
|
||||
|
@ -759,10 +759,38 @@ GetTimezoneOffset()
|
||||
return -(offset / 60);
|
||||
}
|
||||
|
||||
static int32_t sKernelTimezoneOffset = 0;
|
||||
|
||||
static void
|
||||
UpdateKernelTimezone(int32_t timezoneOffset)
|
||||
{
|
||||
if (sKernelTimezoneOffset == timezoneOffset) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell the kernel about the new time zone as well, so that FAT filesystems
|
||||
// will get local timestamps rather than UTC timestamps.
|
||||
//
|
||||
// We assume that /init.rc has a sysclktz entry so that settimeofday has
|
||||
// already been called once before we call it (there is a side-effect in
|
||||
// the kernel the very first time settimeofday is called where it does some
|
||||
// special processing if you only set the timezone).
|
||||
struct timezone tz;
|
||||
memset(&tz, 0, sizeof(tz));
|
||||
tz.tz_minuteswest = timezoneOffset;
|
||||
settimeofday(nullptr, &tz);
|
||||
sKernelTimezoneOffset = timezoneOffset;
|
||||
}
|
||||
|
||||
void
|
||||
SetTimezone(const nsCString& aTimezoneSpec)
|
||||
{
|
||||
if (aTimezoneSpec.Equals(GetTimezone())) {
|
||||
// Even though the timezone hasn't changed, we still need to tell the
|
||||
// kernel what the current timezone is. The timezone is persisted in
|
||||
// a property and doesn't change across reboots, but the kernel still
|
||||
// needs to be updated on every boot.
|
||||
UpdateKernelTimezone(GetTimezoneOffset());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -772,6 +800,7 @@ SetTimezone(const nsCString& aTimezoneSpec)
|
||||
// functions that depend on the timezone. To be safe, we call it manually.
|
||||
tzset();
|
||||
int32_t newTimezoneOffsetMinutes = GetTimezoneOffset();
|
||||
UpdateKernelTimezone(newTimezoneOffsetMinutes);
|
||||
hal::NotifySystemTimezoneChange(
|
||||
hal::SystemTimezoneChangeInformation(
|
||||
oldTimezoneOffsetMinutes, newTimezoneOffsetMinutes));
|
||||
|
@ -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");
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
var gTestfile = 'destructuring-__proto__-target--assignment.js';
|
||||
var BUGNUMBER = 963641;
|
||||
var summary =
|
||||
"{ __proto__: target } 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__: target } = objectWithProtoProperty(null);
|
||||
assertEq(target, null);
|
||||
|
||||
({ __proto__: target } = objectWithProtoProperty("aacchhorrt"));
|
||||
assertEq(target, "aacchhorrt");
|
||||
|
||||
function nested()
|
||||
{
|
||||
var { __proto__: target } = objectWithProtoProperty(3.141592654);
|
||||
assertEq(target, 3.141592654);
|
||||
|
||||
({ __proto__: target } = objectWithProtoProperty(-0));
|
||||
assertEq(target, -0);
|
||||
}
|
||||
nested();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
print("Tests complete");
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
var gTestfile = 'destructuring-for-inof-__proto__.js';
|
||||
var BUGNUMBER = 963641;
|
||||
var summary =
|
||||
"__proto__ should work in destructuring patterns as the targets of " +
|
||||
"for-in/for-of loops";
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
/**************
|
||||
* BEGIN TEST *
|
||||
**************/
|
||||
|
||||
function objectWithProtoProperty(v)
|
||||
{
|
||||
var obj = {};
|
||||
return Object.defineProperty(obj, "__proto__",
|
||||
{
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: v
|
||||
});
|
||||
}
|
||||
|
||||
function* objectWithProtoGenerator(v)
|
||||
{
|
||||
yield objectWithProtoProperty(v);
|
||||
}
|
||||
|
||||
function* identityGenerator(v)
|
||||
{
|
||||
yield v;
|
||||
}
|
||||
|
||||
for (var { __proto__: target } of objectWithProtoGenerator(null))
|
||||
assertEq(target, null);
|
||||
|
||||
for ({ __proto__: target } of objectWithProtoGenerator("aacchhorrt"))
|
||||
assertEq(target, "aacchhorrt");
|
||||
|
||||
for ({ __proto__: target } of identityGenerator(42))
|
||||
assertEq(target, Number.prototype);
|
||||
|
||||
for (var { __proto__: target } in { prop: "kneedle" })
|
||||
assertEq(target, String.prototype);
|
||||
|
||||
for ({ __proto__: target } in { prop: "snork" })
|
||||
assertEq(target, String.prototype);
|
||||
|
||||
for ({ __proto__: target } in { prop: "ohia" })
|
||||
assertEq(target, String.prototype);
|
||||
|
||||
function nested()
|
||||
{
|
||||
for (var { __proto__: target } of objectWithProtoGenerator(null))
|
||||
assertEq(target, null);
|
||||
|
||||
for ({ __proto__: target } of objectWithProtoGenerator("aacchhorrt"))
|
||||
assertEq(target, "aacchhorrt");
|
||||
|
||||
for ({ __proto__: target } of identityGenerator(42))
|
||||
assertEq(target, Number.prototype);
|
||||
|
||||
for (var { __proto__: target } in { prop: "kneedle" })
|
||||
assertEq(target, String.prototype);
|
||||
|
||||
for ({ __proto__: target } in { prop: "snork" })
|
||||
assertEq(target, String.prototype);
|
||||
|
||||
for ({ __proto__: target } in { prop: "ohia" })
|
||||
assertEq(target, String.prototype);
|
||||
}
|
||||
nested();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
print("Tests complete");
|
@ -0,0 +1,11 @@
|
||||
// |reftest| skip-if(!xulRuntime.shell)
|
||||
// bug 963641
|
||||
|
||||
Reflect.parse("({ __proto__: null });");
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
|
||||
|
||||
print("Tests complete");
|
@ -20,14 +20,11 @@ ProxyObject::New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, Tag
|
||||
Rooted<TaggedProto> proto(cx, proto_);
|
||||
RootedObject parent(cx, parent_);
|
||||
|
||||
const Class *clasp = options.clasp();
|
||||
|
||||
JS_ASSERT(isValidProxyClass(clasp));
|
||||
JS_ASSERT_IF(proto.isObject(), cx->compartment() == proto.toObject()->compartment());
|
||||
JS_ASSERT_IF(parent, cx->compartment() == parent->compartment());
|
||||
const Class *clasp;
|
||||
if (handler->isOuterWindow())
|
||||
clasp = &OuterWindowProxyObject::class_;
|
||||
else
|
||||
clasp = options.callable() ? &ProxyObject::callableClass_
|
||||
: &ProxyObject::uncallableClass_;
|
||||
|
||||
/*
|
||||
* Eagerly mark properties unknown for proxies, so we don't try to track
|
||||
@ -40,8 +37,7 @@ ProxyObject::New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, Tag
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NewObjectKind newKind =
|
||||
(clasp == &OuterWindowProxyObject::class_ || options.singleton()) ? SingletonObject : GenericObject;
|
||||
NewObjectKind newKind = options.singleton() ? SingletonObject : GenericObject;
|
||||
gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
|
||||
if (handler->finalizeInBackground(priv))
|
||||
allocKind = GetBackgroundAllocKind(allocKind);
|
||||
@ -88,9 +84,10 @@ NukeSlot(ProxyObject *proxy, uint32_t slot)
|
||||
void
|
||||
ProxyObject::nuke(BaseProxyHandler *handler)
|
||||
{
|
||||
NukeSlot(this, PRIVATE_SLOT);
|
||||
/* Allow people to add their own number of reserved slots beyond the expected 4 */
|
||||
unsigned numSlots = JSCLASS_RESERVED_SLOTS(getClass());
|
||||
for (unsigned i = 0; i < numSlots; i++)
|
||||
NukeSlot(this, i);
|
||||
/* Restore the handler as requested after nuking. */
|
||||
setHandler(handler);
|
||||
|
||||
NukeSlot(this, EXTRA_SLOT + 0);
|
||||
NukeSlot(this, EXTRA_SLOT + 1);
|
||||
}
|
||||
|
@ -71,6 +71,25 @@ class ProxyObject : public JSObject
|
||||
return &getReservedSlotRef(EXTRA_SLOT + n);
|
||||
}
|
||||
|
||||
HeapSlot *slotOfClassSpecific(size_t n) {
|
||||
JS_ASSERT(n >= PROXY_MINIMUM_SLOTS);
|
||||
JS_ASSERT(n < JSCLASS_RESERVED_SLOTS(getClass()));
|
||||
return &getReservedSlotRef(n);
|
||||
}
|
||||
|
||||
static bool isValidProxyClass(const Class *clasp) {
|
||||
// Since we can take classes from the outside, make sure that they
|
||||
// are "sane". They have to quack enough like proxies for us to belive
|
||||
// they should be treated as such.
|
||||
|
||||
// proxy_Trace is just a trivial wrapper around ProxyObject::trace for
|
||||
// friend api exposure.
|
||||
return clasp->isProxy() &&
|
||||
(clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS) &&
|
||||
clasp->trace == proxy_Trace &&
|
||||
JSCLASS_RESERVED_SLOTS(clasp) >= PROXY_MINIMUM_SLOTS;
|
||||
}
|
||||
|
||||
public:
|
||||
static unsigned grayLinkSlot(JSObject *obj);
|
||||
|
||||
@ -84,12 +103,6 @@ class ProxyObject : public JSObject
|
||||
static const Class uncallableClass_;
|
||||
};
|
||||
|
||||
class OuterWindowProxyObject : public ProxyObject
|
||||
{
|
||||
public:
|
||||
static const Class class_;
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
||||
// Note: the following |JSObject::is<T>| methods are implemented in terms of
|
||||
|
@ -789,7 +789,7 @@ WrapCallable(JSContext *cx, JSObject *callable, JSObject *sandboxProtoProxy)
|
||||
|
||||
RootedValue priv(cx, ObjectValue(*callable));
|
||||
js::ProxyOptions options;
|
||||
options.setCallable(true);
|
||||
options.selectDefaultClass(true);
|
||||
return js::NewProxyObject(cx, &xpc::sandboxCallableProxyHandler,
|
||||
priv, nullptr,
|
||||
sandboxProtoProxy, options);
|
||||
|
@ -1170,6 +1170,8 @@ XPCNativeScriptableShared::PopulateJSClass()
|
||||
|
||||
if (mFlags.WantConvert())
|
||||
mJSClass.base.convert = XPC_WN_Helper_Convert;
|
||||
else if (mFlags.WantOuterObject())
|
||||
mJSClass.base.convert = JS_ConvertStub;
|
||||
else
|
||||
mJSClass.base.convert = XPC_WN_Shared_Convert;
|
||||
|
||||
|
@ -86,6 +86,7 @@ support-files =
|
||||
[test_bug916945.html]
|
||||
[test_bug92773.html]
|
||||
[test_bug940783.html]
|
||||
[test_bug965082.html]
|
||||
[test_crosscompartment_weakmap.html]
|
||||
[test_frameWrapping.html]
|
||||
[test_nac.xhtml]
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user