Merge latest green b2g-inbound changeset and mozilla-central; a=merge

This commit is contained in:
Ed Morley 2014-10-03 14:29:24 +01:00
commit e477fa5b6d
440 changed files with 5383 additions and 47596 deletions

View File

@ -0,0 +1,25 @@
MOZ_AUTOMATION_TALOS_SENDCHANGE=0
. $topsrcdir/build/macosx/mozconfig.common
ac_add_options --enable-application=b2g/dev
ac_add_options --disable-install-strip
ac_add_options --enable-signmar
ac_add_options --enable-profiling
ac_add_options --enable-instruments
ac_add_options --enable-dtrace
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
ac_add_options --with-macbundlename-prefix=Firefox
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

View File

@ -4,10 +4,10 @@
# location which also work on other platforms. # location which also work on other platforms.
# #
# @DIR_MACOS@ # @DIR_MACOS@
# Equals Contents/MacOS/ on Mac OX X and is an empty string on other platforms. # Equals Contents/MacOS/ on Mac OS X and is an empty string on other platforms.
# #
# @DIR_RESOURCES@ # @DIR_RESOURCES@
# Equals Contents/Resources/ on Mac OX X and is an empty string on other # Equals Contents/Resources/ on Mac OS X and is an empty string on other
# platforms. # platforms.
# Mac OS X v2 signing removals # Mac OS X v2 signing removals

View File

@ -46,7 +46,7 @@ const gXPInstallObserver = {
} }
// Note that the above try/catch will pass through dead object proxies and // Note that the above try/catch will pass through dead object proxies and
// other degenerate objects. Make sure the browser is bonafide. // other degenerate objects. Make sure the browser is bonafide.
if (!browser || !gBrowser.browsers.contains(browser)) if (!browser || gBrowser.browsers.indexOf(browser) == -1)
return; return;
const anchorID = "addons-notification-icon"; const anchorID = "addons-notification-icon";

View File

