Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2014-01-30 12:10:15 +01:00
commit 2f49c3b34b
156 changed files with 3051 additions and 996 deletions

1
.clang-format Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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"/>

View File

@ -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 -->

View File

@ -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"/>

View File

@ -1,4 +1,4 @@
{
"revision": "621040ee199cdde3bdd2aeaf2a016ff7806875bb",
"revision": "d369bbb3b7c415097c7c1fa303843cf5683cd843",
"repo_path": "/integration/gaia-central"
}

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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 -->

View File

@ -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"/>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,20 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include "WebGLExtensions.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
using namespace mozilla;
WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* context)
: WebGLExtensionBase(context)
{
}
WebGLExtensionTextureHalfFloat::~WebGLExtensionTextureHalfFloat()
{
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloat)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
},

View File

@ -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":

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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) {

View File

@ -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);

View File

@ -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",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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