@ -1371,7 +1371,7 @@ let BookmarkingUI = {
// calls back. For such an edge case, retain all unique entries from both // calls back. For such an edge case, retain all unique entries from both
// arrays. // arrays.
this._itemIds = this._itemIds.filter( this._itemIds = this._itemIds.filter(
function (id) !aItemIds.contains(id) function (id) aItemIds.indexOf(id) == -1
).concat(aItemIds); ).concat(aItemIds);
this._updateStar(); this._updateStar();
@ -1592,7 +1592,7 @@ let BookmarkingUI = {
aURI) { aURI) {
if (aURI && aURI.equals(this._uri)) { if (aURI && aURI.equals(this._uri)) {
// If a new bookmark has been added to the tracked uri, register it. // If a new bookmark has been added to the tracked uri, register it.
if (!this._itemIds.contains(aItemId)) { if (this._itemIds.indexOf(aItemId) == -1) {
this._itemIds.push(aItemId); this._itemIds.push(aItemId);
// Only need to update the UI if it wasn't marked as starred before: // Only need to update the UI if it wasn't marked as starred before:
if (this._itemIds.length == 1) { if (this._itemIds.length == 1) {

View File

@ -2233,7 +2233,7 @@ function URLBarSetURI(aURI) {
// Replace initial page URIs with an empty string // Replace initial page URIs with an empty string
// only if there's no opener (bug 370555). // only if there's no opener (bug 370555).
// Bug 863515 - Make content.opener checks work in electrolysis. // Bug 863515 - Make content.opener checks work in electrolysis.
if (gInitialPages.contains(uri.spec)) if (gInitialPages.indexOf(uri.spec) != -1)
value = !gMultiProcessBrowser && content.opener ? uri.spec : ""; value = !gMultiProcessBrowser && content.opener ? uri.spec : "";
else else
value = losslessDecodeURI(uri); value = losslessDecodeURI(uri);

View File

@ -129,7 +129,7 @@ let gUpdater = {
// Delete sites that were removed from the grid. // Delete sites that were removed from the grid.
gGrid.sites.forEach(function (aSite) { gGrid.sites.forEach(function (aSite) {
// The site must be valid and not in the current grid. // The site must be valid and not in the current grid.
if (!aSite || aSites.contains(aSite)) if (!aSite || aSites.indexOf(aSite) != -1)
return; return;
batch.push(new Promise(resolve => { batch.push(new Promise(resolve => {

View File

@ -18,7 +18,7 @@ var permissionObserver = {
if (aTopic == "perm-changed") { if (aTopic == "perm-changed") {
var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission); var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission);
if (permission.host == gPermURI.host) { if (permission.host == gPermURI.host) {
if (gPermissions.contains(permission.type)) if (gPermissions.indexOf(permission.type) > -1)
initRow(permission.type); initRow(permission.type);
else if (permission.type.startsWith("plugin")) else if (permission.type.startsWith("plugin"))
setPluginsRadioState(); setPluginsRadioState();

View File

@ -152,9 +152,9 @@ var gSyncSetup = {
// Only open the dialog if username + password are actually correct. // Only open the dialog if username + password are actually correct.
Weave.Service.login(); Weave.Service.login();
if (![Weave.LOGIN_FAILED_INVALID_PASSPHRASE, if ([Weave.LOGIN_FAILED_INVALID_PASSPHRASE,
Weave.LOGIN_FAILED_NO_PASSPHRASE, Weave.LOGIN_FAILED_NO_PASSPHRASE,
Weave.LOGIN_SUCCEEDED].contains(Weave.Status.login)) { Weave.LOGIN_SUCCEEDED].indexOf(Weave.Status.login) == -1) {
return; return;
} }

View File

@ -1668,7 +1668,7 @@
if (!docShellsSwapped && !uriIsAboutBlank) { if (!docShellsSwapped && !uriIsAboutBlank) {
// pretend the user typed this so it'll be available till // pretend the user typed this so it'll be available till
// the document successfully loads // the document successfully loads
if (aURI && !gInitialPages.contains(aURI)) if (aURI && gInitialPages.indexOf(aURI) == -1)
b.userTypedValue = aURI; b.userTypedValue = aURI;
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE; let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
@ -2167,14 +2167,14 @@
var tab = aTab; var tab = aTab;
do { do {
tab = tab.nextSibling; tab = tab.nextSibling;
} while (tab && !remainingTabs.contains(tab)); } while (tab && remainingTabs.indexOf(tab) == -1);
if (!tab) { if (!tab) {
tab = aTab; tab = aTab;
do { do {
tab = tab.previousSibling; tab = tab.previousSibling;
} while (tab && !remainingTabs.contains(tab)); } while (tab && remainingTabs.indexOf(tab) == -1);
} }
this.selectedTab = tab; this.selectedTab = tab;
@ -2422,10 +2422,10 @@
<body> <body>
<![CDATA[ <![CDATA[
Array.forEach(this.tabs, function(tab) { Array.forEach(this.tabs, function(tab) {
if (aTabs.contains(tab)) if (aTabs.indexOf(tab) == -1)
this.showTab(tab);
else
this.hideTab(tab); this.hideTab(tab);
else
this.showTab(tab);
}, this); }, this);
this.tabContainer._handleTabSelect(false); this.tabContainer._handleTabSelect(false);

View File

@ -69,23 +69,17 @@ let successfulPinningPageListener = {
// The browser should load about:neterror, when this happens, proceed // The browser should load about:neterror, when this happens, proceed
// to load the pinning domain again, this time removing the pinning information // to load the pinning domain again, this time removing the pinning information
let certErrorProgressListener = { let certErrorProgressListener = {
buttonClicked: false,
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) { onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) { if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
let self = this; let textElement = content.document.getElementById("errorShortDescText");
// Can't directly call button.click() in onStateChange let text = textElement.innerHTML;
executeSoon(function() { ok(text.indexOf("mozilla_pkix_error_key_pinning_failure") > 0,
let button = content.document.getElementById("errorTryAgain"); "Got a pinning error page");
// If about:neterror hasn't fully loaded, the button won't be present. gBrowser.removeProgressListener(this);
// It will eventually be there, however. gBrowser.selectedBrowser.addEventListener("load",
if (button && !self.buttonClicked) { successfulPinningRemovalPageListener,
gBrowser.removeProgressListener(self); true);
gBrowser.selectedBrowser.addEventListener("load", gBrowser.selectedBrowser.loadURI("https://" + kPinningDomain + kURLPath + "zeromaxagevalid");
successfulPinningRemovalPageListener,
true);
gBrowser.selectedBrowser.loadURI("https://" + kPinningDomain + kURLPath + "zeromaxagevalid");
}
});
} }
} }
}; };

View File

@ -13,7 +13,7 @@ function test() {
function record(aName) { function record(aName) {
info("got " + aName); info("got " + aName);
if (!actual.contains(aName)) if (actual.indexOf(aName) == -1)
actual.push(aName); actual.push(aName);
if (actual.length == expected.length) { if (actual.length == expected.length) {
is(actual.toString(), expected.toString(), is(actual.toString(), expected.toString(),

View File

@ -212,8 +212,8 @@ let gClickHandler = {
// Check that all required methods have been called. // Check that all required methods have been called.
gCurrentTest.expectedInvokedMethods.forEach(function(aExpectedMethodName) { gCurrentTest.expectedInvokedMethods.forEach(function(aExpectedMethodName) {
ok(gInvokedMethods.contains(aExpectedMethodName), isnot(gInvokedMethods.indexOf(aExpectedMethodName), -1,
gCurrentTest.desc + ":" + aExpectedMethodName + " was invoked"); gCurrentTest.desc + ":" + aExpectedMethodName + " was invoked");
}); });
if (gInvokedMethods.length != gCurrentTest.expectedInvokedMethods.length) { if (gInvokedMethods.length != gCurrentTest.expectedInvokedMethods.length) {

View File

@ -33,7 +33,7 @@ function promiseObserverCalled(aTopic, aAction) {
ok(true, "got " + aTopic + " notification"); ok(true, "got " + aTopic + " notification");
Services.obs.removeObserver(observer, aTopic); Services.obs.removeObserver(observer, aTopic);
if (kObservedTopics.contains(aTopic)) { if (kObservedTopics.indexOf(aTopic) != -1) {
if (!(aTopic in gObservedTopics)) if (!(aTopic in gObservedTopics))
gObservedTopics[aTopic] = -1; gObservedTopics[aTopic] = -1;
else else
@ -827,7 +827,7 @@ let gTests = [
if (node.localName == "menuitem") if (node.localName == "menuitem")
labels.push(node.getAttribute("label")); labels.push(node.getAttribute("label"));
} }
ok(!labels.contains(alwaysLabel), "The 'Always Allow' item isn't shown"); is(labels.indexOf(alwaysLabel), -1, "The 'Always Allow' item isn't shown");
// Cleanup. // Cleanup.
yield closeStream(true); yield closeStream(true);

View File

@ -38,7 +38,7 @@ function promiseObserverCalled(aTopic, aAction) {
info("Message: " + aData); info("Message: " + aData);
Services.obs.removeObserver(observer, aTopic); Services.obs.removeObserver(observer, aTopic);
if (kObservedTopics.contains(aTopic)) { if (kObservedTopics.indexOf(aTopic) != -1) {
if (!(aTopic in gObservedTopics)) if (!(aTopic in gObservedTopics))
gObservedTopics[aTopic] = -1; gObservedTopics[aTopic] = -1;
else else

View File

@ -691,7 +691,7 @@ function is_hidden(element) {
if (style.visibility != "visible") if (style.visibility != "visible")
return true; return true;
if (style.display == "-moz-popup") if (style.display == "-moz-popup")
return ["hiding","closed"].contains(element.state); return ["hiding","closed"].indexOf(element.state) != -1;
// Hiding a parent element will hide all its children // Hiding a parent element will hide all its children
if (element.parentNode != element.ownerDocument) if (element.parentNode != element.ownerDocument)

View File

@ -891,7 +891,7 @@ function waitForEvents(event)
} }
} }
const isOSXMtnLion = navigator.userAgent.contains("Mac OS X 10.8"); const isOSXMtnLion = navigator.userAgent.indexOf("Mac OS X 10.8") != -1;
if (isOSXMtnLion) { if (isOSXMtnLion) {
todo(false, "Mountain Lion doesn't like this test (bug 792304)"); todo(false, "Mountain Lion doesn't like this test (bug 792304)");

View File

@ -199,7 +199,7 @@
let protocol = value.match(/^[a-z\d.+\-]+:(?=[^\d])/); let protocol = value.match(/^[a-z\d.+\-]+:(?=[^\d])/);
if (protocol && if (protocol &&
!["http:", "https:", "ftp:"].contains(protocol[0])) ["http:", "https:", "ftp:"].indexOf(protocol[0]) == -1)
return; return;
let matchedURL = value.match(/^((?:[a-z]+:\/\/)?(?:[^\/]+@)?)(.+?)(?::\d+)?(?:\/|$)/); let matchedURL = value.match(/^((?:[a-z]+:\/\/)?(?:[^\/]+@)?)(.+?)(?::\d+)?(?:\/|$)/);
if (!matchedURL) if (!matchedURL)

View File

@ -58,10 +58,10 @@
# location which also work on other platforms. # location which also work on other platforms.
# #
# @DIR_MACOS@ # @DIR_MACOS@
# Equals Contents/MacOS/ on Mac OX X and is an empty string on other platforms. # Equals Contents/MacOS/ on Mac OS X and is an empty string on other platforms.
# #
# @DIR_RESOURCES@ # @DIR_RESOURCES@
# Equals Contents/Resources/ on Mac OX X and is an empty string on other # Equals Contents/Resources/ on Mac OS X and is an empty string on other
# platforms. # platforms.
# Common File Removals # Common File Removals

View File

@ -77,9 +77,18 @@ public:
void BufferFilled() { void BufferFilled() {
// It's okay to have exactly zero samples here, it can happen we have an // It's okay to have exactly zero samples here, it can happen we have an
// audio callback driver because of a hint on MSG creation, but the // audio callback driver because of a hint on MSG creation, but the
// AudioOutputStream has not been created yet. // AudioOutputStream has not been created yet, or if all the streams have finished
// but we're still running.
// Note: it's also ok if we had data in the scratch buffer - and we usually do - and
// all the streams were ended (no mixer callback occured).
// XXX Remove this warning, or find a way to avoid it if the mixer callback
// isn't called.
NS_WARN_IF_FALSE(Available() == 0 || mSampleWriteOffset == 0, NS_WARN_IF_FALSE(Available() == 0 || mSampleWriteOffset == 0,
"Audio Buffer is not full by the end of the callback."); "Audio Buffer is not full by the end of the callback.");
// Make sure the data returned is always set and not random!
if (Available()) {
PodZero(mBuffer + mSampleWriteOffset, FramesToSamples(CHANNELS, Available()));
}
MOZ_ASSERT(mSamples, "Buffer not set."); MOZ_ASSERT(mSamples, "Buffer not set.");
mSamples = 0; mSamples = 0;
mSampleWriteOffset = 0; mSampleWriteOffset = 0;

View File

@ -6,7 +6,6 @@
#include "mozilla/dom/SVGCircleElement.h" #include "mozilla/dom/SVGCircleElement.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "nsGkAtoms.h" #include "nsGkAtoms.h"
#include "gfxContext.h"
#include "mozilla/dom/SVGCircleElementBinding.h" #include "mozilla/dom/SVGCircleElementBinding.h"
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Circle) NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Circle)
@ -82,17 +81,6 @@ SVGCircleElement::GetLengthInfo()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// nsSVGPathGeometryElement methods // nsSVGPathGeometryElement methods
void
SVGCircleElement::ConstructPath(gfxContext *aCtx)
{
float x, y, r;
GetAnimatedLengthValues(&x, &y, &r, nullptr);
if (r > 0.0f)
aCtx->Arc(gfxPoint(x, y), r, 0, 2*M_PI);
}
TemporaryRef<Path> TemporaryRef<Path>
SVGCircleElement::BuildPath(PathBuilder* aBuilder) SVGCircleElement::BuildPath(PathBuilder* aBuilder)
{ {

View File

@ -30,7 +30,6 @@ public:
virtual bool HasValidDimensions() const MOZ_OVERRIDE; virtual bool HasValidDimensions() const MOZ_OVERRIDE;
// nsSVGPathGeometryElement methods: // nsSVGPathGeometryElement methods:
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE; virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;

View File

@ -159,7 +159,8 @@ void
SVGContentUtils::GetStrokeOptions(AutoStrokeOptions* aStrokeOptions, SVGContentUtils::GetStrokeOptions(AutoStrokeOptions* aStrokeOptions,
nsSVGElement* aElement, nsSVGElement* aElement,
nsStyleContext* aStyleContext, nsStyleContext* aStyleContext,
gfxTextContextPaint *aContextPaint) gfxTextContextPaint *aContextPaint,
StrokeOptionFlags aFlags)
{ {
nsRefPtr<nsStyleContext> styleContext; nsRefPtr<nsStyleContext> styleContext;
if (aStyleContext) { if (aStyleContext) {
@ -176,17 +177,19 @@ SVGContentUtils::GetStrokeOptions(AutoStrokeOptions* aStrokeOptions,
const nsStyleSVG* styleSVG = styleContext->StyleSVG(); const nsStyleSVG* styleSVG = styleContext->StyleSVG();
DashState dashState = if (aFlags != eIgnoreStrokeDashing) {
GetStrokeDashData(aStrokeOptions, aElement, styleSVG, aContextPaint); DashState dashState =
GetStrokeDashData(aStrokeOptions, aElement, styleSVG, aContextPaint);
if (dashState == eNoStroke) { if (dashState == eNoStroke) {
// Hopefully this will shortcircuit any stroke operations: // Hopefully this will shortcircuit any stroke operations:
aStrokeOptions->mLineWidth = 0; aStrokeOptions->mLineWidth = 0;
return; return;
} }
if (dashState == eContinuousStroke && aStrokeOptions->mDashPattern) { if (dashState == eContinuousStroke && aStrokeOptions->mDashPattern) {
// Prevent our caller from wasting time looking at a pattern without gaps: // Prevent our caller from wasting time looking at a pattern without gaps:
aStrokeOptions->DiscardDashPattern(); aStrokeOptions->DiscardDashPattern();
}
} }
aStrokeOptions->mLineWidth = aStrokeOptions->mLineWidth =

View File

@ -128,10 +128,15 @@ public:
Float mSmallArray[16]; Float mSmallArray[16];
}; };
enum StrokeOptionFlags {
eAllStrokeOptions,
eIgnoreStrokeDashing
};
static void GetStrokeOptions(AutoStrokeOptions* aStrokeOptions, static void GetStrokeOptions(AutoStrokeOptions* aStrokeOptions,
nsSVGElement* aElement, nsSVGElement* aElement,
nsStyleContext* aStyleContext, nsStyleContext* aStyleContext,
gfxTextContextPaint *aContextPaint); gfxTextContextPaint *aContextPaint,
StrokeOptionFlags aFlags = eAllStrokeOptions);
/** /**
* Returns the current computed value of the CSS property 'stroke-width' for * Returns the current computed value of the CSS property 'stroke-width' for

View File

@ -8,7 +8,6 @@
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "mozilla/gfx/PathHelpers.h" #include "mozilla/gfx/PathHelpers.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "gfxContext.h"
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Ellipse) NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Ellipse)
@ -93,17 +92,6 @@ SVGEllipseElement::GetLengthInfo()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// nsSVGPathGeometryElement methods // nsSVGPathGeometryElement methods
void
SVGEllipseElement::ConstructPath(gfxContext *aCtx)
{
RefPtr<DrawTarget> dt = aCtx->GetDrawTarget();
RefPtr<PathBuilder> builder = dt->CreatePathBuilder(aCtx->CurrentFillRule());
RefPtr<Path> path = BuildPath(builder);
if (path) {
aCtx->SetPath(path);
}
}
TemporaryRef<Path> TemporaryRef<Path>
SVGEllipseElement::BuildPath(PathBuilder* aBuilder) SVGEllipseElement::BuildPath(PathBuilder* aBuilder)
{ {

View File

@ -30,7 +30,6 @@ public:
virtual bool HasValidDimensions() const MOZ_OVERRIDE; virtual bool HasValidDimensions() const MOZ_OVERRIDE;
// nsSVGPathGeometryElement methods: // nsSVGPathGeometryElement methods:
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE; virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;

View File

@ -12,7 +12,6 @@
#include "nsIURI.h" #include "nsIURI.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "imgINotificationObserver.h" #include "imgINotificationObserver.h"
#include "gfxContext.h"
#include "mozilla/dom/SVGImageElementBinding.h" #include "mozilla/dom/SVGImageElementBinding.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
@ -227,19 +226,6 @@ SVGImageElement::IsAttributeMapped(const nsIAtom* name) const
/* For the purposes of the update/invalidation logic pretend to /* For the purposes of the update/invalidation logic pretend to
be a rectangle. */ be a rectangle. */
void
SVGImageElement::ConstructPath(gfxContext *aCtx)
{
float x, y, width, height;
GetAnimatedLengthValues(&x, &y, &width, &height, nullptr);
if (width <= 0 || height <= 0)
return;
aCtx->Rectangle(gfxRect(x, y, width, height));
}
TemporaryRef<Path> TemporaryRef<Path>
SVGImageElement::BuildPath(PathBuilder* aBuilder) SVGImageElement::BuildPath(PathBuilder* aBuilder)
{ {

View File

@ -53,7 +53,6 @@ public:
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const MOZ_OVERRIDE; NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const MOZ_OVERRIDE;
// nsSVGPathGeometryElement methods: // nsSVGPathGeometryElement methods:
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE; virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
// nsSVGSVGElement methods: // nsSVGSVGElement methods:

View File

@ -6,7 +6,6 @@
#include "mozilla/dom/SVGLineElement.h" #include "mozilla/dom/SVGLineElement.h"
#include "mozilla/dom/SVGLineElementBinding.h" #include "mozilla/dom/SVGLineElementBinding.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "gfxContext.h"
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Line) NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Line)
@ -107,17 +106,6 @@ SVGLineElement::GetMarkPoints(nsTArray<nsSVGMark> *aMarks) {
aMarks->AppendElement(nsSVGMark(x2, y2, angle, nsSVGMark::eEnd)); aMarks->AppendElement(nsSVGMark(x2, y2, angle, nsSVGMark::eEnd));
} }
void
SVGLineElement::ConstructPath(gfxContext *aCtx)
{
float x1, y1, x2, y2;
GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nullptr);
aCtx->MoveTo(gfxPoint(x1, y1));
aCtx->LineTo(gfxPoint(x2, y2));
}
TemporaryRef<Path> TemporaryRef<Path>
SVGLineElement::BuildPath(PathBuilder* aBuilder) SVGLineElement::BuildPath(PathBuilder* aBuilder)
{ {

View File

@ -32,7 +32,6 @@ public:
// nsSVGPathGeometryElement methods: // nsSVGPathGeometryElement methods:
virtual bool IsMarkable() MOZ_OVERRIDE { return true; } virtual bool IsMarkable() MOZ_OVERRIDE { return true; }
virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE; virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE;
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE; virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const;

View File

@ -19,7 +19,6 @@
#include "nsStyleConsts.h" #include "nsStyleConsts.h"
#include "SVGContentUtils.h" #include "SVGContentUtils.h"
#include "SVGPathSegUtils.h" #include "SVGPathSegUtils.h"
#include "gfxContext.h"
#include <algorithm> #include <algorithm>
using namespace mozilla; using namespace mozilla;
@ -260,47 +259,22 @@ ApproximateZeroLengthSubpathSquareCaps(PathBuilder* aPB,
// line is rather arbitrary, other than being chosen to meet the requirements // line is rather arbitrary, other than being chosen to meet the requirements
// described in the comment above. // described in the comment above.
Float tinyLength = aStrokeWidth / 32; Float tinyLength = aStrokeWidth / 512;
aPB->MoveTo(aPoint);
aPB->LineTo(aPoint + Point(tinyLength, 0)); aPB->LineTo(aPoint + Point(tinyLength, 0));
aPB->MoveTo(aPoint); aPB->MoveTo(aPoint);
} }
static void
ApproximateZeroLengthSubpathSquareCaps(const gfxPoint &aPoint, gfxContext *aCtx)
{
// Cairo's fixed point fractional part is 8 bits wide, so its device space
// coordinate granularity is 1/256 pixels. However, to prevent user space
// |aPoint| and |aPoint + tinyAdvance| being rounded to the same device
// coordinates, we double this for |tinyAdvance|:
const gfxSize tinyAdvance = aCtx->DeviceToUser(gfxSize(2.0/256.0, 0.0));
aCtx->MoveTo(aPoint);
aCtx->LineTo(aPoint + gfxPoint(tinyAdvance.width, tinyAdvance.height));
aCtx->MoveTo(aPoint);
}
#define MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT \ #define MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT \
do { \ do { \
if (capsAreSquare && !subpathHasLength && aStrokeWidth > 0 && \ if (!subpathHasLength && hasLineCaps && aStrokeWidth > 0 && \
subpathContainsNonArc && SVGPathSegUtils::IsValidType(prevSegType) && \ subpathContainsNonMoveTo && \
SVGPathSegUtils::IsValidType(prevSegType) && \
(!IsMoveto(prevSegType) || segType == PATHSEG_CLOSEPATH)) { \ (!IsMoveto(prevSegType) || segType == PATHSEG_CLOSEPATH)) { \
ApproximateZeroLengthSubpathSquareCaps(builder, segStart, aStrokeWidth);\ ApproximateZeroLengthSubpathSquareCaps(builder, segStart, aStrokeWidth);\
} \ } \
} while(0) } while(0)
#define MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS \
do { \
if (capsAreSquare && !subpathHasLength && subpathContainsNonArc && \
SVGPathSegUtils::IsValidType(prevSegType) && \
(!IsMoveto(prevSegType) || \
segType == PATHSEG_CLOSEPATH)) { \
ApproximateZeroLengthSubpathSquareCaps(segStart, aCtx); \
} \
} while(0)
TemporaryRef<Path> TemporaryRef<Path>
SVGPathData::BuildPath(PathBuilder* builder, SVGPathData::BuildPath(PathBuilder* builder,
uint8_t aStrokeLineCap, uint8_t aStrokeLineCap,
@ -310,9 +284,9 @@ SVGPathData::BuildPath(PathBuilder* builder,
return nullptr; // paths without an initial moveto are invalid return nullptr; // paths without an initial moveto are invalid
} }
bool capsAreSquare = aStrokeLineCap == NS_STYLE_STROKE_LINECAP_SQUARE; bool hasLineCaps = aStrokeLineCap != NS_STYLE_STROKE_LINECAP_BUTT;
bool subpathHasLength = false; // visual length bool subpathHasLength = false; // visual length
bool subpathContainsNonArc = false; bool subpathContainsNonMoveTo = false;
uint32_t segType = PATHSEG_UNKNOWN; uint32_t segType = PATHSEG_UNKNOWN;
uint32_t prevSegType = PATHSEG_UNKNOWN; uint32_t prevSegType = PATHSEG_UNKNOWN;
@ -335,7 +309,7 @@ SVGPathData::BuildPath(PathBuilder* builder,
{ {
case PATHSEG_CLOSEPATH: case PATHSEG_CLOSEPATH:
// set this early to allow drawing of square caps for "M{x},{y} Z": // set this early to allow drawing of square caps for "M{x},{y} Z":
subpathContainsNonArc = true; subpathContainsNonMoveTo = true;
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT; MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT;
segEnd = pathStart; segEnd = pathStart;
builder->Close(); builder->Close();
@ -346,7 +320,6 @@ SVGPathData::BuildPath(PathBuilder* builder,
pathStart = segEnd = Point(mData[i], mData[i+1]); pathStart = segEnd = Point(mData[i], mData[i+1]);
builder->MoveTo(segEnd); builder->MoveTo(segEnd);
subpathHasLength = false; subpathHasLength = false;
subpathContainsNonArc = false;
break; break;
case PATHSEG_MOVETO_REL: case PATHSEG_MOVETO_REL:
@ -354,47 +327,42 @@ SVGPathData::BuildPath(PathBuilder* builder,
pathStart = segEnd = segStart + Point(mData[i], mData[i+1]); pathStart = segEnd = segStart + Point(mData[i], mData[i+1]);
builder->MoveTo(segEnd); builder->MoveTo(segEnd);
subpathHasLength = false; subpathHasLength = false;
subpathContainsNonArc = false;
break; break;
case PATHSEG_LINETO_ABS: case PATHSEG_LINETO_ABS:
segEnd = Point(mData[i], mData[i+1]); segEnd = Point(mData[i], mData[i+1]);
builder->LineTo(segEnd); if (segEnd != segStart) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart); builder->LineTo(segEnd);
} }
subpathContainsNonArc = true;
break; break;
case PATHSEG_LINETO_REL: case PATHSEG_LINETO_REL:
segEnd = segStart + Point(mData[i], mData[i+1]); segEnd = segStart + Point(mData[i], mData[i+1]);
builder->LineTo(segEnd); if (segEnd != segStart) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart); builder->LineTo(segEnd);
} }
subpathContainsNonArc = true;
break; break;
case PATHSEG_CURVETO_CUBIC_ABS: case PATHSEG_CURVETO_CUBIC_ABS:
cp1 = Point(mData[i], mData[i+1]); cp1 = Point(mData[i], mData[i+1]);
cp2 = Point(mData[i+2], mData[i+3]); cp2 = Point(mData[i+2], mData[i+3]);
segEnd = Point(mData[i+4], mData[i+5]); segEnd = Point(mData[i+4], mData[i+5]);
builder->BezierTo(cp1, cp2, segEnd); if (segEnd != segStart || segEnd != cp1 || segEnd != cp2) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2); builder->BezierTo(cp1, cp2, segEnd);
} }
subpathContainsNonArc = true;
break; break;
case PATHSEG_CURVETO_CUBIC_REL: case PATHSEG_CURVETO_CUBIC_REL:
cp1 = segStart + Point(mData[i], mData[i+1]); cp1 = segStart + Point(mData[i], mData[i+1]);
cp2 = segStart + Point(mData[i+2], mData[i+3]); cp2 = segStart + Point(mData[i+2], mData[i+3]);
segEnd = segStart + Point(mData[i+4], mData[i+5]); segEnd = segStart + Point(mData[i+4], mData[i+5]);
builder->BezierTo(cp1, cp2, segEnd); if (segEnd != segStart || segEnd != cp1 || segEnd != cp2) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2); builder->BezierTo(cp1, cp2, segEnd);
} }
subpathContainsNonArc = true;
break; break;
case PATHSEG_CURVETO_QUADRATIC_ABS: case PATHSEG_CURVETO_QUADRATIC_ABS:
@ -403,11 +371,10 @@ SVGPathData::BuildPath(PathBuilder* builder,
tcp1 = segStart + (cp1 - segStart) * 2 / 3; tcp1 = segStart + (cp1 - segStart) * 2 / 3;
segEnd = Point(mData[i+2], mData[i+3]); // set before setting tcp2! segEnd = Point(mData[i+2], mData[i+3]); // set before setting tcp2!
tcp2 = cp1 + (segEnd - cp1) / 3; tcp2 = cp1 + (segEnd - cp1) / 3;
builder->BezierTo(tcp1, tcp2, segEnd); if (segEnd != segStart || segEnd != cp1) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart || segEnd != cp1); builder->BezierTo(tcp1, tcp2, segEnd);
} }
subpathContainsNonArc = true;
break; break;
case PATHSEG_CURVETO_QUADRATIC_REL: case PATHSEG_CURVETO_QUADRATIC_REL:
@ -416,11 +383,10 @@ SVGPathData::BuildPath(PathBuilder* builder,
tcp1 = segStart + (cp1 - segStart) * 2 / 3; tcp1 = segStart + (cp1 - segStart) * 2 / 3;
segEnd = segStart + Point(mData[i+2], mData[i+3]); // set before setting tcp2! segEnd = segStart + Point(mData[i+2], mData[i+3]); // set before setting tcp2!
tcp2 = cp1 + (segEnd - cp1) / 3; tcp2 = cp1 + (segEnd - cp1) / 3;
builder->BezierTo(tcp1, tcp2, segEnd); if (segEnd != segStart || segEnd != cp1) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart || segEnd != cp1); builder->BezierTo(tcp1, tcp2, segEnd);
} }
subpathContainsNonArc = true;
break; break;
case PATHSEG_ARC_ABS: case PATHSEG_ARC_ABS:
@ -432,6 +398,7 @@ SVGPathData::BuildPath(PathBuilder* builder,
segEnd += segStart; segEnd += segStart;
} }
if (segEnd != segStart) { if (segEnd != segStart) {
subpathHasLength = true;
if (radii.x == 0.0f || radii.y == 0.0f) { if (radii.x == 0.0f || radii.y == 0.0f) {
builder->LineTo(segEnd); builder->LineTo(segEnd);
} else { } else {
@ -442,68 +409,59 @@ SVGPathData::BuildPath(PathBuilder* builder,
} }
} }
} }
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
break; break;
} }
case PATHSEG_LINETO_HORIZONTAL_ABS: case PATHSEG_LINETO_HORIZONTAL_ABS:
segEnd = Point(mData[i], segStart.y); segEnd = Point(mData[i], segStart.y);
builder->LineTo(segEnd); if (segEnd != segStart) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart); builder->LineTo(segEnd);
} }
subpathContainsNonArc = true;
break; break;
case PATHSEG_LINETO_HORIZONTAL_REL: case PATHSEG_LINETO_HORIZONTAL_REL:
segEnd = segStart + Point(mData[i], 0.0f); segEnd = segStart + Point(mData[i], 0.0f);
builder->LineTo(segEnd); if (segEnd != segStart) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart); builder->LineTo(segEnd);
} }
subpathContainsNonArc = true;
break; break;
case PATHSEG_LINETO_VERTICAL_ABS: case PATHSEG_LINETO_VERTICAL_ABS:
segEnd = Point(segStart.x, mData[i]); segEnd = Point(segStart.x, mData[i]);
builder->LineTo(segEnd); if (segEnd != segStart) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart); builder->LineTo(segEnd);
} }
subpathContainsNonArc = true;
break; break;
case PATHSEG_LINETO_VERTICAL_REL: case PATHSEG_LINETO_VERTICAL_REL:
segEnd = segStart + Point(0.0f, mData[i]); segEnd = segStart + Point(0.0f, mData[i]);
builder->LineTo(segEnd); if (segEnd != segStart) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart); builder->LineTo(segEnd);
} }
subpathContainsNonArc = true;
break; break;
case PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: case PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ? segStart * 2 - cp2 : segStart; cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ? segStart * 2 - cp2 : segStart;
cp2 = Point(mData[i], mData[i+1]); cp2 = Point(mData[i], mData[i+1]);
segEnd = Point(mData[i+2], mData[i+3]); segEnd = Point(mData[i+2], mData[i+3]);
builder->BezierTo(cp1, cp2, segEnd); if (segEnd != segStart || segEnd != cp1 || segEnd != cp2) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2); builder->BezierTo(cp1, cp2, segEnd);
} }
subpathContainsNonArc = true;
break; break;
case PATHSEG_CURVETO_CUBIC_SMOOTH_REL: case PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ? segStart * 2 - cp2 : segStart; cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ? segStart * 2 - cp2 : segStart;
cp2 = segStart + Point(mData[i], mData[i+1]); cp2 = segStart + Point(mData[i], mData[i+1]);
segEnd = segStart + Point(mData[i+2], mData[i+3]); segEnd = segStart + Point(mData[i+2], mData[i+3]);
builder->BezierTo(cp1, cp2, segEnd); if (segEnd != segStart || segEnd != cp1 || segEnd != cp2) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2); builder->BezierTo(cp1, cp2, segEnd);
} }
subpathContainsNonArc = true;
break; break;
case PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: case PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
@ -512,11 +470,10 @@ SVGPathData::BuildPath(PathBuilder* builder,
tcp1 = segStart + (cp1 - segStart) * 2 / 3; tcp1 = segStart + (cp1 - segStart) * 2 / 3;
segEnd = Point(mData[i], mData[i+1]); // set before setting tcp2! segEnd = Point(mData[i], mData[i+1]); // set before setting tcp2!
tcp2 = cp1 + (segEnd - cp1) / 3; tcp2 = cp1 + (segEnd - cp1) / 3;
builder->BezierTo(tcp1, tcp2, segEnd); if (segEnd != segStart || segEnd != cp1) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart || segEnd != cp1); builder->BezierTo(tcp1, tcp2, segEnd);
} }
subpathContainsNonArc = true;
break; break;
case PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: case PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
@ -525,17 +482,19 @@ SVGPathData::BuildPath(PathBuilder* builder,
tcp1 = segStart + (cp1 - segStart) * 2 / 3; tcp1 = segStart + (cp1 - segStart) * 2 / 3;
segEnd = segStart + Point(mData[i], mData[i+1]); // changed before setting tcp2! segEnd = segStart + Point(mData[i], mData[i+1]); // changed before setting tcp2!
tcp2 = cp1 + (segEnd - cp1) / 3; tcp2 = cp1 + (segEnd - cp1) / 3;
builder->BezierTo(tcp1, tcp2, segEnd); if (segEnd != segStart || segEnd != cp1) {
if (!subpathHasLength) { subpathHasLength = true;
subpathHasLength = (segEnd != segStart || segEnd != cp1); builder->BezierTo(tcp1, tcp2, segEnd);
} }
subpathContainsNonArc = true;
break; break;
default: default:
NS_NOTREACHED("Bad path segment type"); NS_NOTREACHED("Bad path segment type");
return nullptr; // according to spec we'd use everything up to the bad seg anyway return nullptr; // according to spec we'd use everything up to the bad seg anyway
} }
subpathContainsNonMoveTo = segType != PATHSEG_MOVETO_ABS &&
segType != PATHSEG_MOVETO_REL;
i += argCount; i += argCount;
prevSegType = segType; prevSegType = segType;
segStart = segEnd; segStart = segEnd;
@ -550,258 +509,6 @@ SVGPathData::BuildPath(PathBuilder* builder,
return builder->Finish(); return builder->Finish();
} }
void
SVGPathData::ConstructPath(gfxContext *aCtx) const
{
if (mData.IsEmpty() || !IsMoveto(SVGPathSegUtils::DecodeType(mData[0]))) {
return; // paths without an initial moveto are invalid
}
bool capsAreSquare = aCtx->CurrentLineCap() == gfxContext::LINE_CAP_SQUARE;
bool subpathHasLength = false; // visual length
bool subpathContainsNonArc = false;
uint32_t segType = PATHSEG_UNKNOWN;
uint32_t prevSegType = PATHSEG_UNKNOWN;
gfxPoint pathStart(0.0, 0.0); // start point of [sub]path
gfxPoint segStart(0.0, 0.0);
gfxPoint segEnd;
gfxPoint cp1, cp2; // previous bezier's control points
gfxPoint tcp1, tcp2; // temporaries
// Regarding cp1 and cp2: If the previous segment was a cubic bezier curve,
// then cp2 is its second control point. If the previous segment was a
// quadratic curve, then cp1 is its (only) control point.
uint32_t i = 0;
while (i < mData.Length()) {
segType = SVGPathSegUtils::DecodeType(mData[i++]);
uint32_t argCount = SVGPathSegUtils::ArgCountForType(segType);
switch (segType)
{
case PATHSEG_CLOSEPATH:
// set this early to allow drawing of square caps for "M{x},{y} Z":
subpathContainsNonArc = true;
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS;
segEnd = pathStart;
aCtx->ClosePath();
break;
case PATHSEG_MOVETO_ABS:
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS;
pathStart = segEnd = gfxPoint(mData[i], mData[i+1]);
aCtx->MoveTo(segEnd);
subpathHasLength = false;
subpathContainsNonArc = false;
break;
case PATHSEG_MOVETO_REL:
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS;
pathStart = segEnd = segStart + gfxPoint(mData[i], mData[i+1]);
aCtx->MoveTo(segEnd);
subpathHasLength = false;
subpathContainsNonArc = false;
break;
case PATHSEG_LINETO_ABS:
segEnd = gfxPoint(mData[i], mData[i+1]);
aCtx->LineTo(segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
subpathContainsNonArc = true;
break;
case PATHSEG_LINETO_REL:
segEnd = segStart + gfxPoint(mData[i], mData[i+1]);
aCtx->LineTo(segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_CUBIC_ABS:
cp1 = gfxPoint(mData[i], mData[i+1]);
cp2 = gfxPoint(mData[i+2], mData[i+3]);
segEnd = gfxPoint(mData[i+4], mData[i+5]);
aCtx->CurveTo(cp1, cp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_CUBIC_REL:
cp1 = segStart + gfxPoint(mData[i], mData[i+1]);
cp2 = segStart + gfxPoint(mData[i+2], mData[i+3]);
segEnd = segStart + gfxPoint(mData[i+4], mData[i+5]);
aCtx->CurveTo(cp1, cp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_QUADRATIC_ABS:
cp1 = gfxPoint(mData[i], mData[i+1]);
// Convert quadratic curve to cubic curve:
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
segEnd = gfxPoint(mData[i+2], mData[i+3]); // set before setting tcp2!
tcp2 = cp1 + (segEnd - cp1) / 3;
aCtx->CurveTo(tcp1, tcp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_QUADRATIC_REL:
cp1 = segStart + gfxPoint(mData[i], mData[i+1]);
// Convert quadratic curve to cubic curve:
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
segEnd = segStart + gfxPoint(mData[i+2], mData[i+3]); // set before setting tcp2!
tcp2 = cp1 + (segEnd - cp1) / 3;
aCtx->CurveTo(tcp1, tcp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1);
}
subpathContainsNonArc = true;
break;
case PATHSEG_ARC_ABS:
case PATHSEG_ARC_REL:
{
gfxPoint radii(mData[i], mData[i+1]);
segEnd = gfxPoint(mData[i+5], mData[i+6]);
if (segType == PATHSEG_ARC_REL) {
segEnd += segStart;
}
if (segEnd != segStart) {
if (radii.x == 0.0f || radii.y == 0.0f) {
aCtx->LineTo(segEnd);
} else {
nsSVGArcConverter converter(ToPoint(segStart), ToPoint(segEnd),
ToPoint(radii), mData[i+2],
mData[i+3] != 0, mData[i+4] != 0);
Point cp1, cp2, segEnd_;
while (converter.GetNextSegment(&cp1, &cp2, &segEnd_)) {
aCtx->CurveTo(ThebesPoint(cp1), ThebesPoint(cp2), ThebesPoint(segEnd_));
}
segEnd = ThebesPoint(segEnd_);
}
}
if (!subpathHasLength) {
// Round to make sure the current comparison doesn't fail due to
// precision issues:
// XXX kill after all code is converted to float precision
segStart = ThebesPoint(ToPoint(segStart));
subpathHasLength = (segEnd != segStart);
}
break;
}
case PATHSEG_LINETO_HORIZONTAL_ABS:
segEnd = gfxPoint(mData[i], segStart.y);
aCtx->LineTo(segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
subpathContainsNonArc = true;
break;
case PATHSEG_LINETO_HORIZONTAL_REL:
segEnd = segStart + gfxPoint(mData[i], 0.0f);
aCtx->LineTo(segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
subpathContainsNonArc = true;
break;
case PATHSEG_LINETO_VERTICAL_ABS:
segEnd = gfxPoint(segStart.x, mData[i]);
aCtx->LineTo(segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
subpathContainsNonArc = true;
break;
case PATHSEG_LINETO_VERTICAL_REL:
segEnd = segStart + gfxPoint(0.0f, mData[i]);
aCtx->LineTo(segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ? segStart * 2 - cp2 : segStart;
cp2 = gfxPoint(mData[i], mData[i+1]);
segEnd = gfxPoint(mData[i+2], mData[i+3]);
aCtx->CurveTo(cp1, cp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
cp1 = SVGPathSegUtils::IsCubicType(prevSegType) ? segStart * 2 - cp2 : segStart;
cp2 = segStart + gfxPoint(mData[i], mData[i+1]);
segEnd = segStart + gfxPoint(mData[i+2], mData[i+3]);
aCtx->CurveTo(cp1, cp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1 || segEnd != cp2);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
cp1 = SVGPathSegUtils::IsQuadraticType(prevSegType) ? segStart * 2 - cp1 : segStart;
// Convert quadratic curve to cubic curve:
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
segEnd = gfxPoint(mData[i], mData[i+1]); // set before setting tcp2!
tcp2 = cp1 + (segEnd - cp1) / 3;
aCtx->CurveTo(tcp1, tcp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1);
}
subpathContainsNonArc = true;
break;
case PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
cp1 = SVGPathSegUtils::IsQuadraticType(prevSegType) ? segStart * 2 - cp1 : segStart;
// Convert quadratic curve to cubic curve:
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
segEnd = segStart + gfxPoint(mData[i], mData[i+1]); // changed before setting tcp2!
tcp2 = cp1 + (segEnd - cp1) / 3;
aCtx->CurveTo(tcp1, tcp2, segEnd);
if (!subpathHasLength) {
subpathHasLength = (segEnd != segStart || segEnd != cp1);
}
subpathContainsNonArc = true;
break;
default:
NS_NOTREACHED("Bad path segment type");
return; // according to spec we'd use everything up to the bad seg anyway
}
i += argCount;
prevSegType = segType;
segStart = segEnd;
}
NS_ABORT_IF_FALSE(i == mData.Length(), "Very, very bad - mData corrupt");
NS_ABORT_IF_FALSE(prevSegType == segType,
"prevSegType should be left at the final segType");
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS;
}
TemporaryRef<Path> TemporaryRef<Path>
SVGPathData::ToPathForLengthOrPositionMeasuring() const SVGPathData::ToPathForLengthOrPositionMeasuring() const
{ {

View File

@ -20,7 +20,6 @@
#include <string.h> #include <string.h>
class gfxContext;
class nsSVGPathDataParser; // IWYU pragma: keep class nsSVGPathDataParser; // IWYU pragma: keep
struct nsSVGMark; struct nsSVGMark;
@ -166,7 +165,6 @@ public:
*/ */
TemporaryRef<Path> ToPathForLengthOrPositionMeasuring() const; TemporaryRef<Path> ToPathForLengthOrPositionMeasuring() const;
void ConstructPath(gfxContext *aCtx) const;
TemporaryRef<Path> BuildPath(PathBuilder* aBuilder, TemporaryRef<Path> BuildPath(PathBuilder* aBuilder,
uint8_t aCapStyle, uint8_t aCapStyle,
Float aStrokeWidth) const; Float aStrokeWidth) const;

View File

@ -22,8 +22,6 @@
#include "nsStyleStruct.h" #include "nsStyleStruct.h"
#include "SVGContentUtils.h" #include "SVGContentUtils.h"
class gfxContext;
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Path) NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Path)
using namespace mozilla::gfx; using namespace mozilla::gfx;
@ -334,12 +332,6 @@ SVGPathElement::GetMarkPoints(nsTArray<nsSVGMark> *aMarks)
mD.GetAnimValue().GetMarkerPositioningData(aMarks); mD.GetAnimValue().GetMarkerPositioningData(aMarks);
} }
void
SVGPathElement::ConstructPath(gfxContext *aCtx)
{
mD.GetAnimValue().ConstructPath(aCtx);
}
float float
SVGPathElement::GetPathLengthScale(PathLengthScaleForType aFor) SVGPathElement::GetPathLengthScale(PathLengthScaleForType aFor)
{ {
@ -392,7 +384,7 @@ SVGPathElement::BuildPath(PathBuilder* aBuilder)
// exposes hit-testing of strokes that are not actually painted. For that // exposes hit-testing of strokes that are not actually painted. For that
// reason we do not check for eStyleSVGPaintType_None or check the stroke // reason we do not check for eStyleSVGPaintType_None or check the stroke
// opacity here. // opacity here.
if (style->mStrokeLinecap == NS_STYLE_STROKE_LINECAP_SQUARE) { if (style->mStrokeLinecap != NS_STYLE_STROKE_LINECAP_BUTT) {
strokeLineCap = style->mStrokeLinecap; strokeLineCap = style->mStrokeLinecap;
strokeWidth = SVGContentUtils::GetStrokeWidth(this, styleContext, nullptr); strokeWidth = SVGContentUtils::GetStrokeWidth(this, styleContext, nullptr);
} }

View File

@ -16,8 +16,6 @@
nsresult NS_NewSVGPathElement(nsIContent **aResult, nsresult NS_NewSVGPathElement(nsIContent **aResult,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo); already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
class gfxContext;
typedef nsSVGPathGeometryElement SVGPathElementBase; typedef nsSVGPathGeometryElement SVGPathElementBase;
namespace mozilla { namespace mozilla {
@ -52,7 +50,6 @@ public:
virtual bool AttributeDefinesGeometry(const nsIAtom *aName) MOZ_OVERRIDE; virtual bool AttributeDefinesGeometry(const nsIAtom *aName) MOZ_OVERRIDE;
virtual bool IsMarkable() MOZ_OVERRIDE; virtual bool IsMarkable() MOZ_OVERRIDE;
virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE; virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE;
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE; virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
/** /**

View File

@ -8,7 +8,6 @@
#include "SVGPathSegUtils.h" #include "SVGPathSegUtils.h"
#include "gfx2DGlue.h" #include "gfx2DGlue.h"
#include "gfxPoint.h"
#include "nsSVGPathDataParser.h" #include "nsSVGPathDataParser.h"
#include "nsTextFormatter.h" #include "nsTextFormatter.h"

View File

@ -5,7 +5,6 @@
#include "mozilla/dom/SVGPolygonElement.h" #include "mozilla/dom/SVGPolygonElement.h"
#include "mozilla/dom/SVGPolygonElementBinding.h" #include "mozilla/dom/SVGPolygonElementBinding.h"
#include "gfxContext.h"
#include "SVGContentUtils.h" #include "SVGContentUtils.h"
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Polygon) NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Polygon)
@ -58,14 +57,5 @@ SVGPolygonElement::GetMarkPoints(nsTArray<nsSVGMark> *aMarks)
nsSVGMark::eEnd)); nsSVGMark::eEnd));
} }
void
SVGPolygonElement::ConstructPath(gfxContext *aCtx)
{
SVGPolygonElementBase::ConstructPath(aCtx);
// the difference between a polyline and a polygon is that the
// polygon is closed:
aCtx->ClosePath();
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -28,7 +28,6 @@ protected:
public: public:
// nsSVGPathGeometryElement methods: // nsSVGPathGeometryElement methods:
virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE; virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE;
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const;
}; };

View File

@ -5,7 +5,6 @@
#include "mozilla/dom/SVGRectElement.h" #include "mozilla/dom/SVGRectElement.h"
#include "nsGkAtoms.h" #include "nsGkAtoms.h"
#include "gfxContext.h"
#include "mozilla/dom/SVGRectElementBinding.h" #include "mozilla/dom/SVGRectElementBinding.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "mozilla/gfx/PathHelpers.h" #include "mozilla/gfx/PathHelpers.h"
@ -109,49 +108,6 @@ SVGRectElement::GetLengthInfo()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// nsSVGPathGeometryElement methods // nsSVGPathGeometryElement methods
void
SVGRectElement::ConstructPath(gfxContext *aCtx)
{
float x, y, width, height, rx, ry;
GetAnimatedLengthValues(&x, &y, &width, &height, &rx, &ry, nullptr);
/* In a perfect world, this would be handled by the DOM, and
return a DOM exception. */
if (width <= 0 || height <= 0)
return;
rx = std::max(rx, 0.0f);
ry = std::max(ry, 0.0f);
/* optimize the no rounded corners case */
if (rx == 0 && ry == 0) {
aCtx->Rectangle(gfxRect(x, y, width, height));
return;
}
/* If either the 'rx' or the 'ry' attribute isn't set, then we
have to set it to the value of the other. */
bool hasRx = mLengthAttributes[ATTR_RX].IsExplicitlySet();
bool hasRy = mLengthAttributes[ATTR_RY].IsExplicitlySet();
if (hasRx && !hasRy)
ry = rx;
else if (hasRy && !hasRx)
rx = ry;
/* Clamp rx and ry to half the rect's width and height respectively. */
float halfWidth = width/2;
float halfHeight = height/2;
if (rx > halfWidth)
rx = halfWidth;
if (ry > halfHeight)
ry = halfHeight;
gfxSize corner(rx, ry);
aCtx->RoundedRectangle(gfxRect(x, y, width, height),
gfxCornerSizes(corner, corner, corner, corner));
}
TemporaryRef<Path> TemporaryRef<Path>
SVGRectElement::BuildPath(PathBuilder* aBuilder) SVGRectElement::BuildPath(PathBuilder* aBuilder)
{ {

View File

@ -30,7 +30,6 @@ public:
virtual bool HasValidDimensions() const MOZ_OVERRIDE; virtual bool HasValidDimensions() const MOZ_OVERRIDE;
// nsSVGPathGeometryElement methods: // nsSVGPathGeometryElement methods:
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE; virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;

View File

@ -259,6 +259,7 @@ LOCAL_INCLUDES += [
'/dom/smil', '/dom/smil',
'/dom/xbl', '/dom/xbl',
'/dom/xml', '/dom/xml',
'/layout/base',
'/layout/generic', '/layout/generic',
'/layout/style', '/layout/style',
'/layout/svg', '/layout/svg',

View File

@ -51,6 +51,7 @@
#include "nsSMILAnimationController.h" #include "nsSMILAnimationController.h"
#include "mozilla/dom/SVGElementBinding.h" #include "mozilla/dom/SVGElementBinding.h"
#include "mozilla/unused.h" #include "mozilla/unused.h"
#include "RestyleManager.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom; using namespace mozilla::dom;
@ -916,17 +917,18 @@ nsSVGElement::WalkAnimatedContentStyleRules(nsRuleWalker* aRuleWalker)
// whether this is a "no-animation restyle". (This should match the check // whether this is a "no-animation restyle". (This should match the check
// in nsHTMLCSSStyleSheet::RulesMatching(), where we determine whether to // in nsHTMLCSSStyleSheet::RulesMatching(), where we determine whether to
// apply the SMILOverrideStyle.) // apply the SMILOverrideStyle.)
nsIDocument* doc = OwnerDoc(); nsPresContext* context = aRuleWalker->PresContext();
nsIPresShell* shell = doc->GetShell(); nsIPresShell* shell = context->PresShell();
nsPresContext* context = shell ? shell->GetPresContext() : nullptr; RestyleManager* restyleManager = context->RestyleManager();
if (context && context->IsProcessingRestyles() && if (restyleManager->SkipAnimationRules()) {
!context->IsProcessingAnimationStyleChange()) { if (restyleManager->PostAnimationRestyles()) {
// Any style changes right now could trigger CSS Transitions. We don't // Any style changes right now could trigger CSS Transitions. We don't
// want that to happen from SMIL-animated value of mapped attrs, so // want that to happen from SMIL-animated value of mapped attrs, so
// ignore animated value for now, and request an animation restyle to // ignore animated value for now, and request an animation restyle to
// get our animated value noticed. // get our animated value noticed.
shell->RestyleForAnimation(this, shell->RestyleForAnimation(this,
eRestyle_SVGAttrAnimations | eRestyle_ChangeAnimationPhase); eRestyle_SVGAttrAnimations | eRestyle_ChangeAnimationPhase);
}
} else { } else {
// Ok, this is an animation restyle -- go ahead and update/walk the // Ok, this is an animation restyle -- go ahead and update/walk the
// animated content style rule. // animated content style rule.

View File

@ -26,8 +26,6 @@ struct nsSVGMark {
x(aX), y(aY), angle(aAngle), type(aType) {} x(aX), y(aY), angle(aAngle), type(aType) {}
}; };
class gfxContext;
typedef mozilla::dom::SVGGraphicsElement nsSVGPathGeometryElementBase; typedef mozilla::dom::SVGGraphicsElement nsSVGPathGeometryElementBase;
class nsSVGPathGeometryElement : public nsSVGPathGeometryElementBase class nsSVGPathGeometryElement : public nsSVGPathGeometryElementBase
@ -56,7 +54,6 @@ public:
virtual bool IsMarkable(); virtual bool IsMarkable();
virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks); virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks);
virtual void ConstructPath(gfxContext *aCtx) = 0;
/** /**
* Returns a Path that can be used to paint, hit-test or calculate bounds for * Returns a Path that can be used to paint, hit-test or calculate bounds for

View File

@ -5,7 +5,6 @@
#include "nsSVGPolyElement.h" #include "nsSVGPolyElement.h"
#include "DOMSVGPointList.h" #include "DOMSVGPointList.h"
#include "gfxContext.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "SVGContentUtils.h" #include "SVGContentUtils.h"
@ -121,20 +120,6 @@ nsSVGPolyElement::GetMarkPoints(nsTArray<nsSVGMark> *aMarks)
aMarks->LastElement().type = nsSVGMark::eEnd; aMarks->LastElement().type = nsSVGMark::eEnd;
} }
void
nsSVGPolyElement::ConstructPath(gfxContext *aCtx)
{
const SVGPointList &points = mPoints.GetAnimValue();
if (!points.Length())
return;
aCtx->MoveTo(points[0]);
for (uint32_t i = 1; i < points.Length(); ++i) {
aCtx->LineTo(points[i]);
}
}
TemporaryRef<Path> TemporaryRef<Path>
nsSVGPolyElement::BuildPath(PathBuilder* aBuilder) nsSVGPolyElement::BuildPath(PathBuilder* aBuilder)
{ {

View File

@ -12,8 +12,6 @@
typedef nsSVGPathGeometryElement nsSVGPolyElementBase; typedef nsSVGPathGeometryElement nsSVGPolyElementBase;
class gfxContext;
namespace mozilla { namespace mozilla {
class DOMSVGPointList; class DOMSVGPointList;
} }
@ -47,7 +45,6 @@ public:
virtual bool AttributeDefinesGeometry(const nsIAtom *aName) MOZ_OVERRIDE; virtual bool AttributeDefinesGeometry(const nsIAtom *aName) MOZ_OVERRIDE;
virtual bool IsMarkable() MOZ_OVERRIDE { return true; } virtual bool IsMarkable() MOZ_OVERRIDE { return true; }
virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE; virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE;
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
virtual mozilla::TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE; virtual mozilla::TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
// WebIDL // WebIDL

View File

@ -114,9 +114,9 @@ nsSVGTransform::SetRotate(float aAngle, float aCx, float aCy)
{ {
mType = SVG_TRANSFORM_ROTATE; mType = SVG_TRANSFORM_ROTATE;
mMatrix.Reset(); mMatrix.Reset();
mMatrix.Translate(gfxPoint(aCx, aCy)); mMatrix.Translate(aCx, aCy);
mMatrix.Rotate(aAngle*kRadPerDegree); mMatrix.Rotate(aAngle*kRadPerDegree);
mMatrix.Translate(gfxPoint(-aCx, -aCy)); mMatrix.Translate(-aCx, -aCy);
mAngle = aAngle; mAngle = aAngle;
mOriginX = aCx; mOriginX = aCx;
mOriginY = aCy; mOriginY = aCy;

View File

@ -612,7 +612,7 @@ WebappsApplication.prototype = {
case "Webapps:Connect:Return:OK": case "Webapps:Connect:Return:OK":
this.removeMessageListeners(["Webapps:Connect:Return:OK", this.removeMessageListeners(["Webapps:Connect:Return:OK",
"Webapps:Connect:Return:KO"]); "Webapps:Connect:Return:KO"]);
let messagePorts = []; let messagePorts = new this._window.Array();
msg.messagePortIDs.forEach((aPortID) => { msg.messagePortIDs.forEach((aPortID) => {
let port = new this._window.MozInterAppMessagePort(aPortID); let port = new this._window.MozInterAppMessagePort(aPortID);
messagePorts.push(port); messagePorts.push(port);
@ -626,7 +626,7 @@ WebappsApplication.prototype = {
break; break;
case "Webapps:GetConnections:Return:OK": case "Webapps:GetConnections:Return:OK":
this.removeMessageListeners(aMessage.name); this.removeMessageListeners(aMessage.name);
let connections = []; let connections = new this._window.Array();
msg.connections.forEach((aConnection) => { msg.connections.forEach((aConnection) => {
let connection = let connection =
new this._window.MozInterAppConnection(aConnection.keyword, new this._window.MozInterAppConnection(aConnection.keyword,

View File

@ -2117,7 +2117,14 @@ nsDOMWindowUtils::SendCompositionEvent(const nsAString& aType,
} else if (aType.EqualsLiteral("compositionend")) { } else if (aType.EqualsLiteral("compositionend")) {
msg = NS_COMPOSITION_END; msg = NS_COMPOSITION_END;
} else if (aType.EqualsLiteral("compositionupdate")) { } else if (aType.EqualsLiteral("compositionupdate")) {
msg = NS_COMPOSITION_UPDATE; // Now we don't support manually dispatching composition update with this
// API. compositionupdate is dispatched when text event modifies
// composition string automatically. For backward compatibility, this
// shouldn't return error in this case.
NS_WARNING("Don't call nsIDOMWindowUtils.sendCompositionEvent() for "
"compositionupdate since it's ignored and the event is "
"fired automatically when it's necessary");
return NS_OK;
} else { } else {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }

View File

@ -123,8 +123,10 @@ public:
*/ */
void UpdateWrapper(JSObject* aNewObject, const JSObject* aOldObject) void UpdateWrapper(JSObject* aNewObject, const JSObject* aOldObject)
{ {
MOZ_ASSERT(mWrapper == aOldObject); if (mWrapper) {
mWrapper = aNewObject; MOZ_ASSERT(mWrapper == aOldObject);
mWrapper = aNewObject;
}
} }
bool PreservingWrapper() bool PreservingWrapper()

View File

@ -1595,17 +1595,10 @@ bool
HasPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy, HasPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id) JS::Handle<jsid> id)
{ {
JS::Rooted<JSObject*> obj(cx, proxy);
Maybe<JSAutoCompartment> ac;
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
obj = js::UncheckedUnwrap(obj);
ac.emplace(cx, obj);
}
bool found; bool found;
// We ignore an error from GetPropertyOnPrototype. We pass nullptr // We ignore an error from GetPropertyOnPrototype. We pass nullptr
// for vp so that GetPropertyOnPrototype won't actually do a get. // for vp so that GetPropertyOnPrototype won't actually do a get.
return !GetPropertyOnPrototype(cx, obj, id, &found, nullptr) || found; return !GetPropertyOnPrototype(cx, proxy, id, &found, nullptr) || found;
} }
bool bool

View File

@ -43,8 +43,15 @@ const BT_PAIRING_REQ = "bluetooth-pairing-request";
const BT_PAIRING_PASSKEY = 123456; const BT_PAIRING_PASSKEY = 123456;
const BT_PAIRING_PINCODE = "ABCDEFG"; const BT_PAIRING_PINCODE = "ABCDEFG";
let Promise = // Emulate Promise.jsm semantics.
SpecialPowers.Cu.import("resource://gre/modules/Promise.jsm").Promise; Promise.defer = function() { return new Deferred(); }
function Deferred() {
this.promise = new Promise(function(resolve, reject) {
this.resolve = resolve;
this.reject = reject;
}.bind(this));
Object.freeze(this);
}
let bluetoothManager; let bluetoothManager;

View File

@ -36,8 +36,15 @@ const BDADDR_LOCAL = "ff:ff:ff:00:00:00";
// A user friendly name for remote BT device. // A user friendly name for remote BT device.
const REMOTE_DEVICE_NAME = "Remote_BT_Device"; const REMOTE_DEVICE_NAME = "Remote_BT_Device";
let Promise = // Emulate Promise.jsm semantics.
SpecialPowers.Cu.import("resource://gre/modules/Promise.jsm").Promise; Promise.defer = function() { return new Deferred(); }
function Deferred() {
this.promise = new Promise(function(resolve, reject) {
this.resolve = resolve;
this.reject = reject;
}.bind(this));
Object.freeze(this);
}
let bluetoothManager; let bluetoothManager;

View File

@ -3,7 +3,15 @@
const {Cc: Cc, Ci: Ci, Cr: Cr, Cu: Cu} = SpecialPowers; const {Cc: Cc, Ci: Ci, Cr: Cr, Cu: Cu} = SpecialPowers;
let Promise = Cu.import("resource://gre/modules/Promise.jsm").Promise; // Emulate Promise.jsm semantics.
Promise.defer = function() { return new Deferred(); }
function Deferred() {
this.promise = new Promise(function(resolve, reject) {
this.resolve = resolve;
this.reject = reject;
}.bind(this));
Object.freeze(this);
}
const PDU_DCS_CODING_GROUP_BITS = 0xF0; const PDU_DCS_CODING_GROUP_BITS = 0xF0;
const PDU_DCS_MSG_CODING_7BITS_ALPHABET = 0x00; const PDU_DCS_MSG_CODING_7BITS_ALPHABET = 0x00;

View File

@ -820,7 +820,6 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
compositionEvent->data = selectedText.mReply.mString; compositionEvent->data = selectedText.mReply.mString;
} }
// through to compositionend handling // through to compositionend handling
case NS_COMPOSITION_UPDATE:
case NS_COMPOSITION_END: case NS_COMPOSITION_END:
{ {
WidgetCompositionEvent* compositionEvent = aEvent->AsCompositionEvent(); WidgetCompositionEvent* compositionEvent = aEvent->AsCompositionEvent();

View File

@ -908,6 +908,9 @@ IMEStateManager::DispatchCompositionEvent(nsINode* aEventTargetNode,
return; return;
} }
MOZ_ASSERT(aEvent->message != NS_COMPOSITION_UPDATE,
"compositionupdate event shouldn't be dispatched manually");
EnsureTextCompositionArray(); EnsureTextCompositionArray();
WidgetGUIEvent* GUIEvent = aEvent->AsGUIEvent(); WidgetGUIEvent* GUIEvent = aEvent->AsGUIEvent();

View File

@ -81,16 +81,9 @@ TextComposition::MaybeDispatchCompositionUpdate(const WidgetTextEvent* aEvent)
aEvent->mFlags.mIsSynthesizedForTests; aEvent->mFlags.mIsSynthesizedForTests;
nsEventStatus status = nsEventStatus_eConsumeNoDefault; nsEventStatus status = nsEventStatus_eConsumeNoDefault;
if (aEvent->mFlags.mIsSynthesizedForTests && mLastData = compositionUpdate.data;
(mIsRequestingCommit || mIsRequestingCancel)) { EventDispatcher::Dispatch(mNode, mPresContext,
// At emulating commit/cancel request, compositionupdate should be &compositionUpdate, nullptr, &status, nullptr);
// dispatched via widget since it's more similar path to native event.
aEvent->widget->DispatchEvent(&compositionUpdate, status);
} else {
mLastData = compositionUpdate.data;
EventDispatcher::Dispatch(mNode, mPresContext,
&compositionUpdate, nullptr, &status, nullptr);
}
return !Destroyed(); return !Destroyed();
} }
@ -152,7 +145,6 @@ TextComposition::DispatchEvent(WidgetGUIEvent* aEvent,
if (!aIsSynthesized && (mIsRequestingCommit || mIsRequestingCancel)) { if (!aIsSynthesized && (mIsRequestingCommit || mIsRequestingCancel)) {
nsString* committingData = nullptr; nsString* committingData = nullptr;
switch (aEvent->message) { switch (aEvent->message) {
case NS_COMPOSITION_UPDATE:
case NS_COMPOSITION_END: case NS_COMPOSITION_END:
committingData = &aEvent->AsCompositionEvent()->data; committingData = &aEvent->AsCompositionEvent()->data;
break; break;
@ -171,26 +163,13 @@ TextComposition::DispatchEvent(WidgetGUIEvent* aEvent,
} else if (mIsRequestingCancel && !committingData->IsEmpty()) { } else if (mIsRequestingCancel && !committingData->IsEmpty()) {
committingData->Truncate(); committingData->Truncate();
} }
if (aEvent->message == NS_COMPOSITION_UPDATE) {
// If committing string is not different from the last data,
// we don't need to dispatch this.
if (committingData->Equals(mLastData)) {
return;
}
} else if (aEvent->message == NS_TEXT_TEXT) {
// If committing string is different from the last data,
// we need to dispatch compositionupdate before dispatching text event.
if (!MaybeDispatchCompositionUpdate(aEvent->AsTextEvent())) {
NS_WARNING("Dispatching compositionupdate caused destroying");
return;
}
}
} }
} }
if (aEvent->message == NS_COMPOSITION_UPDATE) { if (aEvent->message == NS_TEXT_TEXT) {
mLastData = aEvent->AsCompositionEvent()->data; if (!MaybeDispatchCompositionUpdate(aEvent->AsTextEvent())) {
return;
}
} }
EventDispatcher::Dispatch(mNode, mPresContext, EventDispatcher::Dispatch(mNode, mPresContext,
@ -341,15 +320,11 @@ TextComposition::RequestToCommit(nsIWidget* aWidget, bool aDiscard)
// Otherwise, synthesize the commit in content. // Otherwise, synthesize the commit in content.
nsAutoString data(aDiscard ? EmptyString() : lastData); nsAutoString data(aDiscard ? EmptyString() : lastData);
bool changingData = lastData != data;
if (changingData) {
DispatchCompositionEventRunnable(NS_COMPOSITION_UPDATE, data, true);
}
// If the last composition string and new data are different, we need to // If the last composition string and new data are different, we need to
// dispatch text event for removing IME selection. However, if the commit // dispatch text event for removing IME selection. However, if the commit
// string is empty string and it's not changed from the last data, we don't // string is empty string and it's not changed from the last data, we don't
// need to dispatch text event. // need to dispatch text event.
if (changingData || !data.IsEmpty()) { if (lastData != data || !data.IsEmpty()) {
DispatchCompositionEventRunnable(NS_TEXT_TEXT, data, true); DispatchCompositionEventRunnable(NS_TEXT_TEXT, data, true);
} }
DispatchCompositionEventRunnable(NS_COMPOSITION_END, data, true); DispatchCompositionEventRunnable(NS_COMPOSITION_END, data, true);
@ -468,7 +443,6 @@ TextComposition::CompositionEventDispatcher::Run()
mIsSynthesizedEvent); mIsSynthesizedEvent);
break; break;
} }
case NS_COMPOSITION_UPDATE:
case NS_COMPOSITION_END: { case NS_COMPOSITION_END: {
WidgetCompositionEvent compEvent(true, mEventMessage, widget); WidgetCompositionEvent compEvent(true, mEventMessage, widget);
compEvent.data = mData; compEvent.data = mData;

View File

@ -314,7 +314,7 @@ private:
* *
* @param aEventMessage Must be one of composition event or text event. * @param aEventMessage Must be one of composition event or text event.
* @param aData Used for data value if aEventMessage is * @param aData Used for data value if aEventMessage is
* NS_COMPOSITION_UPDATE or NS_COMPOSITION_END. * NS_COMPOSITION_END.
* Used for theText value if aEventMessage is * Used for theText value if aEventMessage is
* NS_TEXT_TEXT. * NS_TEXT_TEXT.
* @param aIsSynthesizingCommit true if this is called for synthesizing * @param aIsSynthesizingCommit true if this is called for synthesizing

View File

@ -1180,7 +1180,6 @@ function replaceSurroundingText(element, text, selectionStart, selectionEnd,
let CompositionManager = { let CompositionManager = {
_isStarted: false, _isStarted: false,
_text: '',
_clauseAttrMap: { _clauseAttrMap: {
'raw-input': 'raw-input':
Ci.nsICompositionStringSynthesizer.ATTR_RAWINPUT, Ci.nsICompositionStringSynthesizer.ATTR_RAWINPUT,
@ -1233,14 +1232,9 @@ let CompositionManager = {
if (!this._isStarted) { if (!this._isStarted) {
this._isStarted = true; this._isStarted = true;
domWindowUtils.sendCompositionEvent('compositionstart', '', ''); domWindowUtils.sendCompositionEvent('compositionstart', '', '');
this._text = '';
} }
// Update the composing text. // Update the composing text.
if (this._text !== text) {
this._text = text;
domWindowUtils.sendCompositionEvent('compositionupdate', text, '');
}
let compositionString = domWindowUtils.createCompositionStringSynthesizer(); let compositionString = domWindowUtils.createCompositionStringSynthesizer();
compositionString.setString(text); compositionString.setString(text);
for (var i = 0; i < clauseLens.length; i++) { for (var i = 0; i < clauseLens.length; i++) {
@ -1257,9 +1251,6 @@ let CompositionManager = {
return; return;
} }
// Update the composing text. // Update the composing text.
if (this._text !== text) {
domWindowUtils.sendCompositionEvent('compositionupdate', text, '');
}
let compositionString = domWindowUtils.createCompositionStringSynthesizer(); let compositionString = domWindowUtils.createCompositionStringSynthesizer();
compositionString.setString(text); compositionString.setString(text);
// Set the cursor position to |text.length| so that the text will be // Set the cursor position to |text.length| so that the text will be
@ -1267,7 +1258,6 @@ let CompositionManager = {
compositionString.setCaret(text.length, 0); compositionString.setCaret(text.length, 0);
compositionString.dispatchEvent(); compositionString.dispatchEvent();
domWindowUtils.sendCompositionEvent('compositionend', text, ''); domWindowUtils.sendCompositionEvent('compositionend', text, '');
this._text = '';
this._isStarted = false; this._isStarted = false;
}, },
@ -1277,7 +1267,6 @@ let CompositionManager = {
return; return;
} }
this._text = '';
this._isStarted = false; this._isStarted = false;
} }
}; };

View File

@ -55,10 +55,10 @@ SpecialPowers.pushPrefEnv({'set':[
// Finally, poll for the new crash record. // Finally, poll for the new crash record.
function tryGetCrash() { function tryGetCrash() {
info("Waiting for getCrashes"); info("Waiting for getCrashes");
crashMan.getCrashes().then(function (crashes) { crashMan.getCrashes().then(SpecialPowers.wrapCallback(function (crashes) {
if (crashes.length) { if (crashes.length) {
is(crashes.length, 1, "There should be only one record"); is(crashes.length, 1, "There should be only one record");
var crash = SpecialPowers.wrap(crashes[0]); var crash = crashes[0];
ok(crash.isOfType(crashMan.PROCESS_TYPE_CONTENT, ok(crash.isOfType(crashMan.PROCESS_TYPE_CONTENT,
crashMan.CRASH_TYPE_CRASH), crashMan.CRASH_TYPE_CRASH),
"Record should be a content crash"); "Record should be a content crash");
@ -75,7 +75,7 @@ SpecialPowers.pushPrefEnv({'set':[
else { else {
setTimeout(tryGetCrash, 1000); setTimeout(tryGetCrash, 1000);
} }
}, function (err) { }), function (err) {
ok(false, "Error getting crashes: " + err); ok(false, "Error getting crashes: " + err);
SimpleTest.finish(); SimpleTest.finish();
}); });

View File

@ -3,7 +3,15 @@
const {Cc: Cc, Ci: Ci, Cr: Cr, Cu: Cu} = SpecialPowers; const {Cc: Cc, Ci: Ci, Cr: Cr, Cu: Cu} = SpecialPowers;
let Promise = Cu.import("resource://gre/modules/Promise.jsm").Promise; // Emulate Promise.jsm semantics.
Promise.defer = function() { return new Deferred(); }
function Deferred() {
this.promise = new Promise(function(resolve, reject) {
this.resolve = resolve;
this.reject = reject;
}.bind(this));
Object.freeze(this);
}
/** /**
* Push a list of preference settings. Never reject. * Push a list of preference settings. Never reject.

View File

@ -168,11 +168,9 @@ function expandPermissions(aPerms) {
var perms = []; var perms = [];
aPerms.forEach(function(el) { aPerms.forEach(function(el) {
var access = permTable[el].access ? "readwrite" : null; var access = permTable[el].access ? "readwrite" : null;
var expanded = SpecialPowers.unwrap(expand(el, access)); var expanded = expand(el, access);
// COW arrays don't behave array-like enough, to allow
// using expanded.slice(0) here.
for (let i = 0; i < expanded.length; i++) { for (let i = 0; i < expanded.length; i++) {
perms.push(expanded[i]); perms.push(SpecialPowers.unwrap(expanded[i]));
} }
}); });

View File

@ -69,7 +69,7 @@ function crashAndGetCrashServiceRecord(crashMethodName, callback) {
// the new record. // the new record.
function tryGetCrash() { function tryGetCrash() {
info("Waiting for getCrashes"); info("Waiting for getCrashes");
crashMan.getCrashes().then(function (crashes) { crashMan.getCrashes().then(SpecialPowers.wrapCallback(function (crashes) {
if (crashes.length) { if (crashes.length) {
is(crashes.length, 1, "There should be only one record"); is(crashes.length, 1, "There should be only one record");
var crash = SpecialPowers.wrap(crashes[0]); var crash = SpecialPowers.wrap(crashes[0]);
@ -86,7 +86,7 @@ function crashAndGetCrashServiceRecord(crashMethodName, callback) {
else { else {
setTimeout(tryGetCrash, 1000); setTimeout(tryGetCrash, 1000);
} }
}, function (err) { }), function (err) {
ok(false, "Error getting crashes: " + err); ok(false, "Error getting crashes: " + err);
SimpleTest.finish(); SimpleTest.finish();
}); });

View File

@ -799,7 +799,8 @@ RILContentHelper.prototype = {
let window = this._windowsMap[message.requestId]; let window = this._windowsMap[message.requestId];
delete this._windowsMap[message.requestId]; delete this._windowsMap[message.requestId];
let contacts = message.contacts; let contacts = message.contacts;
let result = contacts.map(function(c) { let result = new window.Array();
contacts.forEach(function(c) {
let prop = {name: [c.alphaId], tel: [{value: c.number}]}; let prop = {name: [c.alphaId], tel: [{value: c.number}]};
if (c.email) { if (c.email) {
@ -814,7 +815,7 @@ RILContentHelper.prototype = {
let contact = new window.mozContact(prop); let contact = new window.mozContact(prop);
contact.id = c.contactId; contact.id = c.contactId;
return contact; result.push(contact);
}); });
this.fireRequestSuccess(message.requestId, result); this.fireRequestSuccess(message.requestId, result);

View File

@ -1,7 +1,16 @@
/* Any copyright is dedicated to the Public Domain. /* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */ * http://creativecommons.org/publicdomain/zero/1.0/ */
let Promise = SpecialPowers.Cu.import("resource://gre/modules/Promise.jsm").Promise; // Emulate Promise.jsm semantics.
Promise.defer = function() { return new Deferred(); }
function Deferred() {
this.promise = new Promise(function(resolve, reject) {
this.resolve = resolve;
this.reject = reject;
}.bind(this));
Object.freeze(this);
}
let telephony; let telephony;
let conference; let conference;

View File

@ -25,8 +25,15 @@ const TETHERING_SETTING_KEY = "1234567890";
const SETTINGS_RIL_DATA_ENABLED = 'ril.data.enabled'; const SETTINGS_RIL_DATA_ENABLED = 'ril.data.enabled';
let Promise = // Emulate Promise.jsm semantics.
SpecialPowers.Cu.import("resource://gre/modules/Promise.jsm").Promise; Promise.defer = function() { return new Deferred(); }
function Deferred() {
this.promise = new Promise(function(resolve, reject) {
this.resolve = resolve;
this.reject = reject;
}.bind(this));
Object.freeze(this);
}
let gTestSuite = (function() { let gTestSuite = (function() {
let suite = {}; let suite = {};

View File

@ -5,10 +5,18 @@
const {Cc: Cc, Ci: Ci, Cr: Cr, Cu: Cu} = SpecialPowers; const {Cc: Cc, Ci: Ci, Cr: Cr, Cu: Cu} = SpecialPowers;
let RIL = {}; let RIL = SpecialPowers.wrap(SpecialPowers.createBlankObject());
Cu.import("resource://gre/modules/ril_consts.js", RIL); SpecialPowers.Cu.import("resource://gre/modules/ril_consts.js", RIL);
let Promise = Cu.import("resource://gre/modules/Promise.jsm").Promise; // Emulate Promise.jsm semantics.
Promise.defer = function() { return new Deferred(); }
function Deferred() {
this.promise = new Promise(function(resolve, reject) {
this.resolve = resolve;
this.reject = reject;
}.bind(this));
Object.freeze(this);
}
const MWI_PDU_PREFIX = "0000"; const MWI_PDU_PREFIX = "0000";
const MWI_PDU_UDH_PREFIX = "0040"; const MWI_PDU_UDH_PREFIX = "0040";

View File

@ -160,7 +160,7 @@ DOMWifiManager.prototype = {
}, },
_convertWifiNetworks: function(aNetworks) { _convertWifiNetworks: function(aNetworks) {
let networks = []; let networks = new this._window.Array();
for (let i in aNetworks) { for (let i in aNetworks) {
networks.push(this._convertWifiNetwork(aNetworks[i])); networks.push(this._convertWifiNetwork(aNetworks[i]));
} }

View File

@ -1,7 +1,15 @@
/* Any copyright is dedicated to the Public Domain. /* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */ * http://creativecommons.org/publicdomain/zero/1.0/ */
let Promise = SpecialPowers.Cu.import('resource://gre/modules/Promise.jsm').Promise; // Emulate Promise.jsm semantics.
Promise.defer = function() { return new Deferred(); }
function Deferred() {
this.promise = new Promise(function(resolve, reject) {
this.resolve = resolve;
this.reject = reject;
}.bind(this));
Object.freeze(this);
}
const STOCK_HOSTAPD_NAME = 'goldfish-hostapd'; const STOCK_HOSTAPD_NAME = 'goldfish-hostapd';
const HOSTAPD_CONFIG_PATH = '/data/misc/wifi/remote-hostapd/'; const HOSTAPD_CONFIG_PATH = '/data/misc/wifi/remote-hostapd/';

View File

@ -47,7 +47,6 @@ function runTests()
} }
synthesizeComposition({ type: "compositionstart" }); synthesizeComposition({ type: "compositionstart" });
synthesizeComposition({ type: "compositionupdate", data: aInsertString });
synthesizeText( synthesizeText(
{ "composition": { "composition":
{ "string": aInsertString, { "string": aInsertString,

View File

@ -53,7 +53,6 @@ function runTests()
// input first character // input first character
composingString = "\u306B"; composingString = "\u306B";
synthesizeComposition({ type: "compositionupdate", data: composingString });
synthesizeText( synthesizeText(
{ "composition": { "composition":
{ "string": composingString, { "string": composingString,
@ -67,7 +66,6 @@ function runTests()
// input second character // input second character
composingString = "\u306B\u3085"; composingString = "\u306B\u3085";
synthesizeComposition({ type: "compositionupdate", data: composingString });
synthesizeText( synthesizeText(
{ "composition": { "composition":
{ "string": composingString, { "string": composingString,

View File

@ -122,7 +122,6 @@ function doCompositionTest(aElement, aElementDescription, aCallback)
"\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u3088\u308a" + "\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u3088\u308a" +
"\u77ed\u6642\u9593\u3067\u7c21\u5358\u306b\u4f5c\u6210\u3067" + "\u77ed\u6642\u9593\u3067\u7c21\u5358\u306b\u4f5c\u6210\u3067" +
"\u304d\u307e\u3059\u3002"; "\u304d\u307e\u3059\u3002";
synthesizeComposition({ type: "compositionupdate", data: str });
synthesizeText({ synthesizeText({
composition: { composition: {
string: str, string: str,
@ -135,7 +134,6 @@ function doCompositionTest(aElement, aElementDescription, aCallback)
hitEventLoop(function () { hitEventLoop(function () {
isnot(aElement.scrollTop, 0, isnot(aElement.scrollTop, 0,
aElementDescription + " was not scrolled by composition"); aElementDescription + " was not scrolled by composition");
synthesizeComposition({ type: "compositionupdate", data: "" });
synthesizeText({ synthesizeText({
composition: { string: "", clauses: [ { length: 0, attr: 0 } ] }, composition: { string: "", clauses: [ { length: 0, attr: 0 } ] },
caret: { start: 0, length: 0 } caret: { start: 0, length: 0 }

View File

@ -222,7 +222,6 @@ function runTests()
// start composition // start composition
synthesizeComposition({ type: "compositionstart" }); synthesizeComposition({ type: "compositionstart" });
// input first character // input first character
synthesizeComposition({ type: "compositionupdate", data: "\u3089" });
synthesizeText( synthesizeText(
{ "composition": { "composition":
{ "string": "\u3089", { "string": "\u3089",

View File

@ -2367,7 +2367,9 @@ DrawTargetD2D::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
RefPtr<SourceSurface> source = pat->mSurface; RefPtr<SourceSurface> source = pat->mSurface;
if (!pat->mSamplingRect.IsEmpty()) { if (!pat->mSamplingRect.IsEmpty() &&
(source->GetType() == SurfaceType::D2D1_BITMAP ||
source->GetType() == SurfaceType::D2D1_DRAWTARGET)) {
IntRect samplingRect = pat->mSamplingRect; IntRect samplingRect = pat->mSamplingRect;
RefPtr<DrawTargetD2D> dt = new DrawTargetD2D(); RefPtr<DrawTargetD2D> dt = new DrawTargetD2D();
@ -2411,7 +2413,12 @@ DrawTargetD2D::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
return nullptr; return nullptr;
} }
bitmap = CreatePartialBitmapForSurface(dataSurf, mTransform, mSize, pat->mExtendMode, mat, mRT); IntRect sourceRect = pat->mSamplingRect;
if (sourceRect.IsEmpty()) {
sourceRect = IntRect(0, 0, source->GetSize().width, source->GetSize().height);
}
bitmap = CreatePartialBitmapForSurface(dataSurf, mTransform, mSize, pat->mExtendMode, mat, mRT, &sourceRect);
if (!bitmap) { if (!bitmap) {
return nullptr; return nullptr;
} }

View File

@ -513,7 +513,8 @@ CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions)
static TemporaryRef<ID2D1Bitmap> static TemporaryRef<ID2D1Bitmap>
CreatePartialBitmapForSurface(DataSourceSurface *aSurface, const Matrix &aDestinationTransform, CreatePartialBitmapForSurface(DataSourceSurface *aSurface, const Matrix &aDestinationTransform,
const IntSize &aDestinationSize, ExtendMode aExtendMode, const IntSize &aDestinationSize, ExtendMode aExtendMode,
Matrix &aSourceTransform, ID2D1RenderTarget *aRT) Matrix &aSourceTransform, ID2D1RenderTarget *aRT,
const IntRect* aSourceRect = nullptr)
{ {
RefPtr<ID2D1Bitmap> bitmap; RefPtr<ID2D1Bitmap> bitmap;
@ -538,6 +539,9 @@ CreatePartialBitmapForSurface(DataSourceSurface *aSurface, const Matrix &aDestin
IntSize size = aSurface->GetSize(); IntSize size = aSurface->GetSize();
Rect uploadRect(0, 0, Float(size.width), Float(size.height)); Rect uploadRect(0, 0, Float(size.width), Float(size.height));
if (aSourceRect) {
uploadRect = Rect(aSourceRect->x, aSourceRect->y, aSourceRect->width, aSourceRect->height);
}
// Limit the uploadRect as much as possible without supporting discontiguous uploads // Limit the uploadRect as much as possible without supporting discontiguous uploads
// //

View File

@ -92,6 +92,8 @@ CompositingRenderTargetOGL::InitializeImpl()
NS_ERROR(msg.get()); NS_ERROR(msg.get());
} }
mInitParams.mStatus = InitParams::INITIALIZED;
mCompositor->PrepareViewport(mInitParams.mSize); mCompositor->PrepareViewport(mInitParams.mSize);
mGL->fScissor(0, 0, mInitParams.mSize.width, mInitParams.mSize.height); mGL->fScissor(0, 0, mInitParams.mSize.width, mInitParams.mSize.height);
if (mInitParams.mInit == INIT_MODE_CLEAR) { if (mInitParams.mInit == INIT_MODE_CLEAR) {
@ -99,7 +101,6 @@ CompositingRenderTargetOGL::InitializeImpl()
mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT); mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
} }
mInitParams.mStatus = InitParams::INITIALIZED;
} }
} }

View File

@ -84,7 +84,7 @@ public:
const gfx::IntSize& aSize) const gfx::IntSize& aSize)
{ {
RefPtr<CompositingRenderTargetOGL> result RefPtr<CompositingRenderTargetOGL> result
= new CompositingRenderTargetOGL(aCompositor, gfx::IntPoint(0, 0), 0, 0); = new CompositingRenderTargetOGL(aCompositor, gfx::IntPoint(), 0, 0);
result->mInitParams = InitParams(aSize, 0, INIT_MODE_NONE); result->mInitParams = InitParams(aSize, 0, INIT_MODE_NONE);
result->mInitParams.mStatus = InitParams::INITIALIZED; result->mInitParams.mStatus = InitParams::INITIALIZED;
return result.forget(); return result.forget();
@ -112,6 +112,8 @@ public:
*/ */
void BindRenderTarget(); void BindRenderTarget();
bool IsWindow() { return GetFBO() == 0; }
GLuint GetFBO() const GLuint GetFBO() const
{ {
MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED); MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);

View File

@ -593,7 +593,10 @@ CompositorOGL::PrepareViewport(const gfx::IntSize& aSize)
viewMatrix.PreScale(1.0f, -1.0f); viewMatrix.PreScale(1.0f, -1.0f);
} }
if (!mTarget) { MOZ_ASSERT(mCurrentRenderTarget, "No destination");
// If we're drawing directly to the window then we want to offset
// drawing by the render offset.
if (!mTarget && mCurrentRenderTarget->IsWindow()) {
viewMatrix.PreTranslate(mRenderOffset.x, mRenderOffset.y); viewMatrix.PreTranslate(mRenderOffset.x, mRenderOffset.y);
} }
@ -660,8 +663,8 @@ CompositorOGL::SetRenderTarget(CompositingRenderTarget *aSurface)
CompositingRenderTargetOGL* surface CompositingRenderTargetOGL* surface
= static_cast<CompositingRenderTargetOGL*>(aSurface); = static_cast<CompositingRenderTargetOGL*>(aSurface);
if (mCurrentRenderTarget != surface) { if (mCurrentRenderTarget != surface) {
surface->BindRenderTarget();
mCurrentRenderTarget = surface; mCurrentRenderTarget = surface;
surface->BindRenderTarget();
} }
} }
@ -1019,9 +1022,14 @@ CompositorOGL::DrawQuad(const Rect& aRect,
js::ProfileEntry::Category::GRAPHICS); js::ProfileEntry::Category::GRAPHICS);
MOZ_ASSERT(mFrameInProgress, "frame not started"); MOZ_ASSERT(mFrameInProgress, "frame not started");
MOZ_ASSERT(mCurrentRenderTarget, "No destination");
Rect clipRect = aClipRect; Rect clipRect = aClipRect;
if (!mTarget) { // aClipRect is in destination coordinate space (after all
// transforms and offsets have been applied) so if our
// drawing is going to be shifted by mRenderOffset then we need
// to shift the clip rect by the same amount.
if (!mTarget && mCurrentRenderTarget->IsWindow()) {
clipRect.MoveBy(mRenderOffset.x, mRenderOffset.y); clipRect.MoveBy(mRenderOffset.x, mRenderOffset.y);
} }
IntRect intClipRect; IntRect intClipRect;

View File

@ -856,20 +856,7 @@ gfxContext::SetColor(const gfxRGBA& c)
CurrentState().pattern = nullptr; CurrentState().pattern = nullptr;
CurrentState().sourceSurfCairo = nullptr; CurrentState().sourceSurfCairo = nullptr;
CurrentState().sourceSurface = nullptr; CurrentState().sourceSurface = nullptr;
CurrentState().color = gfxPlatform::MaybeTransformColor(c);
if (gfxPlatform::GetCMSMode() == eCMSMode_All) {
gfxRGBA cms;
qcms_transform *transform = gfxPlatform::GetCMSRGBTransform();
if (transform)
gfxPlatform::TransformPixel(c, cms, transform);
// Use the original alpha to avoid unnecessary float->byte->float
// conversion errors
CurrentState().color = ToColor(cms);
}
else
CurrentState().color = ToColor(c);
} }
void void

View File

@ -1631,6 +1631,26 @@ gfxPlatform::TransformPixel(const gfxRGBA& in, gfxRGBA& out, qcms_transform *tra
out = in; out = in;
} }
Color
gfxPlatform::MaybeTransformColor(const gfxRGBA& aColor)
{
// We only return this object to get some return value optimization goodness:
Color color;
if (GetCMSMode() == eCMSMode_All) {
gfxRGBA cms;
qcms_transform *transform = GetCMSRGBTransform();
if (transform) {
TransformPixel(aColor, cms, transform);
// Use the original alpha to avoid unnecessary float->byte->float
// conversion errors
color = ToColor(cms);
return color;
}
}
color = ToColor(aColor);
return color;
}
void void
gfxPlatform::GetPlatformCMSOutputProfile(void *&mem, size_t &size) gfxPlatform::GetPlatformCMSOutputProfile(void *&mem, size_t &size)
{ {

View File

@ -7,6 +7,7 @@
#define GFX_PLATFORM_H #define GFX_PLATFORM_H
#include "prlog.h" #include "prlog.h"
#include "mozilla/gfx/Types.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsString.h" #include "nsString.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
@ -158,6 +159,7 @@ GetBackendName(mozilla::gfx::BackendType aBackend)
class gfxPlatform { class gfxPlatform {
public: public:
typedef mozilla::gfx::Color Color;
typedef mozilla::gfx::DataSourceSurface DataSourceSurface; typedef mozilla::gfx::DataSourceSurface DataSourceSurface;
typedef mozilla::gfx::DrawTarget DrawTarget; typedef mozilla::gfx::DrawTarget DrawTarget;
typedef mozilla::gfx::IntSize IntSize; typedef mozilla::gfx::IntSize IntSize;
@ -493,6 +495,12 @@ public:
*/ */
static void TransformPixel(const gfxRGBA& in, gfxRGBA& out, qcms_transform *transform); static void TransformPixel(const gfxRGBA& in, gfxRGBA& out, qcms_transform *transform);
/**
* Converts the color using the GetCMSRGBTransform() transform if the
* CMS mode is eCMSMode_All, else just returns the color.
*/
static Color MaybeTransformColor(const gfxRGBA& aColor);
/** /**
* Return the output device ICC profile. * Return the output device ICC profile.
*/ */

View File

@ -593,17 +593,6 @@ gfxUtils::DrawPixelSnapped(gfxContext* aContext,
imageRect.Width(), imageRect.Height(), imageRect.Width(), imageRect.Height(),
region.Width(), region.Height()); region.Width(), region.Height());
if (aRegion.IsRestricted() &&
aContext->CurrentMatrix().HasNonIntegerTranslation() &&
drawable->DrawWithSamplingRect(aContext, aRegion.Rect(), aRegion.Restriction(),
doTile, aFilter, aOpacity)) {
return;
}
// On Mobile, we don't ever want to do this; it has the potential for
// allocating very large temporary surfaces, especially since we'll
// do full-page snapshots often (see bug 749426).
#ifndef MOZ_GFX_OPTIMIZE_MOBILE
// OK now, the hard part left is to account for the subimage sampling // OK now, the hard part left is to account for the subimage sampling
// restriction. If all the transforms involved are just integer // restriction. If all the transforms involved are just integer
// translations, then we assume no resampling will occur so there's // translations, then we assume no resampling will occur so there's
@ -611,19 +600,29 @@ gfxUtils::DrawPixelSnapped(gfxContext* aContext,
// XXX if only we had source-clipping in cairo! // XXX if only we had source-clipping in cairo!
if (aContext->CurrentMatrix().HasNonIntegerTranslation()) { if (aContext->CurrentMatrix().HasNonIntegerTranslation()) {
if (doTile || !aRegion.RestrictionContains(imageRect)) { if (doTile || !aRegion.RestrictionContains(imageRect)) {
if (drawable->DrawWithSamplingRect(aContext, aRegion.Rect(), aRegion.Restriction(),
doTile, aFilter, aOpacity)) {
return;
}
// On Mobile, we don't ever want to do this; it has the potential for
// allocating very large temporary surfaces, especially since we'll
// do full-page snapshots often (see bug 749426).
#ifndef MOZ_GFX_OPTIMIZE_MOBILE
nsRefPtr<gfxDrawable> restrictedDrawable = nsRefPtr<gfxDrawable> restrictedDrawable =
CreateSamplingRestrictedDrawable(aDrawable, aContext, CreateSamplingRestrictedDrawable(aDrawable, aContext,
aRegion, aFormat); aRegion, aFormat);
if (restrictedDrawable) { if (restrictedDrawable) {
drawable.swap(restrictedDrawable); drawable.swap(restrictedDrawable);
} }
}
// We no longer need to tile: Either we never needed to, or we already // We no longer need to tile: Either we never needed to, or we already
// filled a surface with the tiled pattern; this surface can now be // filled a surface with the tiled pattern; this surface can now be
// drawn without tiling. // drawn without tiling.
doTile = false; doTile = false;
}
#endif #endif
}
}
drawable->Draw(aContext, aRegion.Rect(), doTile, aFilter, aOpacity); drawable->Draw(aContext, aRegion.Rect(), doTile, aFilter, aOpacity);
} }

View File

@ -90,6 +90,11 @@ ScopedXREEmbed::Start()
localFile = do_QueryInterface(parent); localFile = do_QueryInterface(parent);
NS_ENSURE_TRUE_VOID(localFile); NS_ENSURE_TRUE_VOID(localFile);
rv = localFile->SetNativeLeafName(NS_LITERAL_CSTRING("Resources"));
if (NS_FAILED(rv)) {
return;
}
} }
#endif #endif

View File

@ -885,6 +885,24 @@ class RootedBase<JSObject*>
JS::Handle<U*> as() const; JS::Handle<U*> as() const;
}; };
/*
* Augment the generic Handle<T> interface when T = JSObject* with
* downcasting operations.
*
* Given a Handle<JSObject*> obj, one can view
* Handle<StringObject*> h = obj.as<StringObject*>();
* as an optimization of
* Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
* Handle<StringObject*> h = rooted;
*/
template <>
class HandleBase<JSObject*>
{
public:
template <class U>
JS::Handle<U*> as() const;
};
/* Interface substitute for Rooted<T> which does not root the variable's memory. */ /* Interface substitute for Rooted<T> which does not root the variable's memory. */
template <typename T> template <typename T>
class FakeRooted : public RootedBase<T> class FakeRooted : public RootedBase<T>
@ -1003,6 +1021,11 @@ template <typename T> class MaybeRooted<T, CanGC>
static inline JS::MutableHandle<T> toMutableHandle(MutableHandleType v) { static inline JS::MutableHandle<T> toMutableHandle(MutableHandleType v) {
return v; return v;
} }
template <typename T2>
static inline JS::Handle<T2*> downcastHandle(HandleType v) {
return v.template as<T2>();
}
}; };
template <typename T> class MaybeRooted<T, NoGC> template <typename T> class MaybeRooted<T, NoGC>
@ -1019,6 +1042,11 @@ template <typename T> class MaybeRooted<T, NoGC>
static JS::MutableHandle<T> toMutableHandle(MutableHandleType v) { static JS::MutableHandle<T> toMutableHandle(MutableHandleType v) {
MOZ_CRASH("Bad conversion"); MOZ_CRASH("Bad conversion");
} }
template <typename T2>
static inline T2* downcastHandle(HandleType v) {
return &v->template as<T2>();
}
}; };
} /* namespace js */ } /* namespace js */

View File

@ -44,6 +44,7 @@
#include "jsobjinlines.h" #include "jsobjinlines.h"
#include "vm/ArrayBufferObject-inl.h" #include "vm/ArrayBufferObject-inl.h"
#include "vm/ObjectImpl-inl.h"
using namespace js; using namespace js;
using namespace js::jit; using namespace js::jit;
@ -117,7 +118,7 @@ HasPureCoercion(JSContext *cx, HandleValue v)
jsid toString = NameToId(cx->names().toString); jsid toString = NameToId(cx->names().toString);
if (v.toObject().is<JSFunction>() && if (v.toObject().is<JSFunction>() &&
HasObjectValueOf(&v.toObject(), cx) && HasObjectValueOf(&v.toObject(), cx) &&
ClassMethodIsNative(cx, &v.toObject(), &JSFunction::class_, toString, fun_toString)) ClassMethodIsNative(cx, &v.toObject().as<JSFunction>(), &JSFunction::class_, toString, fun_toString))
{ {
return true; return true;
} }
@ -897,7 +898,7 @@ CreateExportObject(JSContext *cx, Handle<AsmJSModuleObject*> moduleObj)
} }
gc::AllocKind allocKind = gc::GetGCObjectKind(module.numExportedFunctions()); gc::AllocKind allocKind = gc::GetGCObjectKind(module.numExportedFunctions());
RootedObject obj(cx, NewBuiltinClassInstance(cx, &JSObject::class_, allocKind)); RootedNativeObject obj(cx, NewNativeBuiltinClassInstance(cx, &JSObject::class_, allocKind));
if (!obj) if (!obj)
return nullptr; return nullptr;

View File

@ -868,9 +868,10 @@ AsmJSModuleObject::create(ExclusiveContext *cx, ScopedJSDeletePtr<AsmJSModule> *
JSObject *obj = NewObjectWithGivenProto(cx, &AsmJSModuleObject::class_, nullptr, nullptr); JSObject *obj = NewObjectWithGivenProto(cx, &AsmJSModuleObject::class_, nullptr, nullptr);
if (!obj) if (!obj)
return nullptr; return nullptr;
AsmJSModuleObject *nobj = &obj->as<AsmJSModuleObject>();
obj->setReservedSlot(MODULE_SLOT, PrivateValue(module->forget())); nobj->setReservedSlot(MODULE_SLOT, PrivateValue(module->forget()));
return &obj->as<AsmJSModuleObject>(); return nobj;
} }
AsmJSModule & AsmJSModule &

View File

@ -1437,7 +1437,7 @@ LookupAsmJSModuleInCache(ExclusiveContext *cx,
// directly to user script) which manages the lifetime of an AsmJSModule. A // directly to user script) which manages the lifetime of an AsmJSModule. A
// JSObject is necessary since we want LinkAsmJS/CallAsmJS JSFunctions to be // JSObject is necessary since we want LinkAsmJS/CallAsmJS JSFunctions to be
// able to point to their module via their extended slots. // able to point to their module via their extended slots.
class AsmJSModuleObject : public JSObject class AsmJSModuleObject : public NativeObject
{ {
static const unsigned MODULE_SLOT = 0; static const unsigned MODULE_SLOT = 0;

View File

@ -581,54 +581,6 @@ function ArrayFill(value, start = 0, end = undefined) {
return O; return O;
} }
// Proposed for ES7:
// https://github.com/domenic/Array.prototype.contains/blob/master/spec.md
function ArrayContains(searchElement, fromIndex = 0) {
// Steps 1-2.
var O = ToObject(this);
// Steps 3-4.
var len = ToLength(O.length);
// Step 5.
if (len === 0)
return false;
// Steps 6-7.
var n = ToInteger(fromIndex);
// Step 8.
if (n >= len)
return false;
// Step 9.
var k;
if (n >= 0) {
k = n;
}
// Step 10.
else {
// Step a.
k = len + n;
// Step b.
if (k < 0)
k = 0;
}
// Step 11.
while (k < len) {
// Steps a-c.
if (SameValueZero(searchElement, O[k]))
return true;
// Step d.
k++;
}
// Step 12.
return false;
}
#define ARRAY_ITERATOR_SLOT_ITERATED_OBJECT 0 #define ARRAY_ITERATOR_SLOT_ITERATED_OBJECT 0
#define ARRAY_ITERATOR_SLOT_NEXT_INDEX 1 #define ARRAY_ITERATOR_SLOT_NEXT_INDEX 1
#define ARRAY_ITERATOR_SLOT_ITEM_KIND 2 #define ARRAY_ITERATOR_SLOT_ITEM_KIND 2

View File

@ -633,7 +633,7 @@ Collator(JSContext *cx, CallArgs args, bool construct)
if (!obj) if (!obj)
return false; return false;
obj->setReservedSlot(UCOLLATOR_SLOT, PrivateValue(nullptr)); obj->as<NativeObject>().setReservedSlot(UCOLLATOR_SLOT, PrivateValue(nullptr));
} }
// 10.1.2.1 steps 1 and 2; 10.1.3.1 steps 1 and 2 // 10.1.2.1 steps 1 and 2; 10.1.3.1 steps 1 and 2
@ -669,7 +669,7 @@ js::intl_Collator(JSContext *cx, unsigned argc, Value *vp)
static void static void
collator_finalize(FreeOp *fop, JSObject *obj) collator_finalize(FreeOp *fop, JSObject *obj)
{ {
UCollator *coll = static_cast<UCollator*>(obj->getReservedSlot(UCOLLATOR_SLOT).toPrivate()); UCollator *coll = static_cast<UCollator*>(obj->as<NativeObject>().getReservedSlot(UCOLLATOR_SLOT).toPrivate());
if (coll) if (coll)
ucol_close(coll); ucol_close(coll);
} }
@ -732,7 +732,7 @@ InitCollatorClass(JSContext *cx, HandleObject Intl, Handle<GlobalObject*> global
bool bool
GlobalObject::initCollatorProto(JSContext *cx, Handle<GlobalObject*> global) GlobalObject::initCollatorProto(JSContext *cx, Handle<GlobalObject*> global)
{ {
RootedObject proto(cx, global->createBlankPrototype(cx, &CollatorClass)); RootedNativeObject proto(cx, global->createBlankPrototype(cx, &CollatorClass));
if (!proto) if (!proto)
return false; return false;
proto->setReservedSlot(UCOLLATOR_SLOT, PrivateValue(nullptr)); proto->setReservedSlot(UCOLLATOR_SLOT, PrivateValue(nullptr));
@ -1006,12 +1006,12 @@ js::intl_CompareStrings(JSContext *cx, unsigned argc, Value *vp)
bool isCollatorInstance = collator->getClass() == &CollatorClass; bool isCollatorInstance = collator->getClass() == &CollatorClass;
UCollator *coll; UCollator *coll;
if (isCollatorInstance) { if (isCollatorInstance) {
coll = static_cast<UCollator *>(collator->getReservedSlot(UCOLLATOR_SLOT).toPrivate()); coll = static_cast<UCollator *>(collator->as<NativeObject>().getReservedSlot(UCOLLATOR_SLOT).toPrivate());
if (!coll) { if (!coll) {
coll = NewUCollator(cx, collator); coll = NewUCollator(cx, collator);
if (!coll) if (!coll)
return false; return false;
collator->setReservedSlot(UCOLLATOR_SLOT, PrivateValue(coll)); collator->as<NativeObject>().setReservedSlot(UCOLLATOR_SLOT, PrivateValue(coll));
} }
} else { } else {
// There's no good place to cache the ICU collator for an object // There's no good place to cache the ICU collator for an object
@ -1122,7 +1122,7 @@ NumberFormat(JSContext *cx, CallArgs args, bool construct)
if (!obj) if (!obj)
return false; return false;
obj->setReservedSlot(UNUMBER_FORMAT_SLOT, PrivateValue(nullptr)); obj->as<NativeObject>().setReservedSlot(UNUMBER_FORMAT_SLOT, PrivateValue(nullptr));
} }
// 11.1.2.1 steps 1 and 2; 11.1.3.1 steps 1 and 2 // 11.1.2.1 steps 1 and 2; 11.1.3.1 steps 1 and 2
@ -1160,7 +1160,7 @@ static void
numberFormat_finalize(FreeOp *fop, JSObject *obj) numberFormat_finalize(FreeOp *fop, JSObject *obj)
{ {
UNumberFormat *nf = UNumberFormat *nf =
static_cast<UNumberFormat*>(obj->getReservedSlot(UNUMBER_FORMAT_SLOT).toPrivate()); static_cast<UNumberFormat*>(obj->as<NativeObject>().getReservedSlot(UNUMBER_FORMAT_SLOT).toPrivate());
if (nf) if (nf)
unum_close(nf); unum_close(nf);
} }
@ -1223,7 +1223,7 @@ InitNumberFormatClass(JSContext *cx, HandleObject Intl, Handle<GlobalObject*> gl
bool bool
GlobalObject::initNumberFormatProto(JSContext *cx, Handle<GlobalObject*> global) GlobalObject::initNumberFormatProto(JSContext *cx, Handle<GlobalObject*> global)
{ {
RootedObject proto(cx, global->createBlankPrototype(cx, &NumberFormatClass)); RootedNativeObject proto(cx, global->createBlankPrototype(cx, &NumberFormatClass));
if (!proto) if (!proto)
return false; return false;
proto->setReservedSlot(UNUMBER_FORMAT_SLOT, PrivateValue(nullptr)); proto->setReservedSlot(UNUMBER_FORMAT_SLOT, PrivateValue(nullptr));
@ -1465,12 +1465,12 @@ js::intl_FormatNumber(JSContext *cx, unsigned argc, Value *vp)
bool isNumberFormatInstance = numberFormat->getClass() == &NumberFormatClass; bool isNumberFormatInstance = numberFormat->getClass() == &NumberFormatClass;
UNumberFormat *nf; UNumberFormat *nf;
if (isNumberFormatInstance) { if (isNumberFormatInstance) {
nf = static_cast<UNumberFormat*>(numberFormat->getReservedSlot(UNUMBER_FORMAT_SLOT).toPrivate()); nf = static_cast<UNumberFormat*>(numberFormat->as<NativeObject>().getReservedSlot(UNUMBER_FORMAT_SLOT).toPrivate());
if (!nf) { if (!nf) {
nf = NewUNumberFormat(cx, numberFormat); nf = NewUNumberFormat(cx, numberFormat);
if (!nf) if (!nf)
return false; return false;
numberFormat->setReservedSlot(UNUMBER_FORMAT_SLOT, PrivateValue(nf)); numberFormat->as<NativeObject>().setReservedSlot(UNUMBER_FORMAT_SLOT, PrivateValue(nf));
} }
} else { } else {
// There's no good place to cache the ICU number format for an object // There's no good place to cache the ICU number format for an object
@ -1579,7 +1579,7 @@ DateTimeFormat(JSContext *cx, CallArgs args, bool construct)
if (!obj) if (!obj)
return false; return false;
obj->setReservedSlot(UDATE_FORMAT_SLOT, PrivateValue(nullptr)); obj->as<NativeObject>().setReservedSlot(UDATE_FORMAT_SLOT, PrivateValue(nullptr));
} }
// 12.1.2.1 steps 1 and 2; 12.1.3.1 steps 1 and 2 // 12.1.2.1 steps 1 and 2; 12.1.3.1 steps 1 and 2
@ -1616,7 +1616,7 @@ js::intl_DateTimeFormat(JSContext *cx, unsigned argc, Value *vp)
static void static void
dateTimeFormat_finalize(FreeOp *fop, JSObject *obj) dateTimeFormat_finalize(FreeOp *fop, JSObject *obj)
{ {
UDateFormat *df = static_cast<UDateFormat*>(obj->getReservedSlot(UDATE_FORMAT_SLOT).toPrivate()); UDateFormat *df = static_cast<UDateFormat*>(obj->as<NativeObject>().getReservedSlot(UDATE_FORMAT_SLOT).toPrivate());
if (df) if (df)
udat_close(df); udat_close(df);
} }
@ -1679,7 +1679,7 @@ InitDateTimeFormatClass(JSContext *cx, HandleObject Intl, Handle<GlobalObject*>
bool bool
GlobalObject::initDateTimeFormatProto(JSContext *cx, Handle<GlobalObject*> global) GlobalObject::initDateTimeFormatProto(JSContext *cx, Handle<GlobalObject*> global)
{ {
RootedObject proto(cx, global->createBlankPrototype(cx, &DateTimeFormatClass)); RootedNativeObject proto(cx, global->createBlankPrototype(cx, &DateTimeFormatClass));
if (!proto) if (!proto)
return false; return false;
proto->setReservedSlot(UDATE_FORMAT_SLOT, PrivateValue(nullptr)); proto->setReservedSlot(UDATE_FORMAT_SLOT, PrivateValue(nullptr));
@ -1966,12 +1966,12 @@ js::intl_FormatDateTime(JSContext *cx, unsigned argc, Value *vp)
bool isDateTimeFormatInstance = dateTimeFormat->getClass() == &DateTimeFormatClass; bool isDateTimeFormatInstance = dateTimeFormat->getClass() == &DateTimeFormatClass;
UDateFormat *df; UDateFormat *df;
if (isDateTimeFormatInstance) { if (isDateTimeFormatInstance) {
df = static_cast<UDateFormat*>(dateTimeFormat->getReservedSlot(UDATE_FORMAT_SLOT).toPrivate()); df = static_cast<UDateFormat*>(dateTimeFormat->as<NativeObject>().getReservedSlot(UDATE_FORMAT_SLOT).toPrivate());
if (!df) { if (!df) {
df = NewUDateFormat(cx, dateTimeFormat); df = NewUDateFormat(cx, dateTimeFormat);
if (!df) if (!df)
return false; return false;
dateTimeFormat->setReservedSlot(UDATE_FORMAT_SLOT, PrivateValue(df)); dateTimeFormat->as<NativeObject>().setReservedSlot(UDATE_FORMAT_SLOT, PrivateValue(df));
} }
} else { } else {
// There's no good place to cache the ICU date-time format for an object // There's no good place to cache the ICU date-time format for an object

View File

@ -19,6 +19,8 @@
#include "jsobjinlines.h" #include "jsobjinlines.h"
#include "vm/ObjectImpl-inl.h"
using namespace js; using namespace js;
using mozilla::ArrayLength; using mozilla::ArrayLength;
@ -840,7 +842,7 @@ HashableValue::mark(JSTracer *trc) const
namespace { namespace {
class MapIteratorObject : public JSObject class MapIteratorObject : public NativeObject
{ {
public: public:
static const Class class_; static const Class class_;
@ -901,8 +903,8 @@ GlobalObject::initMapIteratorProto(JSContext *cx, Handle<GlobalObject *> global)
JSObject *base = GlobalObject::getOrCreateIteratorPrototype(cx, global); JSObject *base = GlobalObject::getOrCreateIteratorPrototype(cx, global);
if (!base) if (!base)
return false; return false;
Rooted<JSObject*> proto(cx, RootedNativeObject proto(cx,
NewObjectWithGivenProto(cx, &MapIteratorObject::class_, base, global)); NewNativeObjectWithGivenProto(cx, &MapIteratorObject::class_, base, global));
if (!proto) if (!proto)
return false; return false;
proto->setSlot(MapIteratorObject::RangeSlot, PrivateValue(nullptr)); proto->setSlot(MapIteratorObject::RangeSlot, PrivateValue(nullptr));
@ -925,7 +927,7 @@ MapIteratorObject::create(JSContext *cx, HandleObject mapobj, ValueMap *data,
if (!range) if (!range)
return nullptr; return nullptr;
JSObject *iterobj = NewObjectWithGivenProto(cx, &class_, proto, global); NativeObject *iterobj = NewNativeObjectWithGivenProto(cx, &class_, proto, global);
if (!iterobj) { if (!iterobj) {
js_delete(range); js_delete(range);
return nullptr; return nullptr;
@ -1044,7 +1046,7 @@ static JSObject *
InitClass(JSContext *cx, Handle<GlobalObject*> global, const Class *clasp, JSProtoKey key, Native construct, InitClass(JSContext *cx, Handle<GlobalObject*> global, const Class *clasp, JSProtoKey key, Native construct,
const JSPropertySpec *properties, const JSFunctionSpec *methods) const JSPropertySpec *properties, const JSFunctionSpec *methods)
{ {
Rooted<JSObject*> proto(cx, global->createBlankPrototype(cx, clasp)); RootedNativeObject proto(cx, global->createBlankPrototype(cx, clasp));
if (!proto) if (!proto)
return nullptr; return nullptr;
proto->setPrivate(nullptr); proto->setPrivate(nullptr);
@ -1198,7 +1200,7 @@ MapObject::set(JSContext *cx, HandleObject obj, HandleValue k, HandleValue v)
MapObject* MapObject*
MapObject::create(JSContext *cx) MapObject::create(JSContext *cx)
{ {
RootedObject obj(cx, NewBuiltinClassInstance(cx, &class_)); RootedNativeObject obj(cx, NewNativeBuiltinClassInstance(cx, &class_));
if (!obj) if (!obj)
return nullptr; return nullptr;
@ -1278,7 +1280,7 @@ MapObject::construct(JSContext *cx, unsigned argc, Value *vp)
bool bool
MapObject::is(HandleValue v) MapObject::is(HandleValue v)
{ {
return v.isObject() && v.toObject().hasClass(&class_) && v.toObject().getPrivate(); return v.isObject() && v.toObject().hasClass(&class_) && v.toObject().as<MapObject>().getPrivate();
} }
#define ARG0_KEY(cx, args, key) \ #define ARG0_KEY(cx, args, key) \
@ -1489,7 +1491,7 @@ js_InitMapClass(JSContext *cx, HandleObject obj)
namespace { namespace {
class SetIteratorObject : public JSObject class SetIteratorObject : public NativeObject
{ {
public: public:
static const Class class_; static const Class class_;
@ -1550,7 +1552,8 @@ GlobalObject::initSetIteratorProto(JSContext *cx, Handle<GlobalObject*> global)
JSObject *base = GlobalObject::getOrCreateIteratorPrototype(cx, global); JSObject *base = GlobalObject::getOrCreateIteratorPrototype(cx, global);
if (!base) if (!base)
return false; return false;
RootedObject proto(cx, NewObjectWithGivenProto(cx, &SetIteratorObject::class_, base, global)); RootedNativeObject proto(cx, NewNativeObjectWithGivenProto(cx, &SetIteratorObject::class_,
base, global));
if (!proto) if (!proto)
return false; return false;
proto->setSlot(SetIteratorObject::RangeSlot, PrivateValue(nullptr)); proto->setSlot(SetIteratorObject::RangeSlot, PrivateValue(nullptr));
@ -1573,7 +1576,7 @@ SetIteratorObject::create(JSContext *cx, HandleObject setobj, ValueSet *data,
if (!range) if (!range)
return nullptr; return nullptr;
JSObject *iterobj = NewObjectWithGivenProto(cx, &class_, proto, global); NativeObject *iterobj = NewNativeObjectWithGivenProto(cx, &class_, proto, global);
if (!iterobj) { if (!iterobj) {
js_delete(range); js_delete(range);
return nullptr; return nullptr;
@ -1742,7 +1745,7 @@ SetObject::add(JSContext *cx, HandleObject obj, HandleValue k)
SetObject* SetObject*
SetObject::create(JSContext *cx) SetObject::create(JSContext *cx)
{ {
RootedObject obj(cx, NewBuiltinClassInstance(cx, &class_)); RootedNativeObject obj(cx, NewNativeBuiltinClassInstance(cx, &class_));
if (!obj) if (!obj)
return nullptr; return nullptr;
@ -1812,7 +1815,7 @@ SetObject::construct(JSContext *cx, unsigned argc, Value *vp)
bool bool
SetObject::is(HandleValue v) SetObject::is(HandleValue v)
{ {
return v.isObject() && v.toObject().hasClass(&class_) && v.toObject().getPrivate(); return v.isObject() && v.toObject().hasClass(&class_) && v.toObject().as<SetObject>().getPrivate();
} }
ValueSet & ValueSet &

View File

@ -85,7 +85,7 @@ typedef OrderedHashSet<HashableValue,
HashableValue::Hasher, HashableValue::Hasher,
RuntimeAllocPolicy> ValueSet; RuntimeAllocPolicy> ValueSet;
class MapObject : public JSObject { class MapObject : public NativeObject {
public: public:
enum IteratorKind { Keys, Values, Entries }; enum IteratorKind { Keys, Values, Entries };
@ -130,7 +130,7 @@ class MapObject : public JSObject {
static bool clear(JSContext *cx, unsigned argc, Value *vp); static bool clear(JSContext *cx, unsigned argc, Value *vp);
}; };
class SetObject : public JSObject { class SetObject : public NativeObject {
public: public:
enum IteratorKind { Values, Entries }; enum IteratorKind { Values, Entries };
static JSObject *initClass(JSContext *cx, JSObject *obj); static JSObject *initClass(JSContext *cx, JSObject *obj);

View File

@ -16,6 +16,8 @@
#include "jsobjinlines.h" #include "jsobjinlines.h"
#include "vm/ObjectImpl-inl.h"
using namespace js; using namespace js;
using namespace js::types; using namespace js::types;
@ -46,7 +48,7 @@ js::CreateRegExpMatchResult(JSContext *cx, HandleString input, const MatchPairs
size_t numPairs = matches.length(); size_t numPairs = matches.length();
MOZ_ASSERT(numPairs > 0); MOZ_ASSERT(numPairs > 0);
RootedObject arr(cx, NewDenseFullyAllocatedArrayWithTemplate(cx, numPairs, templateObject)); RootedArrayObject arr(cx, NewDenseFullyAllocatedArrayWithTemplate(cx, numPairs, templateObject));
if (!arr) if (!arr)
return false; return false;
@ -71,21 +73,21 @@ js::CreateRegExpMatchResult(JSContext *cx, HandleString input, const MatchPairs
} }
/* Set the |index| property. (TemplateObject positions it in slot 0) */ /* Set the |index| property. (TemplateObject positions it in slot 0) */
arr->nativeSetSlot(0, Int32Value(matches[0].start)); arr->setSlot(0, Int32Value(matches[0].start));
/* Set the |input| property. (TemplateObject positions it in slot 1) */ /* Set the |input| property. (TemplateObject positions it in slot 1) */
arr->nativeSetSlot(1, StringValue(input)); arr->setSlot(1, StringValue(input));
#ifdef DEBUG #ifdef DEBUG
RootedValue test(cx); RootedValue test(cx);
RootedId id(cx, NameToId(cx->names().index)); RootedId id(cx, NameToId(cx->names().index));
if (!baseops::GetProperty(cx, arr, id, &test)) if (!baseops::GetProperty(cx, arr, id, &test))
return false; return false;
MOZ_ASSERT(test == arr->nativeGetSlot(0)); MOZ_ASSERT(test == arr->getSlot(0));
id = NameToId(cx->names().input); id = NameToId(cx->names().input);
if (!baseops::GetProperty(cx, arr, id, &test)) if (!baseops::GetProperty(cx, arr, id, &test))
return false; return false;
MOZ_ASSERT(test == arr->nativeGetSlot(1)); MOZ_ASSERT(test == arr->getSlot(1));
#endif #endif
rval.setObject(*arr); rval.setObject(*arr);
@ -508,7 +510,7 @@ js_InitRegExpClass(JSContext *cx, HandleObject obj)
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>()); Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
RootedObject proto(cx, global->createBlankPrototype(cx, &RegExpObject::class_)); RootedNativeObject proto(cx, global->createBlankPrototype(cx, &RegExpObject::class_));
if (!proto) if (!proto)
return nullptr; return nullptr;
proto->setPrivate(nullptr); proto->setPrivate(nullptr);

View File

@ -7,13 +7,12 @@
#ifndef builtin_SymbolObject_h #ifndef builtin_SymbolObject_h
#define builtin_SymbolObject_h #define builtin_SymbolObject_h
#include "jsobj.h" #include "vm/ObjectImpl.h"
#include "vm/Symbol.h" #include "vm/Symbol.h"
namespace js { namespace js {
class SymbolObject : public JSObject class SymbolObject : public NativeObject
{ {
/* Stores this Symbol object's [[PrimitiveValue]]. */ /* Stores this Symbol object's [[PrimitiveValue]]. */
static const unsigned PRIMITIVE_VALUE_SLOT = 0; static const unsigned PRIMITIVE_VALUE_SLOT = 0;

View File

@ -36,6 +36,8 @@
#include "jscntxtinlines.h" #include "jscntxtinlines.h"
#include "jsobjinlines.h" #include "jsobjinlines.h"
#include "vm/ObjectImpl-inl.h"
using namespace js; using namespace js;
using namespace JS; using namespace JS;
@ -1369,7 +1371,7 @@ SetIonCheckGraphCoherency(JSContext *cx, unsigned argc, jsval *vp)
return true; return true;
} }
class CloneBufferObject : public JSObject { class CloneBufferObject : public NativeObject {
static const JSPropertySpec props_[2]; static const JSPropertySpec props_[2];
static const size_t DATA_SLOT = 0; static const size_t DATA_SLOT = 0;
static const size_t LENGTH_SLOT = 1; static const size_t LENGTH_SLOT = 1;
@ -1382,8 +1384,8 @@ class CloneBufferObject : public JSObject {
RootedObject obj(cx, JS_NewObject(cx, Jsvalify(&class_), JS::NullPtr(), JS::NullPtr())); RootedObject obj(cx, JS_NewObject(cx, Jsvalify(&class_), JS::NullPtr(), JS::NullPtr()));
if (!obj) if (!obj)
return nullptr; return nullptr;
obj->setReservedSlot(DATA_SLOT, PrivateValue(nullptr)); obj->as<CloneBufferObject>().setReservedSlot(DATA_SLOT, PrivateValue(nullptr));
obj->setReservedSlot(LENGTH_SLOT, Int32Value(0)); obj->as<CloneBufferObject>().setReservedSlot(LENGTH_SLOT, Int32Value(0));
if (!JS_DefineProperties(cx, obj, props_)) if (!JS_DefineProperties(cx, obj, props_))
return nullptr; return nullptr;
@ -1976,7 +1978,7 @@ FindPath(JSContext *cx, unsigned argc, jsval *vp)
// //
// { node: undefined, edge: <string> } // { node: undefined, edge: <string> }
size_t length = nodes.length(); size_t length = nodes.length();
RootedObject result(cx, NewDenseFullyAllocatedArray(cx, length)); RootedArrayObject result(cx, NewDenseFullyAllocatedArray(cx, length));
if (!result) if (!result)
return false; return false;
result->ensureDenseInitializedLength(cx, 0, length); result->ensureDenseInitializedLength(cx, 0, length);

View File

@ -25,6 +25,7 @@
#include "jsatominlines.h" #include "jsatominlines.h"
#include "jsobjinlines.h" #include "jsobjinlines.h"
#include "vm/ObjectImpl-inl.h"
#include "vm/Shape-inl.h" #include "vm/Shape-inl.h"
using mozilla::AssertedCast; using mozilla::AssertedCast;
@ -1123,21 +1124,19 @@ StructMetaTypeDescr::construct(JSContext *cx, unsigned int argc, Value *vp)
size_t size_t
StructTypeDescr::fieldCount() const StructTypeDescr::fieldCount() const
{ {
return getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_NAMES).toObject().getDenseInitializedLength(); return fieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_NAMES).getDenseInitializedLength();
} }
size_t size_t
StructTypeDescr::maybeForwardedFieldCount() const StructTypeDescr::maybeForwardedFieldCount() const
{ {
JSObject *fieldNames = return maybeForwardedFieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_NAMES).getDenseInitializedLength();
MaybeForwarded(&getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_NAMES).toObject());
return fieldNames->getDenseInitializedLength();
} }
bool bool
StructTypeDescr::fieldIndex(jsid id, size_t *out) const StructTypeDescr::fieldIndex(jsid id, size_t *out) const
{ {
JSObject &fieldNames = getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_NAMES).toObject(); NativeObject &fieldNames = fieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_NAMES);
size_t l = fieldNames.getDenseInitializedLength(); size_t l = fieldNames.getDenseInitializedLength();
for (size_t i = 0; i < l; i++) { for (size_t i = 0; i < l; i++) {
JSAtom &a = fieldNames.getDenseElement(i).toString()->asAtom(); JSAtom &a = fieldNames.getDenseElement(i).toString()->asAtom();
@ -1152,15 +1151,13 @@ StructTypeDescr::fieldIndex(jsid id, size_t *out) const
JSAtom & JSAtom &
StructTypeDescr::fieldName(size_t index) const StructTypeDescr::fieldName(size_t index) const
{ {
JSObject &fieldNames = getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_NAMES).toObject(); return fieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_NAMES).getDenseElement(index).toString()->asAtom();
return fieldNames.getDenseElement(index).toString()->asAtom();
} }
size_t size_t
StructTypeDescr::fieldOffset(size_t index) const StructTypeDescr::fieldOffset(size_t index) const
{ {
JSObject &fieldOffsets = NativeObject &fieldOffsets = fieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS);
getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS).toObject();
MOZ_ASSERT(index < fieldOffsets.getDenseInitializedLength()); MOZ_ASSERT(index < fieldOffsets.getDenseInitializedLength());
return AssertedCast<size_t>(fieldOffsets.getDenseElement(index).toInt32()); return AssertedCast<size_t>(fieldOffsets.getDenseElement(index).toInt32());
} }
@ -1168,8 +1165,7 @@ StructTypeDescr::fieldOffset(size_t index) const
size_t size_t
StructTypeDescr::maybeForwardedFieldOffset(size_t index) const StructTypeDescr::maybeForwardedFieldOffset(size_t index) const
{ {
JSObject &fieldOffsets = NativeObject &fieldOffsets = maybeForwardedFieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS);
*MaybeForwarded(&getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS).toObject());
MOZ_ASSERT(index < fieldOffsets.getDenseInitializedLength()); MOZ_ASSERT(index < fieldOffsets.getDenseInitializedLength());
return AssertedCast<size_t>(fieldOffsets.getDenseElement(index).toInt32()); return AssertedCast<size_t>(fieldOffsets.getDenseElement(index).toInt32());
} }
@ -1177,8 +1173,7 @@ StructTypeDescr::maybeForwardedFieldOffset(size_t index) const
SizedTypeDescr& SizedTypeDescr&
StructTypeDescr::fieldDescr(size_t index) const StructTypeDescr::fieldDescr(size_t index) const
{ {
JSObject &fieldDescrs = NativeObject &fieldDescrs = fieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_TYPES);
getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_TYPES).toObject();
MOZ_ASSERT(index < fieldDescrs.getDenseInitializedLength()); MOZ_ASSERT(index < fieldDescrs.getDenseInitializedLength());
return fieldDescrs.getDenseElement(index).toObject().as<SizedTypeDescr>(); return fieldDescrs.getDenseElement(index).toObject().as<SizedTypeDescr>();
} }
@ -1186,8 +1181,7 @@ StructTypeDescr::fieldDescr(size_t index) const
SizedTypeDescr& SizedTypeDescr&
StructTypeDescr::maybeForwardedFieldDescr(size_t index) const StructTypeDescr::maybeForwardedFieldDescr(size_t index) const
{ {
JSObject &fieldDescrs = NativeObject &fieldDescrs = maybeForwardedFieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_TYPES);
*MaybeForwarded(&getReservedSlot(JS_DESCR_SLOT_STRUCT_FIELD_TYPES).toObject());
MOZ_ASSERT(index < fieldDescrs.getDenseInitializedLength()); MOZ_ASSERT(index < fieldDescrs.getDenseInitializedLength());
JSObject &descr = JSObject &descr =
*MaybeForwarded(&fieldDescrs.getDenseElement(index).toObject()); *MaybeForwarded(&fieldDescrs.getDenseElement(index).toObject());
@ -1301,7 +1295,7 @@ template<typename T>
static JSObject * static JSObject *
DefineMetaTypeDescr(JSContext *cx, DefineMetaTypeDescr(JSContext *cx,
Handle<GlobalObject*> global, Handle<GlobalObject*> global,
HandleObject module, HandleNativeObject module,
TypedObjectModuleObject::Slot protoSlot) TypedObjectModuleObject::Slot protoSlot)
{ {
RootedAtom className(cx, Atomize(cx, T::class_.name, RootedAtom className(cx, Atomize(cx, T::class_.name,
@ -1470,7 +1464,7 @@ TypedObject::offset() const
{ {
if (is<InlineOpaqueTypedObject>()) if (is<InlineOpaqueTypedObject>())
return 0; return 0;
return getReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET).toInt32(); return fakeNativeGetReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET).toInt32();
} }
int32_t int32_t
@ -1586,10 +1580,10 @@ OutlineTypedObject::createUnattachedWithClass(JSContext *cx,
if (!obj) if (!obj)
return nullptr; return nullptr;
obj->initPrivate(nullptr); obj->fakeNativeInitPrivate(nullptr);
obj->initReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(0)); obj->fakeNativeInitReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(0));
obj->initReservedSlot(JS_BUFVIEW_SLOT_LENGTH, Int32Value(length)); obj->fakeNativeInitReservedSlot(JS_BUFVIEW_SLOT_LENGTH, Int32Value(length));
obj->initReservedSlot(JS_BUFVIEW_SLOT_OWNER, NullValue()); obj->fakeNativeInitReservedSlot(JS_BUFVIEW_SLOT_OWNER, NullValue());
return &obj->as<OutlineTypedObject>(); return &obj->as<OutlineTypedObject>();
} }
@ -1603,9 +1597,9 @@ OutlineTypedObject::attach(JSContext *cx, ArrayBufferObject &buffer, int32_t off
if (!buffer.addView(cx, this)) if (!buffer.addView(cx, this))
CrashAtUnhandlableOOM("TypedObject::attach"); CrashAtUnhandlableOOM("TypedObject::attach");
InitArrayBufferViewDataPointer(this, &buffer, offset); fakeNativeInitPrivate(buffer.dataPointer() + offset);
setReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(offset)); fakeNativeSetReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(offset));
setReservedSlot(JS_BUFVIEW_SLOT_OWNER, ObjectValue(buffer)); fakeNativeSetReservedSlot(JS_BUFVIEW_SLOT_OWNER, ObjectValue(buffer));
} }
void void
@ -1623,11 +1617,11 @@ OutlineTypedObject::attach(JSContext *cx, TypedObject &typedObj, int32_t offset)
attach(cx, owner->as<ArrayBufferObject>(), offset); attach(cx, owner->as<ArrayBufferObject>(), offset);
} else { } else {
MOZ_ASSERT(owner->is<InlineOpaqueTypedObject>()); MOZ_ASSERT(owner->is<InlineOpaqueTypedObject>());
initPrivate(owner->as<InlineOpaqueTypedObject>().inlineTypedMem() + offset); fakeNativeInitPrivate(owner->as<InlineOpaqueTypedObject>().inlineTypedMem() + offset);
PostBarrierTypedArrayObject(this); PostBarrierTypedArrayObject(this);
setReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(offset)); fakeNativeSetReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(offset));
setReservedSlot(JS_BUFVIEW_SLOT_OWNER, ObjectValue(*owner)); fakeNativeSetReservedSlot(JS_BUFVIEW_SLOT_OWNER, ObjectValue(*owner));
} }
} }
@ -1767,7 +1761,7 @@ OutlineTypedObject::obj_trace(JSTracer *trc, JSObject *object)
// Mark the owner, watching in case it is moved by the tracer. // Mark the owner, watching in case it is moved by the tracer.
JSObject *oldOwner = typedObj.maybeOwner(); JSObject *oldOwner = typedObj.maybeOwner();
gc::MarkSlot(trc, &typedObj.getFixedSlotRef(JS_BUFVIEW_SLOT_OWNER), "typed object owner"); gc::MarkSlot(trc, &typedObj.fakeNativeGetSlotRef(JS_BUFVIEW_SLOT_OWNER), "typed object owner");
JSObject *owner = typedObj.maybeOwner(); JSObject *owner = typedObj.maybeOwner();
uint8_t *mem = typedObj.outOfLineTypedMem(); uint8_t *mem = typedObj.outOfLineTypedMem();
@ -1779,7 +1773,7 @@ OutlineTypedObject::obj_trace(JSTracer *trc, JSObject *object)
owner->as<ArrayBufferObject>().hasInlineData())) owner->as<ArrayBufferObject>().hasInlineData()))
{ {
mem += reinterpret_cast<uint8_t *>(owner) - reinterpret_cast<uint8_t *>(oldOwner); mem += reinterpret_cast<uint8_t *>(owner) - reinterpret_cast<uint8_t *>(oldOwner);
typedObj.setPrivate(mem); typedObj.fakeNativeSetPrivate(mem);
} }
if (!descr.opaque() || !typedObj.maybeForwardedIsAttached()) if (!descr.opaque() || !typedObj.maybeForwardedIsAttached())
@ -2328,7 +2322,7 @@ TypedObject::obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
/* static */ size_t /* static */ size_t
OutlineTypedObject::offsetOfOwnerSlot() OutlineTypedObject::offsetOfOwnerSlot()
{ {
return JSObject::getFixedSlotOffset(JS_BUFVIEW_SLOT_OWNER); return NativeObject::getFixedSlotOffset(JS_BUFVIEW_SLOT_OWNER);
} }
/* static */ size_t /* static */ size_t
@ -2343,21 +2337,21 @@ OutlineTypedObject::offsetOfDataSlot()
MOZ_ASSERT(DATA_SLOT == nfixed - 1); MOZ_ASSERT(DATA_SLOT == nfixed - 1);
#endif #endif
return JSObject::getPrivateDataOffset(DATA_SLOT); return NativeObject::getPrivateDataOffset(DATA_SLOT);
} }
/* static */ size_t /* static */ size_t
OutlineTypedObject::offsetOfByteOffsetSlot() OutlineTypedObject::offsetOfByteOffsetSlot()
{ {
return JSObject::getFixedSlotOffset(JS_BUFVIEW_SLOT_BYTEOFFSET); return NativeObject::getFixedSlotOffset(JS_BUFVIEW_SLOT_BYTEOFFSET);
} }
void void
OutlineTypedObject::neuter(void *newData) OutlineTypedObject::neuter(void *newData)
{ {
setSlot(JS_BUFVIEW_SLOT_LENGTH, Int32Value(0)); fakeNativeSetSlot(JS_BUFVIEW_SLOT_LENGTH, Int32Value(0));
setSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(0)); fakeNativeSetSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(0));
setPrivate(newData); fakeNativeSetPrivate(newData);
} }
/****************************************************************************** /******************************************************************************
@ -2383,14 +2377,14 @@ InlineOpaqueTypedObject::create(JSContext *cx, HandleTypeDescr descr)
uint8_t * uint8_t *
InlineOpaqueTypedObject::inlineTypedMem() const InlineOpaqueTypedObject::inlineTypedMem() const
{ {
return fixedData(0); return fakeNativeFixedData(0);
} }
/* static */ /* static */
size_t size_t
InlineOpaqueTypedObject::offsetOfDataStart() InlineOpaqueTypedObject::offsetOfDataStart()
{ {
return getFixedSlotOffset(0); return NativeObject::getFixedSlotOffset(0);
} }
/* static */ void /* static */ void
@ -2843,8 +2837,8 @@ js::SetTypedObjectOffset(ThreadSafeContext *, unsigned argc, Value *vp)
MOZ_ASSERT(typedObj.isAttached()); MOZ_ASSERT(typedObj.isAttached());
int32_t oldOffset = typedObj.offset(); int32_t oldOffset = typedObj.offset();
typedObj.setPrivate((typedObj.typedMem() - oldOffset) + offset); typedObj.fakeNativeSetPrivate((typedObj.typedMem() - oldOffset) + offset);
typedObj.setReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(offset)); typedObj.fakeNativeSetReservedSlot(JS_BUFVIEW_SLOT_BYTEOFFSET, Int32Value(offset));
args.rval().setUndefined(); args.rval().setUndefined();
return true; return true;
} }

View File

@ -144,7 +144,7 @@ class SizedTypedProto;
* type descriptor. Eventually will carry most of the type information * type descriptor. Eventually will carry most of the type information
* we want. * we want.
*/ */
class TypedProto : public JSObject class TypedProto : public NativeObject
{ {
public: public:
static const Class class_; static const Class class_;
@ -162,7 +162,7 @@ class TypedProto : public JSObject
inline type::Kind kind() const; inline type::Kind kind() const;
}; };
class TypeDescr : public JSObject class TypeDescr : public NativeObject
{ {
public: public:
// This is *intentionally* not defined so as to produce link // This is *intentionally* not defined so as to produce link
@ -509,6 +509,15 @@ class StructTypeDescr : public ComplexTypeDescr
// Return the offset of the field at index `index`. // Return the offset of the field at index `index`.
size_t fieldOffset(size_t index) const; size_t fieldOffset(size_t index) const;
size_t maybeForwardedFieldOffset(size_t index) const; size_t maybeForwardedFieldOffset(size_t index) const;
private:
NativeObject &fieldInfoObject(size_t slot) const {
return getReservedSlot(slot).toObject().as<NativeObject>();
}
NativeObject &maybeForwardedFieldInfoObject(size_t slot) const {
return *MaybeForwarded(&fieldInfoObject(slot));
}
}; };
typedef Handle<StructTypeDescr*> HandleStructTypeDescr; typedef Handle<StructTypeDescr*> HandleStructTypeDescr;
@ -518,7 +527,7 @@ typedef Handle<StructTypeDescr*> HandleStructTypeDescr;
* somewhat, rather than sticking them all into the global object. * somewhat, rather than sticking them all into the global object.
* Eventually it will go away and become a module. * Eventually it will go away and become a module.
*/ */
class TypedObjectModuleObject : public JSObject { class TypedObjectModuleObject : public NativeObject {
public: public:
enum Slot { enum Slot {
ArrayTypePrototype, ArrayTypePrototype,
@ -530,7 +539,7 @@ class TypedObjectModuleObject : public JSObject {
}; };
/* Base type for transparent and opaque typed objects. */ /* Base type for transparent and opaque typed objects. */
class TypedObject : public ArrayBufferViewObject class TypedObject : public JSObject
{ {
private: private:
static const bool IsTypedObjectClass = true; static const bool IsTypedObjectClass = true;
@ -690,19 +699,19 @@ class OutlineTypedObject : public TypedObject
static size_t offsetOfByteOffsetSlot(); static size_t offsetOfByteOffsetSlot();
JSObject &owner() const { JSObject &owner() const {
return getReservedSlot(JS_BUFVIEW_SLOT_OWNER).toObject(); return fakeNativeGetReservedSlot(JS_BUFVIEW_SLOT_OWNER).toObject();
} }
JSObject *maybeOwner() const { JSObject *maybeOwner() const {
return getReservedSlot(JS_BUFVIEW_SLOT_OWNER).toObjectOrNull(); return fakeNativeGetReservedSlot(JS_BUFVIEW_SLOT_OWNER).toObjectOrNull();
} }
uint8_t *outOfLineTypedMem() const { uint8_t *outOfLineTypedMem() const {
return static_cast<uint8_t *>(getPrivate(DATA_SLOT)); return static_cast<uint8_t *>(fakeNativeGetPrivate(DATA_SLOT));
} }
int32_t length() const { int32_t length() const {
return getReservedSlot(JS_BUFVIEW_SLOT_LENGTH).toInt32(); return fakeNativeGetReservedSlot(JS_BUFVIEW_SLOT_LENGTH).toInt32();
} }
// Helper for createUnattached() // Helper for createUnattached()
@ -763,7 +772,7 @@ class InlineOpaqueTypedObject : public TypedObject
public: public:
static const Class class_; static const Class class_;
static const size_t MaximumSize = JSObject::MAX_FIXED_SLOTS * sizeof(Value); static const size_t MaximumSize = NativeObject::MAX_FIXED_SLOTS * sizeof(Value);
static gc::AllocKind allocKindForTypeDescriptor(TypeDescr *descr) { static gc::AllocKind allocKindForTypeDescriptor(TypeDescr *descr) {
size_t nbytes = descr->as<SizedTypeDescr>().size(); size_t nbytes = descr->as<SizedTypeDescr>().size();

View File

@ -92,7 +92,7 @@ function CheckObjectCoercible(v) {
ThrowError(JSMSG_CANT_CONVERT_TO, ToString(v), "object"); ThrowError(JSMSG_CANT_CONVERT_TO, ToString(v), "object");
} }
// Spec: ECMAScript Draft, 6th edition May 22, 2014, 7.1.15. /* Spec: ECMAScript Draft, 6 edition May 22, 2014, 7.1.15 */
function ToLength(v) { function ToLength(v) {
v = ToInteger(v); v = ToInteger(v);
@ -103,11 +103,6 @@ function ToLength(v) {
return v < 0x1fffffffffffff ? v : 0x1fffffffffffff; return v < 0x1fffffffffffff ? v : 0x1fffffffffffff;
} }
// Spec: ECMAScript Draft, 6th edition Aug 24, 2014, 7.2.4.
function SameValueZero(x, y) {
return x === y || (x !== x && y !== y);
}
/********** Testing code **********/ /********** Testing code **********/
#ifdef ENABLE_PARALLEL_JS #ifdef ENABLE_PARALLEL_JS

View File

@ -15,6 +15,8 @@
#include "jsobjinlines.h" #include "jsobjinlines.h"
#include "vm/ObjectImpl-inl.h"
using namespace js; using namespace js;
using namespace JS; using namespace JS;
@ -48,7 +50,7 @@ WeakSetObject::initClass(JSContext *cx, JSObject *obj)
{ {
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>()); Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
// Todo: WeakSet.prototype should not be a WeakSet! // Todo: WeakSet.prototype should not be a WeakSet!
Rooted<JSObject*> proto(cx, global->createBlankPrototype(cx, &class_)); RootedNativeObject proto(cx, global->createBlankPrototype(cx, &class_));
if (!proto) if (!proto)
return nullptr; return nullptr;
proto->setReservedSlot(WEAKSET_MAP_SLOT, UndefinedValue()); proto->setReservedSlot(WEAKSET_MAP_SLOT, UndefinedValue());
@ -67,7 +69,7 @@ WeakSetObject::initClass(JSContext *cx, JSObject *obj)
WeakSetObject* WeakSetObject*
WeakSetObject::create(JSContext *cx) WeakSetObject::create(JSContext *cx)
{ {
RootedObject obj(cx, NewBuiltinClassInstance(cx, &class_)); RootedNativeObject obj(cx, NewNativeBuiltinClassInstance(cx, &class_));
if (!obj) if (!obj)
return nullptr; return nullptr;

View File

@ -7,11 +7,11 @@
#ifndef builtin_WeakSetObject_h #ifndef builtin_WeakSetObject_h
#define builtin_WeakSetObject_h #define builtin_WeakSetObject_h
#include "jsobj.h" #include "vm/ObjectImpl.h"
namespace js { namespace js {
class WeakSetObject : public JSObject class WeakSetObject : public NativeObject
{ {
public: public:
static const unsigned RESERVED_SLOTS = 1; static const unsigned RESERVED_SLOTS = 1;

View File

@ -3393,14 +3393,14 @@ void
CType::Trace(JSTracer* trc, JSObject* obj) CType::Trace(JSTracer* trc, JSObject* obj)
{ {
// Make sure our TypeCode slot is legit. If it's not, bail. // Make sure our TypeCode slot is legit. If it's not, bail.
jsval slot = obj->getSlot(SLOT_TYPECODE); jsval slot = obj->as<NativeObject>().getSlot(SLOT_TYPECODE);
if (slot.isUndefined()) if (slot.isUndefined())
return; return;
// The contents of our slots depends on what kind of type we are. // The contents of our slots depends on what kind of type we are.
switch (TypeCode(slot.toInt32())) { switch (TypeCode(slot.toInt32())) {
case TYPE_struct: { case TYPE_struct: {
slot = obj->getReservedSlot(SLOT_FIELDINFO); slot = obj->as<NativeObject>().getReservedSlot(SLOT_FIELDINFO);
if (slot.isUndefined()) if (slot.isUndefined())
return; return;
@ -3417,7 +3417,7 @@ CType::Trace(JSTracer* trc, JSObject* obj)
} }
case TYPE_function: { case TYPE_function: {
// Check if we have a FunctionInfo. // Check if we have a FunctionInfo.
slot = obj->getReservedSlot(SLOT_FNINFO); slot = obj->as<NativeObject>().getReservedSlot(SLOT_FNINFO);
if (slot.isUndefined()) if (slot.isUndefined())
return; return;

View File

@ -39,6 +39,7 @@
#include "frontend/ParseMaps-inl.h" #include "frontend/ParseMaps-inl.h"
#include "frontend/ParseNode-inl.h" #include "frontend/ParseNode-inl.h"
#include "vm/ObjectImpl-inl.h"
#include "vm/ScopeObject-inl.h" #include "vm/ScopeObject-inl.h"
using namespace js; using namespace js;
@ -2166,9 +2167,9 @@ IteratorResultShape(ExclusiveContext *cx, BytecodeEmitter *bce, unsigned *shape)
{ {
MOZ_ASSERT(bce->script->compileAndGo()); MOZ_ASSERT(bce->script->compileAndGo());
RootedObject obj(cx); RootedNativeObject obj(cx);
gc::AllocKind kind = GuessObjectGCKind(2); gc::AllocKind kind = GuessObjectGCKind(2);
obj = NewBuiltinClassInstance(cx, &JSObject::class_, kind); obj = NewNativeBuiltinClassInstance(cx, &JSObject::class_, kind);
if (!obj) if (!obj)
return false; return false;
@ -4065,7 +4066,7 @@ ParseNode::getConstantValue(ExclusiveContext *cx, AllowConstantObjects allowObje
pn = pn_head; pn = pn_head;
} }
RootedObject obj(cx, NewDenseFullyAllocatedArray(cx, count, nullptr, MaybeSingletonObject)); RootedArrayObject obj(cx, NewDenseFullyAllocatedArray(cx, count, nullptr, MaybeSingletonObject));
if (!obj) if (!obj)
return false; return false;
@ -4094,7 +4095,8 @@ ParseNode::getConstantValue(ExclusiveContext *cx, AllowConstantObjects allowObje
allowObjects = DontAllowObjects; allowObjects = DontAllowObjects;
gc::AllocKind kind = GuessObjectGCKind(pn_count); gc::AllocKind kind = GuessObjectGCKind(pn_count);
RootedObject obj(cx, NewBuiltinClassInstance(cx, &JSObject::class_, kind, MaybeSingletonObject)); RootedNativeObject obj(cx, NewNativeBuiltinClassInstance(cx, &JSObject::class_,
kind, MaybeSingletonObject));
if (!obj) if (!obj)
return false; return false;
@ -4157,7 +4159,7 @@ EmitSingletonInitialiser(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *
if (!pn->getConstantValue(cx, ParseNode::AllowObjects, &value)) if (!pn->getConstantValue(cx, ParseNode::AllowObjects, &value))
return false; return false;
RootedObject obj(cx, &value.toObject()); RootedNativeObject obj(cx, &value.toObject().as<NativeObject>());
if (!obj->is<ArrayObject>() && !JSObject::setSingletonType(cx, obj)) if (!obj->is<ArrayObject>() && !JSObject::setSingletonType(cx, obj))
return false; return false;
@ -4177,7 +4179,7 @@ EmitCallSiteObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
MOZ_ASSERT(value.isObject()); MOZ_ASSERT(value.isObject());
ObjectBox *objbox1 = bce->parser->newObjectBox(&value.toObject()); ObjectBox *objbox1 = bce->parser->newObjectBox(&value.toObject().as<NativeObject>());
if (!objbox1) if (!objbox1)
return false; return false;
@ -4186,7 +4188,7 @@ EmitCallSiteObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
MOZ_ASSERT(value.isObject()); MOZ_ASSERT(value.isObject());
ObjectBox *objbox2 = bce->parser->newObjectBox(&value.toObject()); ObjectBox *objbox2 = bce->parser->newObjectBox(&value.toObject().as<NativeObject>());
if (!objbox2) if (!objbox2)
return false; return false;
@ -6219,10 +6221,10 @@ EmitObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* Try to construct the shape of the object as we go, so we can emit a * Try to construct the shape of the object as we go, so we can emit a
* JSOP_NEWOBJECT with the final shape instead. * JSOP_NEWOBJECT with the final shape instead.
*/ */
RootedObject obj(cx); RootedNativeObject obj(cx);
if (bce->script->compileAndGo()) { if (bce->script->compileAndGo()) {
gc::AllocKind kind = GuessObjectGCKind(pn->pn_count); gc::AllocKind kind = GuessObjectGCKind(pn->pn_count);
obj = NewBuiltinClassInstance(cx, &JSObject::class_, kind, TenuredObject); obj = NewNativeBuiltinClassInstance(cx, &JSObject::class_, kind, TenuredObject);
if (!obj) if (!obj)
return false; return false;
} }
@ -6904,7 +6906,7 @@ frontend::EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
// for the template is accurate. We don't do this here as we // for the template is accurate. We don't do this here as we
// want to use types::InitObject, which requires a finished // want to use types::InitObject, which requires a finished
// script. // script.
JSObject *obj = &value.toObject(); NativeObject *obj = &value.toObject().as<NativeObject>();
if (!ObjectElements::MakeElementsCopyOnWrite(cx, obj)) if (!ObjectElements::MakeElementsCopyOnWrite(cx, obj))
return false; return false;
@ -7278,7 +7280,7 @@ CGObjectList::finish(ObjectArray *array)
MOZ_ASSERT(length <= INDEX_LIMIT); MOZ_ASSERT(length <= INDEX_LIMIT);
MOZ_ASSERT(length == array->length); MOZ_ASSERT(length == array->length);
js::HeapPtrObject *cursor = array->vector + array->length; js::HeapPtrNativeObject *cursor = array->vector + array->length;
ObjectBox *objbox = lastbox; ObjectBox *objbox = lastbox;
do { do {
--cursor; --cursor;

View File

@ -172,7 +172,7 @@ class FullParseHandler
// Specifically, a Boxer has a .newObjectBox(T) method that accepts a // Specifically, a Boxer has a .newObjectBox(T) method that accepts a
// Rooted<RegExpObject*> argument and returns an ObjectBox*. // Rooted<RegExpObject*> argument and returns an ObjectBox*.
template <class Boxer> template <class Boxer>
ParseNode *newRegExp(HandleObject reobj, const TokenPos &pos, Boxer &boxer) { ParseNode *newRegExp(RegExpObject *reobj, const TokenPos &pos, Boxer &boxer) {
ObjectBox *objbox = boxer.newObjectBox(reobj); ObjectBox *objbox = boxer.newObjectBox(reobj);
if (!objbox) if (!objbox)
return null(); return null();

View File

@ -754,7 +754,7 @@ NameNode::dump(int indent)
} }
#endif #endif
ObjectBox::ObjectBox(JSObject *object, ObjectBox* traceLink) ObjectBox::ObjectBox(NativeObject *object, ObjectBox* traceLink)
: object(object), : object(object),
traceLink(traceLink), traceLink(traceLink),
emitLink(nullptr) emitLink(nullptr)

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