Merge inbound to m-c a=merge

This commit is contained in:
Wes Kocher 2015-01-27 16:02:52 -08:00
commit 8636f49fd5
132 changed files with 1758 additions and 837 deletions

View File

@ -896,13 +896,16 @@ Messages.Simple.prototype = Heritage.extend(Messages.BaseMessage.prototype,
let body = this.document.createElementNS(XHTML_NS, "span");
body.className = "message-body-wrapper message-body devtools-monospace";
let anchor, container = body;
let bodyInner = this.document.createElementNS(XHTML_NS, "span");
body.appendChild(bodyInner);
let anchor, container = bodyInner;
if (this._link || this._linkCallback) {
container = anchor = this.document.createElementNS(XHTML_NS, "a");
anchor.href = this._link || "#";
anchor.draggable = false;
this._addLinkCallback(anchor, this._linkCallback);
body.appendChild(anchor);
bodyInner.appendChild(anchor);
}
if (typeof this._message == "function") {

View File

@ -57,7 +57,9 @@ function consoleOpened(aHud) {
controller = top.document.commandDispatcher.getControllerForCommand("cmd_copy");
is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
let selection = HUD.iframeWindow.getSelection() + "";
// Remove new lines since getSelection() includes one between message and line
// number, but the clipboard doesn't (see bug 1119503)
let selection = (HUD.iframeWindow.getSelection() + "").replace(/\r?\n|\r/g, " ");
isnot(selection.indexOf("bug587617"), -1,
"selection text includes 'bug587617'");
@ -80,7 +82,9 @@ function testContextMenuCopy() {
let copyItem = contextMenu.querySelector("*[command='cmd_copy']");
ok(copyItem, "the context menu on the output node has a \"Copy\" item");
let selection = HUD.iframeWindow.getSelection() + "";
// Remove new lines since getSelection() includes one between message and line
// number, but the clipboard doesn't (see bug 1119503)
let selection = (HUD.iframeWindow.getSelection() + "").replace(/\r?\n|\r/g, " ");
copyItem.doCommand();

View File

@ -69,7 +69,9 @@ function performTest(HUD, [result]) {
getControllerForCommand("cmd_copy");
is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
let selectionText = HUD.iframeWindow.getSelection() + "";
// Remove new lines since getSelection() includes one between message and line
// number, but the clipboard doesn't (see bug 1119503)
let selectionText = (HUD.iframeWindow.getSelection() + "").replace(/\r?\n|\r/g, " ");
isnot(selectionText.indexOf("foobarBazBug613280"), -1,
"selection text includes 'foobarBazBug613280'");

View File

@ -117,7 +117,7 @@ a {
display: flex;
}
.message-body {
.message-body > * {
white-space: pre-wrap;
word-wrap: break-word;
}

View File

@ -4106,23 +4106,6 @@ elif test "$EARLY_BETA_OR_EARLIER"; then
fi
AC_SUBST(EARLY_BETA_OR_EARLIER)
# Allow the application to provide a subconfigure script
if test -f "${srcdir}/${MOZ_BUILD_APP}/configure.in" ; then
do_output_subdirs() {
if test -n "$_subconfigure_subdirs"; then
AC_MSG_ERROR([Cannot specify more than one sub-sub-configure])
fi
_subconfigure_subdir="$1"
_subconfigure_config_args="$ac_configure_args"
}
tmpscript=`$PYTHON -c 'import os, tempfile; print tempfile.mktemp(prefix="subscript.").replace(os.sep, "/")'` || exit 1
m4 "${srcdir}/build/autoconf/subconfigure.m4" \
"${srcdir}/build/autoconf/altoptions.m4" \
"${srcdir}/${MOZ_BUILD_APP}/configure.in" > $tmpscript
. $tmpscript
rm -f $tmpscript
fi
# Allow someone to change MOZ_APP_NAME and MOZ_APP_BASENAME in mozconfig
MOZ_ARG_WITH_STRING(app-name,
[--with-app-name=APPNAME sets MOZ_APP_NAME to APPNAME],
@ -5964,7 +5947,6 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
fi
else
AC_MSG_RESULT([Couldn't find an acceptable DirectX SDK for ANGLE, needed for d3dcompiler_43.])
AC_MSG_RESULT([ Either ignore, install DirectX SDK (June 2010 version or newer), or reconfigure with --disable-webgl.])
fi
fi
@ -5990,7 +5972,6 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
if test -z "$CROSS_COMPILE"; then
if test -z "MOZ_FOUND_A_D3D_COMPILER"; then
AC_MSG_ERROR([Couldn't find an acceptable D3D compiler DLL.])
AC_MSG_ERROR([ Either install Windows SDK 8.0+, install DirectX SDK (June 2010 version or newer), or reconfigure with --disable-webgl.])
fi
if test -n "$MOZ_REQUIRE_ALL_D3DCS" -a -z "$MOZ_FOUND_BOTH_D3D_COMPILERS"; then
@ -7257,6 +7238,25 @@ export MOZ_CRT
AC_SUBST(MOZ_GLUE_IN_PROGRAM)
AC_SUBST_LIST(WIN32_CRT_LIBS)
# Allow the application to provide a subconfigure script.
# This should be after 'export MOZ_NO_DEBUG_RTL=1' since
# ldap/c-sdk/configure refers to the enviroment value.
if test -f "${srcdir}/${MOZ_BUILD_APP}/configure.in" ; then
do_output_subdirs() {
if test -n "$_subconfigure_subdirs"; then
AC_MSG_ERROR([Cannot specify more than one sub-sub-configure])
fi
_subconfigure_subdir="$1"
_subconfigure_config_args="$ac_configure_args"
}
tmpscript=`$PYTHON -c 'import os, tempfile; print tempfile.mktemp(prefix="subscript.").replace(os.sep, "/")'` || exit 1
m4 "${srcdir}/build/autoconf/subconfigure.m4" \
"${srcdir}/build/autoconf/altoptions.m4" \
"${srcdir}/${MOZ_BUILD_APP}/configure.in" > $tmpscript
. $tmpscript
rm -f $tmpscript
fi
dnl We need to wrap dlopen and related functions on Android because we use
dnl our own linker.
if test "$OS_TARGET" = Android; then

View File

@ -97,7 +97,8 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
// Do the first and potentially trial encoding as preformatted and raw.
uint32_t flags = aFlags | nsIDocumentEncoder::OutputPreformatted
| nsIDocumentEncoder::OutputRaw;
| nsIDocumentEncoder::OutputRaw
| nsIDocumentEncoder::OutputForPlainTextClipboardCopy;
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
NS_ASSERTION(domDoc, "Need a document");

View File

@ -227,6 +227,13 @@ interface nsIDocumentEncoder : nsISupports
*/
const unsigned long OutputDontRemoveLineEndingSpaces = (1 << 24);
/**
* Serialize in a way that is suitable for copying a plaintext version of the
* document to the clipboard. This can for example cause line endings to be
* injected at preformatted block element boundaries.
*/
const unsigned long OutputForPlainTextClipboardCopy = (1 << 25);
/**
* Initialize with a pointer to the document and the mime type.
* @param aDocument Document to encode.

View File

@ -17,6 +17,7 @@
#include "jsapi.h"
#include "jsfriendapi.h"
#include "js/Conversions.h"
#include "nsString.h"
class nsIScriptContext;

View File

@ -91,6 +91,8 @@ nsPlainTextSerializer::nsPlainTextSerializer()
mPreFormatted = false;
mStartedOutput = false;
mPreformattedBlockBoundary = false;
// initialize the tag stack to zero:
// The stack only ever contains pointers to static atoms, so they don't
// need refcounting.
@ -167,6 +169,8 @@ nsPlainTextSerializer::Init(uint32_t aFlags, uint32_t aWrapColumn,
mLineBreakDue = false;
mFloatingLines = -1;
mPreformattedBlockBoundary = false;
if (mFlags & nsIDocumentEncoder::OutputFormatted) {
// Get some prefs that controls how we do formatted output
mStructs = Preferences::GetBool(PREF_STRUCTS, mStructs);
@ -437,6 +441,16 @@ nsPlainTextSerializer::DoOpenContainer(nsIAtom* aTag)
return NS_OK;
}
if (mFlags & nsIDocumentEncoder::OutputForPlainTextClipboardCopy) {
if (mPreformattedBlockBoundary && DoOutput()) {
// Should always end a line, but get no more whitespace
if (mFloatingLines < 0)
mFloatingLines = 0;
mLineBreakDue = true;
}
mPreformattedBlockBoundary = false;
}
if (mFlags & nsIDocumentEncoder::OutputRaw) {
// Raw means raw. Don't even think about doing anything fancy
// here like indenting, adding line breaks or any other
@ -670,7 +684,7 @@ nsPlainTextSerializer::DoOpenContainer(nsIAtom* aTag)
// Else make sure we'll separate block level tags,
// even if we're about to leave, before doing any other formatting.
else if (nsContentUtils::IsHTMLBlock(aTag)) {
else if (IsElementBlock(mElement)) {
EnsureVerticalSpace(0);
}
@ -767,6 +781,14 @@ nsPlainTextSerializer::DoCloseContainer(nsIAtom* aTag)
return NS_OK;
}
if (mFlags & nsIDocumentEncoder::OutputForPlainTextClipboardCopy) {
if (DoOutput() && IsInPre() && IsElementBlock(mElement)) {
// If we're closing a preformatted block element, output a line break
// when we find a new container.
mPreformattedBlockBoundary = true;
}
}
if (mFlags & nsIDocumentEncoder::OutputRaw) {
// Raw means raw. Don't even think about doing anything fancy
// here like indenting, adding line breaks or any other
@ -887,8 +909,7 @@ nsPlainTextSerializer::DoCloseContainer(nsIAtom* aTag)
else if (aTag == nsGkAtoms::q) {
Write(NS_LITERAL_STRING("\""));
}
else if (nsContentUtils::IsHTMLBlock(aTag)
&& aTag != nsGkAtoms::script) {
else if (IsElementBlock(mElement) && aTag != nsGkAtoms::script) {
// All other blocks get 1 vertical space after them
// in formatted mode, otherwise 0.
// This is hard. Sometimes 0 is a better number, but
@ -1037,6 +1058,8 @@ nsPlainTextSerializer::DoAddText(bool aIsLineBreak, const nsAString& aText)
nsresult
nsPlainTextSerializer::DoAddLeaf(nsIAtom* aTag)
{
mPreformattedBlockBoundary = false;
// If we don't want any output, just return
if (!DoOutput()) {
return NS_OK;
@ -1778,6 +1801,20 @@ nsPlainTextSerializer::IsElementPreformatted(Element* aElement)
return GetIdForContent(aElement) == nsGkAtoms::pre;
}
bool
nsPlainTextSerializer::IsElementBlock(Element* aElement)
{
nsRefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement, nullptr,
nullptr);
if (styleContext) {
const nsStyleDisplay* displayStyle = styleContext->StyleDisplay();
return displayStyle->IsBlockOutsideStyle();
}
// Fall back to looking at the tag, in case there is no style information.
return nsContentUtils::IsHTMLBlock(GetIdForContent(aElement));
}
/**
* This method is required only to identify LI's inside OL.
* Returns TRUE if we are inside an OL tag and FALSE otherwise.

View File

@ -115,6 +115,7 @@ private:
bool ShouldReplaceContainerWithPlaceholder(nsIAtom* aTag);
bool IsElementPreformatted(mozilla::dom::Element* aElement);
bool IsElementBlock(mozilla::dom::Element* aElement);
private:
nsString mCurrentLine;
@ -169,7 +170,9 @@ private:
// While handling a new tag, this variable should remind if any line break
// is due because of a closing tag. Setting it to "TRUE" while closing the tags.
// Hence opening tags are guaranteed to start with appropriate line breaks.
bool mLineBreakDue;
bool mLineBreakDue;
bool mPreformattedBlockBoundary;
nsString mURL;
int32_t mHeaderStrategy; /* Header strategy (pref)

View File

@ -137,6 +137,31 @@ TestPreElement()
return NS_OK;
}
nsresult
TestBlockElement()
{
nsString test;
test.AppendLiteral(
"<html>" NS_LINEBREAK
"<body>" NS_LINEBREAK
"<div>" NS_LINEBREAK
" first" NS_LINEBREAK
"</div>" NS_LINEBREAK
"<div>" NS_LINEBREAK
" second" NS_LINEBREAK
"</div>" NS_LINEBREAK
"</body>" NS_LINEBREAK "</html>");
ConvertBufToPlainText(test, 0);
if (!test.EqualsLiteral("first" NS_LINEBREAK "second" NS_LINEBREAK)) {
fail("Wrong prettyprinted html to text serialization");
return NS_ERROR_FAILURE;
}
passed("prettyprinted HTML to text serialization test");
return NS_OK;
}
nsresult
TestPlainTextSerializer()
{
@ -163,6 +188,9 @@ TestPlainTextSerializer()
rv = TestPreElement();
NS_ENSURE_SUCCESS(rv, rv);
rv = TestBlockElement();
NS_ENSURE_SUCCESS(rv, rv);
// Add new tests here...
return NS_OK;
}

View File

@ -20,6 +20,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=116083
<div data-result="bar baz"><span style="white-space: pre-wrap">bar </span>baz</div>
<div data-result="bar baz"><span style="white-space: pre-line">bar </span>baz</div>
<div data-result="bar baz"><span style="white-space: -moz-pre-space">bar </span>baz</div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-wrap"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-wrap" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-line"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-line" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: -moz-pre-space"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: -moz-pre-space" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="&#10;foo bar&#10;">foo bar</div>
</div>
<script type="application/javascript">

View File

@ -9,6 +9,7 @@
#include "jsfriendapi.h"
#include "jswrapper.h"
#include "js/Conversions.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Alignment.h"
#include "mozilla/Array.h"

View File

@ -16,6 +16,7 @@
#include <stdint.h>
#include "jsapi.h"
#include "js/Conversions.h"
#include "mozilla/Assertions.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/FloatingPoint.h"

View File

@ -68,6 +68,7 @@
#include "jsapi.h"
#include "jsfriendapi.h"
#include "js/Conversions.h"
#include "mozilla/Alignment.h"
#include "mozilla/Assertions.h"
@ -4820,10 +4821,10 @@ CanvasRenderingContext2D::GetImageData(JSContext* aCx, double aSx,
return nullptr;
}
int32_t x = JS_DoubleToInt32(aSx);
int32_t y = JS_DoubleToInt32(aSy);
int32_t wi = JS_DoubleToInt32(aSw);
int32_t hi = JS_DoubleToInt32(aSh);
int32_t x = JS::ToInt32(aSx);
int32_t y = JS::ToInt32(aSy);
int32_t wi = JS::ToInt32(aSw);
int32_t hi = JS::ToInt32(aSh);
// Handle negative width and height by flipping the rectangle over in the
// relevant direction.
@ -5016,7 +5017,7 @@ CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx,
DebugOnly<bool> inited = arr.Init(imageData.GetDataObject());
MOZ_ASSERT(inited);
error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy),
error = PutImageData_explicit(JS::ToInt32(dx), JS::ToInt32(dy),
imageData.Width(), imageData.Height(),
&arr, false, 0, 0, 0, 0);
}
@ -5032,13 +5033,13 @@ CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx,
DebugOnly<bool> inited = arr.Init(imageData.GetDataObject());
MOZ_ASSERT(inited);
error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy),
error = PutImageData_explicit(JS::ToInt32(dx), JS::ToInt32(dy),
imageData.Width(), imageData.Height(),
&arr, true,
JS_DoubleToInt32(dirtyX),
JS_DoubleToInt32(dirtyY),
JS_DoubleToInt32(dirtyWidth),
JS_DoubleToInt32(dirtyHeight));
JS::ToInt32(dirtyX),
JS::ToInt32(dirtyY),
JS::ToInt32(dirtyWidth),
JS::ToInt32(dirtyHeight));
}
// void putImageData (in ImageData d, in float x, in float y);
@ -5206,8 +5207,8 @@ CanvasRenderingContext2D::CreateImageData(JSContext* cx, double sw,
return nullptr;
}
int32_t wi = JS_DoubleToInt32(sw);
int32_t hi = JS_DoubleToInt32(sh);
int32_t wi = JS::ToInt32(sw);
int32_t hi = JS::ToInt32(sh);
uint32_t w = Abs(wi);
uint32_t h = Abs(hi);

View File

@ -32,6 +32,12 @@ class WantsPopupControlCheck;
#define GENERATED_EVENT(EventClass_) class EventClass_;
#include "mozilla/dom/GeneratedEventList.h"
#undef GENERATED_EVENT
// ExtendableEvent and InstallEvent are ServiceWorker events that are not
// autogenerated since they have some extra methods.
namespace workers {
class ExtendableEvent;
class InstallEvent;
} // namespace workers
// Dummy class so we can cast through it to get from nsISupports to
// Event subclasses with only two non-ambiguous static casts.
@ -104,6 +110,18 @@ public:
#include "mozilla/dom/GeneratedEventList.h"
#undef GENERATED_EVENT
// ExtendableEvent and InstallEvent are ServiceWorker events that are not
// autogenerated since they have some extra methods.
virtual workers::ExtendableEvent* AsExtendableEvent()
{
return nullptr;
}
virtual workers::InstallEvent* AsInstallEvent()
{
return nullptr;
}
// nsIDOMEvent Interface
NS_DECL_NSIDOMEVENT

View File

@ -415,6 +415,7 @@ ToMediaKeyMessageType(GMPSessionMessageType aMessageType) {
case kGMPLicenseRequest: return dom::MediaKeyMessageType::License_request;
case kGMPLicenseRenewal: return dom::MediaKeyMessageType::License_renewal;
case kGMPLicenseRelease: return dom::MediaKeyMessageType::License_release;
case kGMPIndividualizationRequest: return dom::MediaKeyMessageType::Individualization_request;
default: return dom::MediaKeyMessageType::License_request;
};
};

View File

@ -28,12 +28,15 @@ MP4Stream::BlockingReadIntoCache(int64_t aOffset, size_t aCount, Monitor* aToUnl
{
MOZ_ASSERT(mPinCount > 0);
CacheBlock block(aOffset, aCount);
if (!block.Init()) {
return false;
}
uint32_t sum = 0;
uint32_t bytesRead = 0;
do {
uint64_t offset = aOffset + sum;
char* buffer = reinterpret_cast<char*>(block.mBuffer.get()) + sum;
char* buffer = block.Buffer() + sum;
uint32_t toRead = aCount - sum;
MonitorAutoUnlock unlock(*aToUnlock);
nsresult rv = mResource->ReadAt(offset, buffer, toRead, &bytesRead);
@ -76,7 +79,7 @@ MP4Stream::CachedReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
// First, check our local cache.
for (size_t i = 0; i < mCache.Length(); ++i) {
if (mCache[i].mOffset == aOffset && mCache[i].mCount >= aCount) {
memcpy(aBuffer, mCache[i].mBuffer, aCount);
memcpy(aBuffer, mCache[i].Buffer(), aCount);
*aBytesRead = aCount;
return true;
}

View File

@ -11,6 +11,7 @@
#include "MediaResource.h"
#include "mozilla/fallible.h"
#include "mozilla/Maybe.h"
#include "mozilla/Monitor.h"
@ -70,10 +71,24 @@ private:
struct CacheBlock {
CacheBlock(int64_t aOffset, size_t aCount)
: mOffset(aOffset), mCount(aCount), mBuffer(new uint8_t[aCount]) {}
: mOffset(aOffset), mCount(aCount), mBuffer(nullptr) {}
int64_t mOffset;
size_t mCount;
nsAutoArrayPtr<uint8_t> mBuffer;
bool Init()
{
mBuffer = new ((fallible_t())) char[mCount];
return !!mBuffer;
}
char* Buffer()
{
MOZ_ASSERT(mBuffer.get());
return mBuffer.get();
}
private:
nsAutoArrayPtr<char> mBuffer;
};
nsTArray<CacheBlock> mCache;
};

View File

@ -1,5 +1,5 @@
Name: fake
Description: Fake GMP Plugin
Version: 1.0
APIs: encode-video[h264], decode-video[h264], eme-decrypt-v3[fake]
APIs: encode-video[h264], decode-video[h264], eme-decrypt-v4[fake]
Libraries: dxva2.dll

View File

@ -72,7 +72,8 @@ enum GMPSessionMessageType {
kGMPLicenseRequest = 0,
kGMPLicenseRenewal = 1,
kGMPLicenseRelease = 2,
kGMPMessageInvalid = 3 // Must always be last.
kGMPIndividualizationRequest = 3,
kGMPMessageInvalid = 4 // Must always be last.
};
// Time in milliseconds, as offset from epoch, 1 Jan 1970.
@ -219,7 +220,7 @@ enum GMPSessionType {
kGMPSessionInvalid = 2 // Must always be last.
};
#define GMP_API_DECRYPTOR "eme-decrypt-v3"
#define GMP_API_DECRYPTOR "eme-decrypt-v4"
// API exposed by plugin library to manage decryption sessions.
// When the Host requests this by calling GMPGetAPIFunc().

View File

@ -41,26 +41,26 @@ public:
explicit GStreamerReader(AbstractMediaDecoder* aDecoder);
virtual ~GStreamerReader();
virtual nsresult Init(MediaDecoderReader* aCloneDonor);
virtual nsresult ResetDecode();
virtual bool DecodeAudioData();
virtual nsresult Init(MediaDecoderReader* aCloneDonor) MOZ_OVERRIDE;
virtual nsresult ResetDecode() MOZ_OVERRIDE;
virtual bool DecodeAudioData() MOZ_OVERRIDE;
virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
int64_t aTimeThreshold);
int64_t aTimeThreshold) MOZ_OVERRIDE;
virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags);
MetadataTags** aTags) MOZ_OVERRIDE;
virtual nsRefPtr<SeekPromise>
Seek(int64_t aTime, int64_t aEndTime) MOZ_OVERRIDE;
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered);
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) MOZ_OVERRIDE;
virtual void NotifyDataArrived(const char *aBuffer,
uint32_t aLength,
int64_t aOffset) MOZ_OVERRIDE;
virtual bool HasAudio() {
virtual bool HasAudio() MOZ_OVERRIDE {
return mInfo.HasAudio();
}
virtual bool HasVideo() {
virtual bool HasVideo() MOZ_OVERRIDE {
return mInfo.HasVideo();
}

View File

@ -231,7 +231,7 @@ protected:
const nsIntRect& aRect) MOZ_OVERRIDE;
#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error);
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) MOZ_OVERRIDE;
#else
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) MOZ_OVERRIDE;
#endif

View File

@ -16,6 +16,6 @@ interface InstallEvent : ExtendableEvent {
// Should be in the spec soon to satisfy conventions about events.
// https://github.com/slightlyoff/ServiceWorker/issues/216.
dictionary InstallEventInit : EventInit {
dictionary InstallEventInit : ExtendableEventInit {
ServiceWorker? activeWorker = null;
};

View File

@ -13,7 +13,8 @@
enum MediaKeyMessageType {
"license-request",
"license-renewal",
"license-release"
"license-release",
"individualization-request"
};
[Pref="media.eme.enabled", Constructor(DOMString type, optional MediaKeyMessageEventInit eventInitDict)]

View File

@ -11,7 +11,9 @@
*/
interface SVGClipPathElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedEnumeration clipPathUnits;
[Constant]
readonly attribute SVGAnimatedTransformList transform;
};

View File

@ -19,11 +19,18 @@ interface SVGComponentTransferFunctionElement : SVGElement {
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_LINEAR = 4;
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_GAMMA = 5;
[Constant]
readonly attribute SVGAnimatedEnumeration type;
[Constant]
readonly attribute SVGAnimatedNumberList tableValues;
[Constant]
readonly attribute SVGAnimatedNumber slope;
[Constant]
readonly attribute SVGAnimatedNumber intercept;
[Constant]
readonly attribute SVGAnimatedNumber amplitude;
[Constant]
readonly attribute SVGAnimatedNumber exponent;
[Constant]
readonly attribute SVGAnimatedNumber offset;
};

View File

@ -10,6 +10,6 @@
interface SVGDocument : Document {
[Throws]
readonly attribute DOMString domain;
[Throws]
[Pure, Throws]
readonly attribute SVGElement? rootElement;
};

View File

@ -15,6 +15,7 @@ interface SVGElement : Element {
/* [SetterThrows]
attribute DOMString xmlbase; */
[Constant]
readonly attribute SVGAnimatedString className;
[PutForwards=cssText, Constant]
readonly attribute CSSStyleDeclaration style;

View File

@ -30,8 +30,11 @@ interface SVGFEBlendElement : SVGElement {
const unsigned short SVG_FEBLEND_MODE_SATURATION = 14;
const unsigned short SVG_FEBLEND_MODE_COLOR = 15;
const unsigned short SVG_FEBLEND_MODE_LUMINOSITY = 16;
[Constant]
readonly attribute SVGAnimatedString in1;
[Constant]
readonly attribute SVGAnimatedString in2;
[Constant]
readonly attribute SVGAnimatedEnumeration mode;
};

View File

@ -19,8 +19,11 @@ interface SVGFEColorMatrixElement : SVGElement {
const unsigned short SVG_FECOLORMATRIX_TYPE_HUEROTATE = 3;
const unsigned short SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA = 4;
[Constant]
readonly attribute SVGAnimatedString in1;
[Constant]
readonly attribute SVGAnimatedEnumeration type;
[Constant]
readonly attribute SVGAnimatedNumberList values;
};

View File

@ -11,6 +11,7 @@
*/
interface SVGFEComponentTransferElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedString in1;
};

View File

@ -21,12 +21,19 @@ interface SVGFECompositeElement : SVGElement {
const unsigned short SVG_FECOMPOSITE_OPERATOR_XOR = 5;
const unsigned short SVG_FECOMPOSITE_OPERATOR_ARITHMETIC = 6;
[Constant]
readonly attribute SVGAnimatedString in1;
[Constant]
readonly attribute SVGAnimatedString in2;
[Constant]
readonly attribute SVGAnimatedEnumeration operator;
[Constant]
readonly attribute SVGAnimatedNumber k1;
[Constant]
readonly attribute SVGAnimatedNumber k2;
[Constant]
readonly attribute SVGAnimatedNumber k3;
[Constant]
readonly attribute SVGAnimatedNumber k4;
};

View File

@ -18,17 +18,29 @@ interface SVGFEConvolveMatrixElement : SVGElement {
const unsigned short SVG_EDGEMODE_WRAP = 2;
const unsigned short SVG_EDGEMODE_NONE = 3;
[Constant]
readonly attribute SVGAnimatedString in1;
[Constant]
readonly attribute SVGAnimatedInteger orderX;
[Constant]
readonly attribute SVGAnimatedInteger orderY;
[Constant]
readonly attribute SVGAnimatedNumberList kernelMatrix;
[Constant]
readonly attribute SVGAnimatedNumber divisor;
[Constant]
readonly attribute SVGAnimatedNumber bias;
[Constant]
readonly attribute SVGAnimatedInteger targetX;
[Constant]
readonly attribute SVGAnimatedInteger targetY;
[Constant]
readonly attribute SVGAnimatedEnumeration edgeMode;
[Constant]
readonly attribute SVGAnimatedNumber kernelUnitLengthX;
[Constant]
readonly attribute SVGAnimatedNumber kernelUnitLengthY;
[Constant]
readonly attribute SVGAnimatedBoolean preserveAlpha;
};

View File

@ -11,10 +11,15 @@
*/
interface SVGFEDiffuseLightingElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedString in1;
[Constant]
readonly attribute SVGAnimatedNumber surfaceScale;
[Constant]
readonly attribute SVGAnimatedNumber diffuseConstant;
[Constant]
readonly attribute SVGAnimatedNumber kernelUnitLengthX;
[Constant]
readonly attribute SVGAnimatedNumber kernelUnitLengthY;
};

View File

@ -19,10 +19,15 @@ interface SVGFEDisplacementMapElement : SVGElement {
const unsigned short SVG_CHANNEL_B = 3;
const unsigned short SVG_CHANNEL_A = 4;
[Constant]
readonly attribute SVGAnimatedString in1;
[Constant]
readonly attribute SVGAnimatedString in2;
[Constant]
readonly attribute SVGAnimatedNumber scale;
[Constant]
readonly attribute SVGAnimatedEnumeration xChannelSelector;
[Constant]
readonly attribute SVGAnimatedEnumeration yChannelSelector;
};

View File

@ -11,6 +11,8 @@
*/
interface SVGFEDistantLightElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedNumber azimuth;
[Constant]
readonly attribute SVGAnimatedNumber elevation;
};

View File

@ -11,10 +11,15 @@
*/
interface SVGFEDropShadowElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedString in1;
[Constant]
readonly attribute SVGAnimatedNumber dx;
[Constant]
readonly attribute SVGAnimatedNumber dy;
[Constant]
readonly attribute SVGAnimatedNumber stdDeviationX;
[Constant]
readonly attribute SVGAnimatedNumber stdDeviationY;
void setStdDeviation(float stdDeviationX, float stdDeviationY);

View File

@ -11,8 +11,11 @@
*/
interface SVGFEGaussianBlurElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedString in1;
[Constant]
readonly attribute SVGAnimatedNumber stdDeviationX;
[Constant]
readonly attribute SVGAnimatedNumber stdDeviationY;
void setStdDeviation(float stdDeviationX, float stdDeviationY);

View File

@ -11,6 +11,7 @@
*/
interface SVGFEImageElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio;
};

View File

@ -11,5 +11,6 @@
*/
interface SVGFEMergeNodeElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedString in1;
};

View File

@ -17,9 +17,13 @@ interface SVGFEMorphologyElement : SVGElement {
const unsigned short SVG_MORPHOLOGY_OPERATOR_ERODE = 1;
const unsigned short SVG_MORPHOLOGY_OPERATOR_DILATE = 2;
[Constant]
readonly attribute SVGAnimatedString in1;
[Constant]
readonly attribute SVGAnimatedEnumeration operator;
[Constant]
readonly attribute SVGAnimatedNumber radiusX;
[Constant]
readonly attribute SVGAnimatedNumber radiusY;
};

View File

@ -11,8 +11,11 @@
*/
interface SVGFEOffsetElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedString in1;
[Constant]
readonly attribute SVGAnimatedNumber dx;
[Constant]
readonly attribute SVGAnimatedNumber dy;
};

View File

@ -11,7 +11,10 @@
*/
interface SVGFEPointLightElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedNumber x;
[Constant]
readonly attribute SVGAnimatedNumber y;
[Constant]
readonly attribute SVGAnimatedNumber z;
};

View File

@ -11,11 +11,17 @@
*/
interface SVGFESpecularLightingElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedString in1;
[Constant]
readonly attribute SVGAnimatedNumber surfaceScale;
[Constant]
readonly attribute SVGAnimatedNumber specularConstant;
[Constant]
readonly attribute SVGAnimatedNumber specularExponent;
[Constant]
readonly attribute SVGAnimatedNumber kernelUnitLengthX;
[Constant]
readonly attribute SVGAnimatedNumber kernelUnitLengthY;
};

View File

@ -11,12 +11,20 @@
*/
interface SVGFESpotLightElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedNumber x;
[Constant]
readonly attribute SVGAnimatedNumber y;
[Constant]
readonly attribute SVGAnimatedNumber z;
[Constant]
readonly attribute SVGAnimatedNumber pointsAtX;
[Constant]
readonly attribute SVGAnimatedNumber pointsAtY;
[Constant]
readonly attribute SVGAnimatedNumber pointsAtZ;
[Constant]
readonly attribute SVGAnimatedNumber specularExponent;
[Constant]
readonly attribute SVGAnimatedNumber limitingConeAngle;
};

View File

@ -11,6 +11,7 @@
*/
interface SVGFETileElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedString in1;
};

View File

@ -22,11 +22,17 @@ interface SVGFETurbulenceElement : SVGElement {
const unsigned short SVG_STITCHTYPE_STITCH = 1;
const unsigned short SVG_STITCHTYPE_NOSTITCH = 2;
[Constant]
readonly attribute SVGAnimatedNumber baseFrequencyX;
[Constant]
readonly attribute SVGAnimatedNumber baseFrequencyY;
[Constant]
readonly attribute SVGAnimatedInteger numOctaves;
[Constant]
readonly attribute SVGAnimatedNumber seed;
[Constant]
readonly attribute SVGAnimatedEnumeration stitchTiles;
[Constant]
readonly attribute SVGAnimatedEnumeration type;
};

View File

@ -11,11 +11,17 @@
*/
interface SVGFilterElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedEnumeration filterUnits;
[Constant]
readonly attribute SVGAnimatedEnumeration primitiveUnits;
[Constant]
readonly attribute SVGAnimatedLength x;
[Constant]
readonly attribute SVGAnimatedLength y;
[Constant]
readonly attribute SVGAnimatedLength width;
[Constant]
readonly attribute SVGAnimatedLength height;
// ImageData apply(ImageData source);

View File

@ -12,9 +12,14 @@
[NoInterfaceObject]
interface SVGFilterPrimitiveStandardAttributes {
[Constant]
readonly attribute SVGAnimatedLength x;
[Constant]
readonly attribute SVGAnimatedLength y;
[Constant]
readonly attribute SVGAnimatedLength width;
[Constant]
readonly attribute SVGAnimatedLength height;
[Constant]
readonly attribute SVGAnimatedString result;
};

View File

@ -18,8 +18,11 @@ interface SVGGradientElement : SVGElement {
const unsigned short SVG_SPREADMETHOD_REFLECT = 2;
const unsigned short SVG_SPREADMETHOD_REPEAT = 3;
[Constant]
readonly attribute SVGAnimatedEnumeration gradientUnits;
[Constant]
readonly attribute SVGAnimatedTransformList gradientTransform;
[Constant]
readonly attribute SVGAnimatedEnumeration spreadMethod;
};

View File

@ -11,8 +11,12 @@
*/
interface SVGLinearGradientElement : SVGGradientElement {
[Constant]
readonly attribute SVGAnimatedLength x1;
[Constant]
readonly attribute SVGAnimatedLength y1;
[Constant]
readonly attribute SVGAnimatedLength x2;
[Constant]
readonly attribute SVGAnimatedLength y2;
};

View File

@ -22,12 +22,19 @@ interface SVGMarkerElement : SVGElement {
const unsigned short SVG_MARKER_ORIENT_AUTO = 1;
const unsigned short SVG_MARKER_ORIENT_ANGLE = 2;
[Constant]
readonly attribute SVGAnimatedLength refX;
[Constant]
readonly attribute SVGAnimatedLength refY;
[Constant]
readonly attribute SVGAnimatedEnumeration markerUnits;
[Constant]
readonly attribute SVGAnimatedLength markerWidth;
[Constant]
readonly attribute SVGAnimatedLength markerHeight;
[Constant]
readonly attribute SVGAnimatedEnumeration orientType;
[Constant]
readonly attribute SVGAnimatedAngle orientAngle;
void setOrientToAuto();

View File

@ -16,11 +16,17 @@ interface SVGMaskElement : SVGElement {
const unsigned short SVG_MASKTYPE_LUMINANCE = 0;
const unsigned short SVG_MASKTYPE_ALPHA = 1;
[Constant]
readonly attribute SVGAnimatedEnumeration maskUnits;
[Constant]
readonly attribute SVGAnimatedEnumeration maskContentUnits;
[Constant]
readonly attribute SVGAnimatedLength x;
[Constant]
readonly attribute SVGAnimatedLength y;
[Constant]
readonly attribute SVGAnimatedLength width;
[Constant]
readonly attribute SVGAnimatedLength height;
};

View File

@ -11,6 +11,7 @@
*/
interface SVGPathElement : SVGGraphicsElement {
[Constant]
readonly attribute SVGAnimatedNumber pathLength;
float getTotalLength();

View File

@ -34,7 +34,9 @@ interface SVGPathSeg {
const unsigned short PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
const unsigned short PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
[Pure]
readonly attribute unsigned short pathSegType;
[Pure]
readonly attribute DOMString pathSegTypeAsLetter;
};

View File

@ -11,10 +11,15 @@
*/
interface SVGRadialGradientElement : SVGGradientElement {
[Constant]
readonly attribute SVGAnimatedLength cx;
[Constant]
readonly attribute SVGAnimatedLength cy;
[Constant]
readonly attribute SVGAnimatedLength r;
[Constant]
readonly attribute SVGAnimatedLength fx;
[Constant]
readonly attribute SVGAnimatedLength fy;
// readonly attribute SVGAnimatedLength fr;
};

View File

@ -14,9 +14,13 @@ interface SVGViewSpec;
interface SVGSVGElement : SVGGraphicsElement {
[Constant]
readonly attribute SVGAnimatedLength x;
[Constant]
readonly attribute SVGAnimatedLength y;
[Constant]
readonly attribute SVGAnimatedLength width;
[Constant]
readonly attribute SVGAnimatedLength height;
// readonly attribute SVGRect viewport;
[Constant]

View File

@ -11,6 +11,7 @@
*/
interface SVGStopElement : SVGElement {
[Constant]
readonly attribute SVGAnimatedNumber offset;
};

View File

@ -17,7 +17,9 @@ interface SVGTextContentElement : SVGGraphicsElement {
const unsigned short LENGTHADJUST_SPACING = 1;
const unsigned short LENGTHADJUST_SPACINGANDGLYPHS = 2;
[Constant]
readonly attribute SVGAnimatedLength textLength;
[Constant]
readonly attribute SVGAnimatedEnumeration lengthAdjust;
long getNumberOfChars();

View File

@ -22,8 +22,11 @@ interface SVGTextPathElement : SVGTextContentElement {
const unsigned short TEXTPATH_SPACINGTYPE_AUTO = 1;
const unsigned short TEXTPATH_SPACINGTYPE_EXACT = 2;
[Constant]
readonly attribute SVGAnimatedLength startOffset;
[Constant]
readonly attribute SVGAnimatedEnumeration method;
[Constant]
readonly attribute SVGAnimatedEnumeration spacing;
};

View File

@ -11,10 +11,15 @@
*/
interface SVGTextPositioningElement : SVGTextContentElement {
[Constant]
readonly attribute SVGAnimatedLengthList x;
[Constant]
readonly attribute SVGAnimatedLengthList y;
[Constant]
readonly attribute SVGAnimatedLengthList dx;
[Constant]
readonly attribute SVGAnimatedLengthList dy;
[Constant]
readonly attribute SVGAnimatedNumberList rotate;
};

View File

@ -12,6 +12,7 @@
[NoInterfaceObject]
interface SVGURIReference {
[Constant]
readonly attribute SVGAnimatedString href;
};

View File

@ -56,7 +56,10 @@ ServiceWorkerContainer::RemoveReadyPromise()
if (window) {
nsCOMPtr<nsIServiceWorkerManager> swm =
mozilla::services::GetServiceWorkerManager();
MOZ_ASSERT(swm);
if (!swm) {
// If the browser is shutting down, we don't need to remove the promise.
return;
}
swm->RemoveReadyPromise(window);
}

View File

@ -69,6 +69,11 @@ public:
nsRefPtr<Promise> p = mPromise;
return p.forget();
}
virtual ExtendableEvent* AsExtendableEvent() MOZ_OVERRIDE
{
return this;
}
};
class InstallEvent MOZ_FINAL : public ExtendableEvent
@ -132,6 +137,11 @@ public:
{
return mActivateImmediately;
}
InstallEvent* AsInstallEvent() MOZ_OVERRIDE
{
return this;
}
};
END_WORKERS_NAMESPACE

View File

@ -106,26 +106,6 @@ ServiceWorkerRegistrationInfo::~ServiceWorkerRegistrationInfo()
}
}
class QueueFireUpdateFoundRunnable MOZ_FINAL : public nsRunnable
{
nsRefPtr<ServiceWorkerRegistrationInfo> mRegistration;
public:
explicit QueueFireUpdateFoundRunnable(ServiceWorkerRegistrationInfo* aReg)
: mRegistration(aReg)
{
MOZ_ASSERT(aReg);
}
NS_IMETHOD
Run()
{
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->FireEventOnServiceWorkerRegistrations(mRegistration,
NS_LITERAL_STRING("updatefound"));
return NS_OK;
}
};
//////////////////////////
// ServiceWorkerManager //
//////////////////////////
@ -163,17 +143,60 @@ ServiceWorkerManager::CleanupServiceWorkerInformation(const nsACString& aDomain,
class ServiceWorkerRegisterJob;
class FinishInstallRunnable MOZ_FINAL : public nsRunnable
class ContinueLifecycleTask : public nsISupports
{
nsMainThreadPtrHandle<nsISupports> mJob;
NS_DECL_ISUPPORTS
protected:
virtual ~ContinueLifecycleTask()
{ }
public:
virtual void ContinueAfterWorkerEvent(bool aSuccess,
bool aActivateImmediately) = 0;
};
NS_IMPL_ISUPPORTS0(ContinueLifecycleTask);
class ContinueInstallTask MOZ_FINAL : public ContinueLifecycleTask
{
nsRefPtr<ServiceWorkerRegisterJob> mJob;
public:
explicit ContinueInstallTask(ServiceWorkerRegisterJob* aJob)
: mJob(aJob)
{ }
void ContinueAfterWorkerEvent(bool aSuccess, bool aActivateImmediately) MOZ_OVERRIDE;
};
class ContinueActivateTask MOZ_FINAL : public ContinueLifecycleTask
{
nsRefPtr<ServiceWorkerRegistrationInfo> mRegistration;
public:
explicit ContinueActivateTask(ServiceWorkerRegistrationInfo* aReg)
: mRegistration(aReg)
{ }
void
ContinueAfterWorkerEvent(bool aSuccess, bool aActivateImmediately /* unused */) MOZ_OVERRIDE
{
mRegistration->FinishActivate(aSuccess);
}
};
class ContinueLifecycleRunnable MOZ_FINAL : public nsRunnable
{
nsMainThreadPtrHandle<ContinueLifecycleTask> mTask;
bool mSuccess;
bool mActivateImmediately;
public:
explicit FinishInstallRunnable(const nsMainThreadPtrHandle<nsISupports>& aJob,
bool aSuccess,
bool aActivateImmediately)
: mJob(aJob)
ContinueLifecycleRunnable(const nsMainThreadPtrHandle<ContinueLifecycleTask>& aTask,
bool aSuccess,
bool aActivateImmediately)
: mTask(aTask)
, mSuccess(aSuccess)
, mActivateImmediately(aActivateImmediately)
{
@ -181,7 +204,12 @@ public:
}
NS_IMETHOD
Run() MOZ_OVERRIDE;
Run() MOZ_OVERRIDE
{
AssertIsOnMainThread();
mTask->ContinueAfterWorkerEvent(mSuccess, mActivateImmediately);
return NS_OK;
}
};
/*
@ -190,33 +218,33 @@ public:
* ServiceWorkers, so the parent thread -> worker thread requirement for
* runnables is satisfied.
*/
class InstallEventRunnable MOZ_FINAL : public WorkerRunnable
class LifecycleEventWorkerRunnable MOZ_FINAL : public WorkerRunnable
{
nsMainThreadPtrHandle<nsISupports> mJob;
nsCString mScope;
nsString mEventName;
nsMainThreadPtrHandle<ContinueLifecycleTask> mTask;
public:
InstallEventRunnable(WorkerPrivate* aWorkerPrivate,
const nsMainThreadPtrHandle<nsISupports>& aJob,
const nsCString& aScope)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
mJob(aJob),
mScope(aScope)
LifecycleEventWorkerRunnable(WorkerPrivate* aWorkerPrivate,
const nsString& aEventName,
const nsMainThreadPtrHandle<ContinueLifecycleTask>& aTask)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount)
, mEventName(aEventName)
, mTask(aTask)
{
AssertIsOnMainThread();
MOZ_ASSERT(aWorkerPrivate);
}
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) MOZ_OVERRIDE
{
MOZ_ASSERT(aWorkerPrivate);
return DispatchInstallEvent(aCx, aWorkerPrivate);
return DispatchLifecycleEvent(aCx, aWorkerPrivate);
}
private:
bool
DispatchInstallEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
DispatchLifecycleEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
};
@ -356,7 +384,7 @@ public:
class ServiceWorkerRegisterJob MOZ_FINAL : public ServiceWorkerJob,
public nsIStreamLoaderObserver
{
friend class FinishInstallRunnable;
friend class ContinueInstallTask;
nsCString mScope;
nsCString mScriptSpec;
@ -504,8 +532,7 @@ public:
{
MOZ_ASSERT(mCallback);
mCallback->UpdateFailed(aError);
mCallback = nullptr;
Done(NS_ERROR_DOM_JS_EXCEPTION);
FailCommon(NS_ERROR_DOM_JS_EXCEPTION);
}
// Public so our error handling code can continue with a successful worker.
@ -531,15 +558,14 @@ public:
Succeed();
nsRefPtr<QueueFireUpdateFoundRunnable> upr =
new QueueFireUpdateFoundRunnable(mRegistration);
nsCOMPtr<nsIRunnable> upr =
NS_NewRunnableMethodWithArg<ServiceWorkerRegistrationInfo*>(swm,
&ServiceWorkerManager::FireUpdateFound,
mRegistration);
NS_DispatchToMainThread(upr);
// XXXnsm this leads to double fetches right now, ideally we'll be able to
// use the persistent cache later.
nsRefPtr<ServiceWorkerJob> upcasted = this;
nsMainThreadPtrHandle<nsISupports> handle(
new nsMainThreadPtrHolder<nsISupports>(upcasted));
nsMainThreadPtrHandle<ContinueLifecycleTask> handle(
new nsMainThreadPtrHolder<ContinueLifecycleTask>(new ContinueInstallTask(this)));
nsRefPtr<ServiceWorker> serviceWorker;
nsresult rv =
@ -552,8 +578,8 @@ public:
return;
}
nsRefPtr<InstallEventRunnable> r =
new InstallEventRunnable(serviceWorker->GetWorkerPrivate(), handle, mRegistration->mScope);
nsRefPtr<LifecycleEventWorkerRunnable> r =
new LifecycleEventWorkerRunnable(serviceWorker->GetWorkerPrivate(), NS_LITERAL_STRING("install"), handle);
AutoJSAPI jsapi;
jsapi.Init();
@ -634,16 +660,39 @@ private:
mCallback = nullptr;
}
void
FailCommon(nsresult aRv)
{
mCallback = nullptr;
MaybeRemoveRegistration();
// Ensures that the job can't do anything useful from this point on.
mRegistration = nullptr;
Done(aRv);
}
// This MUST only be called when the job is still performing actions related
// to registration or update. After the spec resolves the update promise, use
// Done() with the failure code instead.
void
Fail(nsresult rv)
Fail(nsresult aRv)
{
MOZ_ASSERT(mCallback);
mCallback->UpdateFailed(rv);
mCallback = nullptr;
Done(rv);
mCallback->UpdateFailed(aRv);
FailCommon(aRv);
}
void
MaybeRemoveRegistration()
{
MOZ_ASSERT(mRegistration);
nsRefPtr<ServiceWorkerInfo> newest = mRegistration->Newest();
if (!newest) {
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
nsRefPtr<ServiceWorkerManager::ServiceWorkerDomainInfo> domainInfo =
swm->GetDomainInfo(mRegistration->mScope);
MOZ_ASSERT(domainInfo);
domainInfo->RemoveRegistration(mRegistration);
}
}
void
@ -666,6 +715,7 @@ private:
mRegistration->mInstallingWorker = nullptr;
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
WhichServiceWorker::INSTALLING_WORKER);
MaybeRemoveRegistration();
return Done(NS_ERROR_DOM_ABORT_ERR);
}
@ -705,6 +755,12 @@ ContinueUpdateRunnable::Run()
return NS_OK;
}
void
ContinueInstallTask::ContinueAfterWorkerEvent(bool aSuccess, bool aActivateImmediately)
{
mJob->ContinueAfterInstallEvent(aSuccess, aActivateImmediately);
}
// If we return an error code here, the ServiceWorkerContainer will
// automatically reject the Promise.
NS_IMETHODIMP
@ -853,33 +909,23 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow,
return NS_OK;
}
NS_IMETHODIMP
FinishInstallRunnable::Run()
{
AssertIsOnMainThread();
nsRefPtr<ServiceWorkerJob> job = static_cast<ServiceWorkerJob*>(mJob.get());
nsRefPtr<ServiceWorkerRegisterJob> upjob = static_cast<ServiceWorkerRegisterJob*>(job.get());
MOZ_ASSERT(upjob);
upjob->ContinueAfterInstallEvent(mSuccess, mActivateImmediately);
return NS_OK;
}
/*
* Used to handle InstallEvent::waitUntil() and proceed with installation.
* Used to handle ExtendableEvent::waitUntil() and proceed with
* installation/activation.
*/
class FinishInstallHandler MOZ_FINAL : public PromiseNativeHandler
class LifecycleEventPromiseHandler MOZ_FINAL : public PromiseNativeHandler
{
nsMainThreadPtrHandle<nsISupports> mJob;
nsMainThreadPtrHandle<ContinueLifecycleTask> mTask;
bool mActivateImmediately;
virtual
~FinishInstallHandler()
~LifecycleEventPromiseHandler()
{ }
public:
FinishInstallHandler(const nsMainThreadPtrHandle<nsISupports>& aJob,
bool aActivateImmediately)
: mJob(aJob)
LifecycleEventPromiseHandler(const nsMainThreadPtrHandle<ContinueLifecycleTask>& aTask,
bool aActivateImmediately)
: mTask(aTask)
, mActivateImmediately(aActivateImmediately)
{
MOZ_ASSERT(!NS_IsMainThread());
@ -892,33 +938,47 @@ public:
MOZ_ASSERT(workerPrivate);
workerPrivate->AssertIsOnWorkerThread();
nsRefPtr<FinishInstallRunnable> r = new FinishInstallRunnable(mJob, true, mActivateImmediately);
nsRefPtr<ContinueLifecycleRunnable> r =
new ContinueLifecycleRunnable(mTask, true /* success */, mActivateImmediately);
NS_DispatchToMainThread(r);
}
void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) MOZ_OVERRIDE
{
nsRefPtr<FinishInstallRunnable> r = new FinishInstallRunnable(mJob, false, mActivateImmediately);
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
workerPrivate->AssertIsOnWorkerThread();
nsRefPtr<ContinueLifecycleRunnable> r =
new ContinueLifecycleRunnable(mTask, false /* success */, mActivateImmediately);
NS_DispatchToMainThread(r);
}
};
bool
InstallEventRunnable::DispatchInstallEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
LifecycleEventWorkerRunnable::DispatchLifecycleEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
aWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(aWorkerPrivate->IsServiceWorker());
InstallEventInit init;
init.mBubbles = false;
init.mCancelable = true;
// FIXME(nsm): Bug 982787 pass previous active worker.
// FIXME(nsm): Set error handler so we can grab handler errors.
nsRefPtr<ExtendableEvent> event;
nsRefPtr<EventTarget> target = aWorkerPrivate->GlobalScope();
nsRefPtr<InstallEvent> event =
InstallEvent::Constructor(target, NS_LITERAL_STRING("install"), init);
if (mEventName.EqualsASCII("install")) {
// FIXME(nsm): Bug 982787 pass previous active worker.
InstallEventInit init;
init.mBubbles = false;
init.mCancelable = true;
event = InstallEvent::Constructor(target, mEventName, init);
} else if (mEventName.EqualsASCII("activate")) {
ExtendableEventInit init;
init.mBubbles = false;
init.mCancelable = true;
event = ExtendableEvent::Constructor(target, mEventName, init);
} else {
MOZ_CRASH("Unexpected lifecycle event");
}
event->SetTrusted(true);
@ -952,135 +1012,21 @@ InstallEventRunnable::DispatchInstallEvent(JSContext* aCx, WorkerPrivate* aWorke
return false;
}
nsRefPtr<FinishInstallHandler> handler =
new FinishInstallHandler(mJob, event->ActivateImmediately());
// activateimmediately is only relevant to "install" event.
bool activateImmediately = false;
InstallEvent* installEvent = event->AsInstallEvent();
if (installEvent) {
activateImmediately = installEvent->ActivateImmediately();
// FIXME(nsm): Set activeWorker to the correct thing.
// FIXME(nsm): Install error handler for any listener errors.
}
nsRefPtr<LifecycleEventPromiseHandler> handler =
new LifecycleEventPromiseHandler(mTask, activateImmediately);
waitUntilPromise->AppendNativeHandler(handler);
return true;
}
class FinishActivationRunnable MOZ_FINAL : public nsRunnable
{
bool mSuccess;
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
public:
FinishActivationRunnable(bool aSuccess,
const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
: mSuccess(aSuccess)
, mRegistration(aRegistration)
{
MOZ_ASSERT(!NS_IsMainThread());
}
NS_IMETHODIMP
Run()
{
AssertIsOnMainThread();
mRegistration->FinishActivate(mSuccess);
return NS_OK;
}
};
class FinishActivateHandler MOZ_FINAL : public PromiseNativeHandler
{
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
public:
explicit FinishActivateHandler(const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
: mRegistration(aRegistration)
{
MOZ_ASSERT(!NS_IsMainThread());
}
virtual
~FinishActivateHandler()
{ }
void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) MOZ_OVERRIDE
{
nsRefPtr<FinishActivationRunnable> r = new FinishActivationRunnable(true /* success */, mRegistration);
NS_DispatchToMainThread(r);
}
void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) MOZ_OVERRIDE
{
nsRefPtr<FinishActivationRunnable> r = new FinishActivationRunnable(false /* success */, mRegistration);
NS_DispatchToMainThread(r);
}
};
class ActivateEventRunnable : public WorkerRunnable
{
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> mRegistration;
public:
ActivateEventRunnable(WorkerPrivate* aWorkerPrivate,
const nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
mRegistration(aRegistration)
{
MOZ_ASSERT(aWorkerPrivate);
}
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
MOZ_ASSERT(aWorkerPrivate);
return DispatchActivateEvent(aCx, aWorkerPrivate);
}
private:
bool
DispatchActivateEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
MOZ_ASSERT(aWorkerPrivate->IsServiceWorker());
nsRefPtr<EventTarget> target = do_QueryObject(aWorkerPrivate->GlobalScope());
// FIXME(nsm): Set activeWorker to the correct thing.
EventInit init;
init.mBubbles = false;
init.mCancelable = true;
nsRefPtr<ExtendableEvent> event =
ExtendableEvent::Constructor(target, NS_LITERAL_STRING("activate"), init);
event->SetTrusted(true);
nsRefPtr<Promise> waitUntilPromise;
// FIXME(nsm): Install error handler for any listener errors.
ErrorResult result;
result = target->DispatchDOMEvent(nullptr, event, nullptr, nullptr);
WidgetEvent* internalEvent = event->GetInternalNSEvent();
if (!result.Failed() && !internalEvent->mFlags.mExceptionHasBeenRisen) {
waitUntilPromise = event->GetPromise();
if (!waitUntilPromise) {
nsCOMPtr<nsIGlobalObject> global =
do_QueryObject(aWorkerPrivate->GlobalScope());
waitUntilPromise =
Promise::Resolve(global,
aCx, JS::UndefinedHandleValue, result);
}
} else {
nsCOMPtr<nsIGlobalObject> global =
do_QueryObject(aWorkerPrivate->GlobalScope());
// Continue with a canceled install.
waitUntilPromise = Promise::Reject(global, aCx,
JS::UndefinedHandleValue, result);
}
if (result.Failed()) {
return false;
}
nsRefPtr<FinishActivateHandler> handler = new FinishActivateHandler(mRegistration);
waitUntilPromise->AppendNativeHandler(handler);
return true;
}
};
void
ServiceWorkerRegistrationInfo::TryToActivate()
{
@ -1138,11 +1084,11 @@ ServiceWorkerRegistrationInfo::Activate()
return;
}
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> handle(
new nsMainThreadPtrHolder<ServiceWorkerRegistrationInfo>(this));
nsMainThreadPtrHandle<ContinueLifecycleTask> handle(
new nsMainThreadPtrHolder<ContinueLifecycleTask>(new ContinueActivateTask(this)));
nsRefPtr<ActivateEventRunnable> r =
new ActivateEventRunnable(serviceWorker->GetWorkerPrivate(), handle);
nsRefPtr<LifecycleEventWorkerRunnable> r =
new LifecycleEventWorkerRunnable(serviceWorker->GetWorkerPrivate(), NS_LITERAL_STRING("activate"), handle);
AutoJSAPI jsapi;
jsapi.Init();
@ -1475,6 +1421,90 @@ ServiceWorkerManager::CheckReadyPromise(nsPIDOMWindow* aWindow,
return false;
}
class ServiceWorkerUnregisterJob MOZ_FINAL : public ServiceWorkerJob
{
nsRefPtr<ServiceWorkerRegistrationInfo> mRegistration;
const nsCString mScope;
nsCOMPtr<nsIServiceWorkerUnregisterCallback> mCallback;
~ServiceWorkerUnregisterJob()
{ }
public:
ServiceWorkerUnregisterJob(ServiceWorkerJobQueue* aQueue,
const nsACString& aScope,
nsIServiceWorkerUnregisterCallback* aCallback)
: ServiceWorkerJob(aQueue)
, mScope(aScope)
, mCallback(aCallback)
{
AssertIsOnMainThread();
}
void
Start() MOZ_OVERRIDE
{
AssertIsOnMainThread();
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableMethod(this, &ServiceWorkerUnregisterJob::UnregisterAndDone);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(r)));
}
private:
// You probably want UnregisterAndDone().
nsresult
Unregister()
{
AssertIsOnMainThread();
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
nsRefPtr<ServiceWorkerManager::ServiceWorkerDomainInfo> domainInfo =
swm->GetDomainInfo(mScope);
MOZ_ASSERT(domainInfo);
// "Let registration be the result of running [[Get Registration]]
// algorithm passing scope as the argument."
nsRefPtr<ServiceWorkerRegistrationInfo> registration;
if (!domainInfo->mServiceWorkerRegistrationInfos.Get(mScope,
getter_AddRefs(registration))) {
// "If registration is null, then, resolve promise with false."
return mCallback->UnregisterSucceeded(false);
}
MOZ_ASSERT(registration);
// "Set registration's uninstalling flag."
registration->mPendingUninstall = true;
// "Resolve promise with true"
nsresult rv = mCallback->UnregisterSucceeded(true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// "If no service worker client is using registration..."
if (!registration->IsControllingDocuments()) {
// "If registration's uninstalling flag is set.."
if (!registration->mPendingUninstall) {
return NS_OK;
}
// "Invoke [[Clear Registration]]..."
registration->Clear();
domainInfo->RemoveRegistration(registration);
}
return NS_OK;
}
// The unregister job is done irrespective of success or failure of any sort.
void
UnregisterAndDone()
{
Done(Unregister());
}
};
NS_IMETHODIMP
ServiceWorkerManager::Unregister(nsIServiceWorkerUnregisterCallback* aCallback,
const nsAString& aScope)
@ -1482,78 +1512,26 @@ ServiceWorkerManager::Unregister(nsIServiceWorkerUnregisterCallback* aCallback,
AssertIsOnMainThread();
MOZ_ASSERT(aCallback);
// This is not accessible by content, and callers should always ensure scope is
// a correct URI, so this is wrapped in DEBUG
#ifdef DEBUG
nsCOMPtr<nsIURI> scopeURI;
nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), aScope, nullptr, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_DOM_SECURITY_ERR;
}
#endif
/*
* Implements the async aspects of the unregister algorithm.
*/
class UnregisterRunnable : public nsRunnable
{
nsCOMPtr<nsIServiceWorkerUnregisterCallback> mCallback;
nsCOMPtr<nsIURI> mScopeURI;
NS_ConvertUTF16toUTF8 scope(aScope);
nsRefPtr<ServiceWorkerManager::ServiceWorkerDomainInfo> domainInfo =
GetDomainInfo(scope);
ServiceWorkerJobQueue* queue = domainInfo->GetOrCreateJobQueue(scope);
MOZ_ASSERT(queue);
public:
UnregisterRunnable(nsIServiceWorkerUnregisterCallback* aCallback,
nsIURI* aScopeURI)
: mCallback(aCallback), mScopeURI(aScopeURI)
{
AssertIsOnMainThread();
}
NS_IMETHODIMP
Run()
{
AssertIsOnMainThread();
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
nsRefPtr<ServiceWorkerManager::ServiceWorkerDomainInfo> domainInfo =
swm->GetDomainInfo(mScopeURI);
MOZ_ASSERT(domainInfo);
nsCString spec;
nsresult rv = mScopeURI->GetSpecIgnoringRef(spec);
if (NS_WARN_IF(NS_FAILED(rv))) {
return mCallback->UnregisterFailed();
}
nsRefPtr<ServiceWorkerRegistrationInfo> registration;
if (!domainInfo->mServiceWorkerRegistrationInfos.Get(spec,
getter_AddRefs(registration))) {
return mCallback->UnregisterSucceeded(false);
}
MOZ_ASSERT(registration);
registration->mPendingUninstall = true;
rv = mCallback->UnregisterSucceeded(true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// The "Wait until no document is using registration" can actually be
// handled by [[HandleDocumentUnload]] in Bug 1041340, so we simply check
// if the document is currently in use here.
if (!registration->IsControllingDocuments()) {
if (!registration->mPendingUninstall) {
return NS_OK;
}
registration->Clear();
domainInfo->RemoveRegistration(registration);
}
return NS_OK;
}
};
nsRefPtr<nsIRunnable> unregisterRunnable =
new UnregisterRunnable(aCallback, scopeURI);
return NS_DispatchToCurrentThread(unregisterRunnable);
nsRefPtr<ServiceWorkerUnregisterJob> job =
new ServiceWorkerUnregisterJob(queue, scope, aCallback);
queue->Append(job);
return NS_OK;
}
/* static */
@ -2247,8 +2225,8 @@ ServiceWorkerManager::Update(const nsAString& aScope)
nsRefPtr<ServiceWorkerUpdateFinishCallback> cb =
new ServiceWorkerUpdateFinishCallback();
nsRefPtr<ServiceWorkerRegisterJob> job
= new ServiceWorkerRegisterJob(queue, registration, cb);
nsRefPtr<ServiceWorkerRegisterJob> job =
new ServiceWorkerRegisterJob(queue, registration, cb);
queue->Append(job);
return NS_OK;
}

View File

@ -275,7 +275,7 @@ class ServiceWorkerManager MOZ_FINAL : public nsIServiceWorkerManager
friend class GetRegistrationsRunnable;
friend class GetRegistrationRunnable;
friend class QueueFireUpdateFoundRunnable;
friend class UnregisterRunnable;
friend class ServiceWorkerUnregisterJob;
public:
NS_DECL_ISUPPORTS
@ -461,6 +461,13 @@ private:
FireEventOnServiceWorkerRegistrations(ServiceWorkerRegistrationInfo* aRegistration,
const nsAString& aName);
void
FireUpdateFound(ServiceWorkerRegistrationInfo* aRegistration)
{
FireEventOnServiceWorkerRegistrations(aRegistration,
NS_LITERAL_STRING("updatefound"));
}
void
FireControllerChange(ServiceWorkerRegistrationInfo* aRegistration);

View File

@ -164,6 +164,7 @@ ServiceWorkerRegistration::Unregister(ErrorResult& aRv)
nsCOMPtr<nsIURI> scopeURI;
nsCOMPtr<nsIURI> baseURI = document->GetBaseURI();
// "If the origin of scope is not client's origin..."
nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), mScope, nullptr, baseURI);
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
@ -179,7 +180,7 @@ ServiceWorkerRegistration::Unregister(ErrorResult& aRv)
}
nsAutoCString uriSpec;
aRv = scopeURI->GetSpec(uriSpec);
aRv = scopeURI->GetSpecIgnoringRef(uriSpec);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}

View File

@ -27,7 +27,6 @@ skip-if = true # bug 1094375
[test_install_event.html]
[test_navigator.html]
[test_scopes.html]
skip-if = true # bug 1124743
[test_controller.html]
[test_workerUpdate.html]
skip-if = true # Enable after Bug 982726 postMessage is landed.

View File

@ -106,6 +106,10 @@
var p = navigator.serviceWorker.register("parse_error_worker.js", { scope: "parse_error/" });
return p.then(function(wr) {
ok(false, "Registration should fail with parse error");
return navigator.serviceWorker.getRegistration("parse_error/").then(function(swr) {
// See https://github.com/slightlyoff/ServiceWorker/issues/547
is(swr, undefined, "A failed registration for a scope with no prior controllers should clear itself");
});
}, function(e) {
info("NSM " + e.name);
ok(e instanceof Error, "Registration should fail with parse error");

View File

@ -86,25 +86,9 @@
function runTest() {
simpleRegister()
.then(function(v) {
info("simpleRegister() promise resolved");
})
.then(testControlled)
.then(function(v) {
info("testControlled() promise resolved");
}, function(e) {
info("testControlled() promise rejected " + e);
})
.then(unregister)
.then(function(v) {
info("unregister() promise resolved");
})
.then(testUncontrolled)
.then(function(v) {
info("testUncontrolled() promise resolved");
}, function(e) {
info("testUncontrolled() promise rejected " + e);
})
.then(function() {
SimpleTest.finish();
}).catch(function(e) {

View File

@ -459,7 +459,7 @@ public:
/**
* This function waits until the buffer is no longer being used.
*/
virtual void WaitForBufferOwnership() {}
virtual void WaitForBufferOwnership(bool aWaitReleaseFence = true) {}
/**
* Track how much of this texture is wasted.

View File

@ -88,13 +88,17 @@ GrallocTextureClientOGL::SetRemoveFromCompositableTracker(AsyncTransactionTracke
}
void
GrallocTextureClientOGL::WaitForBufferOwnership()
GrallocTextureClientOGL::WaitForBufferOwnership(bool aWaitReleaseFence)
{
if (mRemoveFromCompositableTracker) {
mRemoveFromCompositableTracker->WaitComplete();
mRemoveFromCompositableTracker = nullptr;
}
if (!aWaitReleaseFence) {
return;
}
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
if (mReleaseFenceHandle.IsValid()) {
android::sp<Fence> fence = mReleaseFenceHandle.mFence;
@ -122,7 +126,11 @@ GrallocTextureClientOGL::Lock(OpenMode aMode)
return true;
}
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
WaitForBufferOwnership(false /* aWaitReleaseFence */);
#else
WaitForBufferOwnership();
#endif
uint32_t usage = 0;
if (aMode & OpenMode::OPEN_READ) {
@ -131,7 +139,19 @@ GrallocTextureClientOGL::Lock(OpenMode aMode)
if (aMode & OpenMode::OPEN_WRITE) {
usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
}
int32_t rv = mGraphicBuffer->lock(usage, reinterpret_cast<void**>(&mMappedBuffer));
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
android::sp<Fence> fence = android::Fence::NO_FENCE;
if (mReleaseFenceHandle.IsValid()) {
fence = mReleaseFenceHandle.mFence;
}
mReleaseFenceHandle = FenceHandle();
int32_t rv = mGraphicBuffer->lockAsync(usage,
reinterpret_cast<void**>(&mMappedBuffer),
fence->dup());
#else
int32_t rv = mGraphicBuffer->lock(usage,
reinterpret_cast<void**>(&mMappedBuffer));
#endif
if (rv) {
mMappedBuffer = nullptr;
NS_WARNING("Couldn't lock graphic buffer");

View File

@ -58,7 +58,7 @@ public:
virtual void SetRemoveFromCompositableTracker(AsyncTransactionTracker* aTracker) MOZ_OVERRIDE;
virtual void WaitForBufferOwnership() MOZ_OVERRIDE;
virtual void WaitForBufferOwnership(bool aWaitReleaseFence = true) MOZ_OVERRIDE;
void InitWith(MaybeMagicGrallocBufferHandle aDesc, gfx::IntSize aSize);

View File

@ -27,7 +27,19 @@ MacIOSurfaceTextureHostOGL::Lock()
}
if (!mTextureSource) {
mTextureSource = new MacIOSurfaceTextureSourceOGL(mCompositor, mSurface);
GLuint textureHandle;
gl::GLContext* gl = mCompositor->gl();
gl->fGenTextures(1, &textureHandle);
gl->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, textureHandle);
gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
mSurface->CGLTexImageIOSurface2D(gl::GLContextCGL::Cast(gl)->GetCGLContext());
mTextureSource = new GLTextureSource(mCompositor, textureHandle, LOCAL_GL_TEXTURE_RECTANGLE_ARB,
gfx::IntSize(mSurface->GetDevicePixelWidth(),
mSurface->GetDevicePixelHeight()),
mSurface->HasAlpha() ? gfx::SurfaceFormat::R8G8B8A8:
gfx::SurfaceFormat::R8G8B8X8);
}
return true;
}

View File

@ -94,7 +94,7 @@ public:
protected:
RefPtr<CompositorOGL> mCompositor;
RefPtr<MacIOSurfaceTextureSourceOGL> mTextureSource;
RefPtr<GLTextureSource> mTextureSource;
RefPtr<MacIOSurface> mSurface;
};

View File

@ -205,8 +205,8 @@ public:
cairo_font_face_destroy(mFontFace);
}
virtual void ForgetHBFace();
virtual void ReleaseGrFace(gr_face* aFace);
virtual void ForgetHBFace() MOZ_OVERRIDE;
virtual void ReleaseGrFace(gr_face* aFace) MOZ_OVERRIDE;
protected:
virtual nsresult
@ -671,12 +671,12 @@ public:
// return a cloned font resized and offset to simulate sub/superscript glyphs
virtual already_AddRefed<gfxFont>
GetSubSuperscriptFont(int32_t aAppUnitsPerDevPixel);
GetSubSuperscriptFont(int32_t aAppUnitsPerDevPixel) MOZ_OVERRIDE;
protected:
virtual already_AddRefed<gfxFont> MakeScaledFont(gfxFontStyle *aFontStyle,
gfxFloat aFontScale);
virtual already_AddRefed<gfxFont> GetSmallCapsFont();
virtual already_AddRefed<gfxFont> GetSmallCapsFont() MOZ_OVERRIDE;
private:
gfxFcFont(cairo_scaled_font_t *aCairoFont, gfxFcFontEntry *aFontEntry,

View File

@ -169,7 +169,7 @@ public:
explicit CrashStatsLogForwarder(const char* aKey);
virtual void Log(const std::string& aString) MOZ_OVERRIDE;
virtual std::vector<std::pair<int32_t,std::string> > StringsVectorCopy();
virtual std::vector<std::pair<int32_t,std::string> > StringsVectorCopy() MOZ_OVERRIDE;
void SetCircularBufferSize(uint32_t aCapacity);

View File

@ -15,10 +15,228 @@
#include <math.h>
#include "jspubtd.h"
#include "js/RootingAPI.h"
#include "js/Value.h"
struct JSContext;
namespace js {
/* DO NOT CALL THIS. Use JS::ToBoolean. */
extern JS_PUBLIC_API(bool)
ToBooleanSlow(JS::HandleValue v);
/* DO NOT CALL THIS. Use JS::ToNumber. */
extern JS_PUBLIC_API(bool)
ToNumberSlow(JSContext *cx, JS::Value v, double *dp);
/* DO NOT CALL THIS. Use JS::ToInt32. */
extern JS_PUBLIC_API(bool)
ToInt32Slow(JSContext *cx, JS::HandleValue v, int32_t *out);
/* DO NOT CALL THIS. Use JS::ToUint32. */
extern JS_PUBLIC_API(bool)
ToUint32Slow(JSContext *cx, JS::HandleValue v, uint32_t *out);
/* DO NOT CALL THIS. Use JS::ToUint16. */
extern JS_PUBLIC_API(bool)
ToUint16Slow(JSContext *cx, JS::HandleValue v, uint16_t *out);
/* DO NOT CALL THIS. Use JS::ToInt64. */
extern JS_PUBLIC_API(bool)
ToInt64Slow(JSContext *cx, JS::HandleValue v, int64_t *out);
/* DO NOT CALL THIS. Use JS::ToUint64. */
extern JS_PUBLIC_API(bool)
ToUint64Slow(JSContext *cx, JS::HandleValue v, uint64_t *out);
/* DO NOT CALL THIS. Use JS::ToString. */
extern JS_PUBLIC_API(JSString*)
ToStringSlow(JSContext *cx, JS::HandleValue v);
/* DO NOT CALL THIS. Use JS::ToObject. */
extern JS_PUBLIC_API(JSObject*)
ToObjectSlow(JSContext *cx, JS::HandleValue v, bool reportScanStack);
} // namespace js
namespace JS {
namespace detail {
#ifdef JS_DEBUG
/*
* Assert that we're not doing GC on cx, that we're in a request as
* needed, and that the compartments for cx and v are correct.
* Also check that GC would be safe at this point.
*/
extern JS_PUBLIC_API(void)
AssertArgumentsAreSane(JSContext *cx, HandleValue v);
#else
inline void AssertArgumentsAreSane(JSContext *cx, HandleValue v)
{}
#endif /* JS_DEBUG */
} // namespace detail
/*
* ES6 draft 20141224, 7.1.1, second algorithm.
*
* Most users shouldn't call this -- use JS::ToBoolean, ToNumber, or ToString
* instead. This will typically only be called from custom convert hooks that
* wish to fall back to the ES6 default conversion behavior shared by most
* objects in JS, codified as OrdinaryToPrimitive.
*/
extern JS_PUBLIC_API(bool)
OrdinaryToPrimitive(JSContext *cx, HandleObject obj, JSType type, MutableHandleValue vp);
/* ES6 draft 20141224, 7.1.2. */
MOZ_ALWAYS_INLINE bool
ToBoolean(HandleValue v)
{
if (v.isBoolean())
return v.toBoolean();
if (v.isInt32())
return v.toInt32() != 0;
if (v.isNullOrUndefined())
return false;
if (v.isDouble()) {
double d = v.toDouble();
return !mozilla::IsNaN(d) && d != 0;
}
if (v.isSymbol())
return true;
/* The slow path handles strings and objects. */
return js::ToBooleanSlow(v);
}
/* ES6 draft 20141224, 7.1.3. */
MOZ_ALWAYS_INLINE bool
ToNumber(JSContext *cx, HandleValue v, double *out)
{
detail::AssertArgumentsAreSane(cx, v);
if (v.isNumber()) {
*out = v.toNumber();
return true;
}
return js::ToNumberSlow(cx, v, out);
}
/* ES6 draft 20141224, ToInteger (specialized for doubles). */
inline double
ToInteger(double d)
{
if (d == 0)
return d;
if (!mozilla::IsFinite(d)) {
if (mozilla::IsNaN(d))
return 0;
return d;
}
return d < 0 ? ceil(d) : floor(d);
}
/* ES6 draft 20141224, 7.1.5. */
MOZ_ALWAYS_INLINE bool
ToInt32(JSContext *cx, JS::HandleValue v, int32_t *out)
{
detail::AssertArgumentsAreSane(cx, v);
if (v.isInt32()) {
*out = v.toInt32();
return true;
}
return js::ToInt32Slow(cx, v, out);
}
/* ES6 draft 20141224, 7.1.6. */
MOZ_ALWAYS_INLINE bool
ToUint32(JSContext *cx, HandleValue v, uint32_t *out)
{
detail::AssertArgumentsAreSane(cx, v);
if (v.isInt32()) {
*out = uint32_t(v.toInt32());
return true;
}
return js::ToUint32Slow(cx, v, out);
}
/* ES6 draft 20141224, 7.1.8. */
MOZ_ALWAYS_INLINE bool
ToUint16(JSContext *cx, HandleValue v, uint16_t *out)
{
detail::AssertArgumentsAreSane(cx, v);
if (v.isInt32()) {
*out = uint16_t(v.toInt32());
return true;
}
return js::ToUint16Slow(cx, v, out);
}
/*
* Non-standard, with behavior similar to that of ToInt32, except in its
* producing an int64_t.
*/
MOZ_ALWAYS_INLINE bool
ToInt64(JSContext *cx, HandleValue v, int64_t *out)
{
detail::AssertArgumentsAreSane(cx, v);
if (v.isInt32()) {
*out = int64_t(v.toInt32());
return true;
}
return js::ToInt64Slow(cx, v, out);
}
/*
* Non-standard, with behavior similar to that of ToUint32, except in its
* producing a uint64_t.
*/
MOZ_ALWAYS_INLINE bool
ToUint64(JSContext *cx, HandleValue v, uint64_t *out)
{
detail::AssertArgumentsAreSane(cx, v);
if (v.isInt32()) {
*out = uint64_t(v.toInt32());
return true;
}
return js::ToUint64Slow(cx, v, out);
}
/* ES6 draft 20141224, 7.1.12. */
MOZ_ALWAYS_INLINE JSString*
ToString(JSContext *cx, HandleValue v)
{
detail::AssertArgumentsAreSane(cx, v);
if (v.isString())
return v.toString();
return js::ToStringSlow(cx, v);
}
/* ES6 draft 20141224, 7.1.13. */
inline JSObject *
ToObject(JSContext *cx, HandleValue v)
{
detail::AssertArgumentsAreSane(cx, v);
if (v.isObject())
return &v.toObject();
return js::ToObjectSlow(cx, v, false);
}
namespace detail {
/*
* Convert a double value to ResultType (an unsigned integral type) using
* ECMAScript-style semantics (that is, in like manner to how ECMAScript's
@ -278,22 +496,6 @@ ToUint64(double d)
return detail::ToUintWidth<uint64_t>(d);
}
/* ES5 9.4 ToInteger (specialized for doubles). */
inline double
ToInteger(double d)
{
if (d == 0)
return d;
if (!mozilla::IsFinite(d)) {
if (mozilla::IsNaN(d))
return 0;
return d;
}
return d < 0 ? ceil(d) : floor(d);
}
} // namespace JS
#endif /* js_Conversions_h */

View File

@ -669,9 +669,15 @@ js::intl_Collator(JSContext *cx, unsigned argc, Value *vp)
static void
collator_finalize(FreeOp *fop, JSObject *obj)
{
UCollator *coll = static_cast<UCollator*>(obj->as<NativeObject>().getReservedSlot(UCOLLATOR_SLOT).toPrivate());
if (coll)
ucol_close(coll);
// This is-undefined check shouldn't be necessary, but for internal
// brokenness in object allocation code. For the moment, hack around it by
// explicitly guarding against the possibility of the reserved slot not
// containing a private. See bug 949220.
const Value &slot = obj->as<NativeObject>().getReservedSlot(UCOLLATOR_SLOT);
if (!slot.isUndefined()) {
if (UCollator *coll = static_cast<UCollator*>(slot.toPrivate()))
ucol_close(coll);
}
}
static JSObject *
@ -1156,10 +1162,15 @@ js::intl_NumberFormat(JSContext *cx, unsigned argc, Value *vp)
static void
numberFormat_finalize(FreeOp *fop, JSObject *obj)
{
UNumberFormat *nf =
static_cast<UNumberFormat*>(obj->as<NativeObject>().getReservedSlot(UNUMBER_FORMAT_SLOT).toPrivate());
if (nf)
unum_close(nf);
// This is-undefined check shouldn't be necessary, but for internal
// brokenness in object allocation code. For the moment, hack around it by
// explicitly guarding against the possibility of the reserved slot not
// containing a private. See bug 949220.
const Value &slot = obj->as<NativeObject>().getReservedSlot(UNUMBER_FORMAT_SLOT);
if (!slot.isUndefined()) {
if (UNumberFormat *nf = static_cast<UNumberFormat*>(slot.toPrivate()))
unum_close(nf);
}
}
static JSObject *
@ -1610,9 +1621,15 @@ js::intl_DateTimeFormat(JSContext *cx, unsigned argc, Value *vp)
static void
dateTimeFormat_finalize(FreeOp *fop, JSObject *obj)
{
UDateFormat *df = static_cast<UDateFormat*>(obj->as<NativeObject>().getReservedSlot(UDATE_FORMAT_SLOT).toPrivate());
if (df)
udat_close(df);
// This is-undefined check shouldn't be necessary, but for internal
// brokenness in object allocation code. For the moment, hack around it by
// explicitly guarding against the possibility of the reserved slot not
// containing a private. See bug 949220.
const Value &slot = obj->as<NativeObject>().getReservedSlot(UDATE_FORMAT_SLOT);
if (!slot.isUndefined()) {
if (UDateFormat *df = static_cast<UDateFormat*>(slot.toPrivate()))
udat_close(df);
}
}
static JSObject *

View File

@ -7,6 +7,7 @@
#ifndef frontend_FullParseHandler_h
#define frontend_FullParseHandler_h
#include "mozilla/Attributes.h"
#include "mozilla/PodOperations.h"
#include "frontend/ParseNode.h"
@ -542,8 +543,30 @@ class FullParseHandler
block->pn_expr = body;
}
bool isOperationWithoutParens(ParseNode *pn, ParseNodeKind kind) {
return pn->isKind(kind) && !pn->isInParens();
ParseNode *newAssignment(ParseNodeKind kind, ParseNode *lhs, ParseNode *rhs,
ParseContext<FullParseHandler> *pc, JSOp op)
{
return newBinaryOrAppend(kind, lhs, rhs, pc, op);
}
bool isUnparenthesizedYieldExpression(ParseNode *node) {
return node->isKind(PNK_YIELD) && !node->isInParens();
}
bool isUnparenthesizedCommaExpression(ParseNode *node) {
return node->isKind(PNK_COMMA) && !node->isInParens();
}
bool isUnparenthesizedAssignment(Node node) {
if (node->isKind(PNK_ASSIGN) && !node->isInParens()) {
// PNK_ASSIGN is also (mis)used for things like |var name = expr;|.
// But this method is only called on actual expressions, so we can
// just assert the node's op is the one used for plain assignment.
MOZ_ASSERT(node->isOp(JSOP_NOP));
return true;
}
return false;
}
inline bool finishInitializerAssignment(ParseNode *pn, ParseNode *init, JSOp op);
@ -580,12 +603,13 @@ class FullParseHandler
return new_<ListNode>(kind, op, kid);
}
void addList(ParseNode *pn, ParseNode *kid) {
pn->append(kid);
ParseNode *newCommaExpressionList(ParseNode *kid) {
return newList(PNK_COMMA, kid, JSOP_NOP);
}
bool isUnparenthesizedYield(ParseNode *pn) {
return pn->isKind(PNK_YIELD) && !pn->isInParens();
void addList(ParseNode *list, ParseNode *kid) {
list->append(kid);
}
void setOp(ParseNode *pn, JSOp op) {
@ -601,12 +625,12 @@ class FullParseHandler
MOZ_ASSERT(pn->isArity(PN_LIST));
pn->pn_xflags |= flag;
}
ParseNode *setInParens(ParseNode *pn) {
MOZ_WARN_UNUSED_RESULT ParseNode *parenthesize(ParseNode *pn) {
pn->setInParens(true);
return pn;
}
ParseNode *setLikelyIIFE(ParseNode *pn) {
return setInParens(pn);
MOZ_WARN_UNUSED_RESULT ParseNode *setLikelyIIFE(ParseNode *pn) {
return parenthesize(pn);
}
void setPrologue(ParseNode *pn) {
pn->pn_prologue = true;

View File

@ -2884,10 +2884,9 @@ Parser<ParseHandler>::condition()
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_COND);
/* Check for (a = b) and warn about possible (a == b) mistype. */
if (handler.isOperationWithoutParens(pn, PNK_ASSIGN) &&
!report(ParseExtraWarning, false, null(), JSMSG_EQUAL_AS_ASSIGN))
{
return null();
if (handler.isUnparenthesizedAssignment(pn)) {
if (!report(ParseExtraWarning, false, null(), JSMSG_EQUAL_AS_ASSIGN))
return null();
}
return pn;
}
@ -5917,11 +5916,11 @@ Parser<ParseHandler>::expr(InvokedPrediction invoked)
if (!tokenStream.matchToken(&matched, TOK_COMMA))
return null();
if (matched) {
Node seq = handler.newList(PNK_COMMA, pn);
Node seq = handler.newCommaExpressionList(pn);
if (!seq)
return null();
while (true) {
if (handler.isUnparenthesizedYield(pn)) {
if (handler.isUnparenthesizedYieldExpression(pn)) {
report(ParseError, false, pn, JSMSG_BAD_GENERATOR_SYNTAX, js_yield_str);
return null();
}
@ -6296,7 +6295,7 @@ Parser<ParseHandler>::assignExpr(InvokedPrediction invoked)
if (!rhs)
return null();
return handler.newBinaryOrAppend(kind, lhs, rhs, pc, op);
return handler.newAssignment(kind, lhs, rhs, pc, op);
}
static const char incop_name_str[][10] = {"increment", "decrement"};
@ -7280,10 +7279,9 @@ Parser<ParseHandler>::comprehensionIf(GeneratorKind comprehensionKind)
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_COND);
/* Check for (a = b) and warn about possible (a == b) mistype. */
if (handler.isOperationWithoutParens(cond, PNK_ASSIGN) &&
!report(ParseExtraWarning, false, null(), JSMSG_EQUAL_AS_ASSIGN))
{
return null();
if (handler.isUnparenthesizedAssignment(cond)) {
if (!report(ParseExtraWarning, false, null(), JSMSG_EQUAL_AS_ASSIGN))
return null();
}
Node then = comprehensionTail(comprehensionKind);
@ -7323,7 +7321,7 @@ Parser<ParseHandler>::comprehensionTail(GeneratorKind comprehensionKind)
Node yieldExpr = newYieldExpression(begin, bodyExpr);
if (!yieldExpr)
return null();
handler.setInParens(yieldExpr);
yieldExpr = handler.parenthesize(yieldExpr);
return handler.newExprStatement(yieldExpr, pos().end);
}
@ -7446,7 +7444,7 @@ Parser<ParseHandler>::argumentList(Node listNode, bool *isSpread)
return false;
}
if (handler.isOperationWithoutParens(argNode, PNK_YIELD)) {
if (handler.isUnparenthesizedYieldExpression(argNode)) {
TokenKind tt;
if (!tokenStream.peekToken(&tt))
return false;
@ -8279,7 +8277,7 @@ Parser<ParseHandler>::parenExprOrGeneratorComprehension()
JSMSG_BAD_GENEXP_BODY, js_yield_str);
return null();
}
if (handler.isOperationWithoutParens(pn, PNK_COMMA)) {
if (handler.isUnparenthesizedCommaExpression(pn)) {
report(ParseError, false, null(),
JSMSG_BAD_GENERATOR_SYNTAX, js_generator_str);
return null();
@ -8297,12 +8295,11 @@ Parser<ParseHandler>::parenExprOrGeneratorComprehension()
return null();
}
handler.setEndPosition(pn, pos().end);
handler.setInParens(pn);
return pn;
return handler.parenthesize(pn);
}
#endif /* JS_HAS_GENERATOR_EXPRS */
pn = handler.setInParens(pn);
pn = handler.parenthesize(pn);
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
@ -8358,7 +8355,7 @@ Parser<ParseHandler>::exprInParens()
JSMSG_BAD_GENEXP_BODY, js_yield_str);
return null();
}
if (handler.isOperationWithoutParens(pn, PNK_COMMA)) {
if (handler.isUnparenthesizedCommaExpression(pn)) {
report(ParseError, false, null(),
JSMSG_BAD_GENERATOR_SYNTAX, js_generator_str);
return null();

View File

@ -7,6 +7,8 @@
#ifndef frontend_SyntaxParseHandler_h
#define frontend_SyntaxParseHandler_h
#include "mozilla/Attributes.h"
#include "frontend/ParseNode.h"
#include "frontend/TokenStream.h"
@ -39,12 +41,61 @@ class SyntaxParseHandler
NodeGeneric,
NodeName,
NodeGetProp,
NodeString,
NodeStringExprStatement,
NodeLValue
NodeLValue,
// In rare cases a parenthesized |node| doesn't have the same semantics
// as |node|. Each such node has a special Node value, and we use a
// different Node value to represent the parenthesized form. See also
// isUnparenthesized*(Node), newExprStatement(Node, uint32_t),
// parenthesize(Node), and meaningMightChangeIfParenthesized(Node).
// The directive prologue at the start of a FunctionBody or ScriptBody
// is the longest sequence (possibly empty) of string literal
// expression statements at the start of a function. Thus we need this
// to treat |"use strict";| as a possible Use Strict Directive and
// |("use strict");| as a useless statement.
NodeUnparenthesizedString,
// Legacy generator expressions of the form |(expr for (...))| and
// array comprehensions of the form |[expr for (...)]|) don't permit
// |expr| to be a comma expression. Thus we need this to treat
// |(a(), b for (x in []))| as a syntax error and
// |((a(), b) for (x in []))| as a generator that calls |a| and then
// yields |b| each time it's resumed.
NodeUnparenthesizedCommaExpr,
// Yield expressions currently (but not in ES6 -- a SpiderMonkey bug to
// fix) must generally be parenthesized. (See the uses of
// isUnparenthesizedYieldExpression in Parser.cpp for the rare
// exceptions.) Thus we need this to treat |yield 1, 2;| as a syntax
// error and |(yield 1), 2;| as a comma expression that will yield 1,
// then evaluate to 2.
NodeUnparenthesizedYieldExpr,
// Assignment expressions in condition contexts could be typos for
// equality checks. (Think |if (x = y)| versus |if (x == y)|.) Thus
// we need this to treat |if (x = y)| as a possible typo and
// |if ((x = y))| as a deliberate assignment within a condition.
//
// (Technically this isn't needed, as these are *only* extraWarnings
// warnings, and parsing with that option disables syntax parsing. But
// it seems best to be consistent, and perhaps the syntax parser will
// eventually enforce extraWarnings and will require this then.)
NodeUnparenthesizedAssignment
};
typedef Definition::Kind DefinitionNode;
private:
static bool meaningMightChangeIfParenthesized(Node node) {
return node == NodeUnparenthesizedString ||
node == NodeUnparenthesizedCommaExpr ||
node == NodeUnparenthesizedYieldExpr ||
node == NodeUnparenthesizedAssignment;
}
public:
SyntaxParseHandler(ExclusiveContext *cx, LifoAlloc &alloc,
TokenStream &tokenStream, bool foldConstants,
Parser<SyntaxParseHandler> *syntaxParser, LazyScript *lazyOuterFunction)
@ -69,14 +120,14 @@ class SyntaxParseHandler
return Definition::PLACEHOLDER;
}
Node newIdentifier(JSAtom *atom, const TokenPos &pos) { return NodeString; }
Node newIdentifier(JSAtom *atom, const TokenPos &pos) { return NodeName; }
Node newNumber(double value, DecimalPoint decimalPoint, const TokenPos &pos) { return NodeGeneric; }
Node newBooleanLiteral(bool cond, const TokenPos &pos) { return NodeGeneric; }
Node newStringLiteral(JSAtom *atom, const TokenPos &pos) {
lastAtom = atom;
lastStringPos = pos;
return NodeString;
return NodeUnparenthesizedString;
}
Node newTemplateStringLiteral(JSAtom *atom, const TokenPos &pos) {
@ -135,7 +186,7 @@ class SyntaxParseHandler
bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
bool addPropertyDefinition(Node literal, Node name, Node expr, bool isShorthand = false) { return true; }
bool addMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
Node newYieldExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; }
Node newYieldExpression(uint32_t begin, Node value, Node gen) { return NodeUnparenthesizedYieldExpr; }
Node newYieldStarExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; }
// Statements
@ -146,7 +197,7 @@ class SyntaxParseHandler
Node newEmptyStatement(const TokenPos &pos) { return NodeGeneric; }
Node newExprStatement(Node expr, uint32_t end) {
return expr == NodeString ? NodeStringExprStatement : NodeGeneric;
return expr == NodeUnparenthesizedString ? NodeStringExprStatement : NodeGeneric;
}
Node newIfStatement(uint32_t begin, Node cond, Node then, Node else_) { return NodeGeneric; }
@ -195,13 +246,6 @@ class SyntaxParseHandler
Node newLexicalScope(ObjectBox *blockbox) { return NodeGeneric; }
void setLexicalScopeBody(Node block, Node body) {}
bool isOperationWithoutParens(Node pn, ParseNodeKind kind) {
// It is OK to return false here, callers should only use this method
// for reporting strict option warnings and parsing code which the
// syntax parser does not handle.
return false;
}
bool finishInitializerAssignment(Node pn, Node init, JSOp op) { return true; }
void setBeginPosition(Node pn, Node oth) {}
@ -222,19 +266,48 @@ class SyntaxParseHandler
Node newList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
return NodeGeneric;
}
void addList(Node pn, Node kid) {}
bool isUnparenthesizedYield(Node pn) { return false; }
Node newCommaExpressionList(Node kid) {
return NodeUnparenthesizedCommaExpr;
}
void addList(Node list, Node kid) {
MOZ_ASSERT(list == NodeGeneric || list == NodeUnparenthesizedCommaExpr);
}
Node newAssignment(ParseNodeKind kind, Node lhs, Node rhs,
ParseContext<SyntaxParseHandler> *pc, JSOp op)
{
if (kind == PNK_ASSIGN)
return NodeUnparenthesizedAssignment;
return newBinaryOrAppend(kind, lhs, rhs, pc, op);
}
bool isUnparenthesizedYieldExpression(Node node) {
return node == NodeUnparenthesizedYieldExpr;
}
bool isUnparenthesizedCommaExpression(Node node) {
return node == NodeUnparenthesizedCommaExpr;
}
bool isUnparenthesizedAssignment(Node node) {
return node == NodeUnparenthesizedAssignment;
}
void setOp(Node pn, JSOp op) {}
void setBlockId(Node pn, unsigned blockid) {}
void setFlag(Node pn, unsigned flag) {}
void setListFlag(Node pn, unsigned flag) {}
Node setInParens(Node pn) {
// String literals enclosed by parentheses are ignored during
// strict mode parsing.
return (pn == NodeString) ? NodeGeneric : pn;
MOZ_WARN_UNUSED_RESULT Node parenthesize(Node node) {
if (meaningMightChangeIfParenthesized(node))
return NodeGeneric;
// In all other cases, the parenthesized form of |node| is equivalent
// to the unparenthesized form: return |node| unchanged.
return node;
}
Node setLikelyIIFE(Node pn) {
MOZ_WARN_UNUSED_RESULT Node setLikelyIIFE(Node pn) {
return pn; // Remain in syntax-parse mode.
}
void setPrologue(Node pn) {}

View File

@ -219,7 +219,6 @@ gc::GCRuntime::startVerifyPreBarriers()
/* Create the root node. */
trc->curnode = MakeNode(trc, nullptr, JSGCTraceKind(0));
/* We want MarkRuntime to save the roots to gcSavedRoots. */
incrementalState = MARK_ROOTS;
/* Make all the roots be edges emanating from the root node. */

View File

@ -21,5 +21,14 @@ assertNear(Math.hypot(1e3, 1e-3), 1000.0000000005);
assertNear(Math.hypot(1e-300, 1e300), 1e300);
assertNear(Math.hypot(1e3, 1e-3, 1e3, 1e-3), 1414.2135623738021555);
for (var i = 1, j = 1; i < 2; i += 0.05, j += 0.05)
assertNear(Math.hypot(1e1, 1e2, 1e3), Math.sqrt(1e2 + 1e4 + 1e6));
assertNear(Math.hypot(1e1, 1e2, 1e3, 1e4), Math.sqrt(1e2 + 1e4 + 1e6 + 1e8));
for (var i = 1, j = 2; i < 2; i += 0.05, j += 0.05)
assertNear(Math.hypot(i, j), Math.sqrt(i * i + j * j));
for (var i = 1, j = 2, k = 3; i < 2; i += 0.05, j += 0.05, k += 0.05)
assertNear(Math.hypot(i, j, k), Math.sqrt(i * i + j * j + k * k));
for (var i = 1, j = 2, k = 3, l = 4; i < 2; i += 0.05, j += 0.05, k += 0.05, l += 0.5)
assertNear(Math.hypot(i, j, k, l), Math.sqrt(i * i + j * j + k * k + l * l));

View File

@ -28,6 +28,11 @@ for (var inf of [Infinity, -Infinity]) {
assertEq(Math.hypot(inf, NaN, NaN), Infinity);
assertEq(Math.hypot(NaN, inf, NaN), Infinity);
assertEq(Math.hypot(NaN, NaN, inf), Infinity);
assertEq(Math.hypot(inf, NaN, NaN, NaN), Infinity);
assertEq(Math.hypot(NaN, inf, NaN, NaN), Infinity);
assertEq(Math.hypot(NaN, NaN, inf, NaN), Infinity);
assertEq(Math.hypot(NaN, NaN, NaN, inf), Infinity);
}
// If no argument is +∞ or −∞, and any argument is NaN, the result is NaN.
@ -42,7 +47,13 @@ assertEq(Math.hypot(NaN, 0, 0), NaN);
assertEq(Math.hypot(0, NaN, 0), NaN);
assertEq(Math.hypot(0, 0, NaN), NaN);
assertEq(Math.hypot(NaN, 0, 0, 0), NaN);
assertEq(Math.hypot(0, NaN, 0, 0), NaN);
assertEq(Math.hypot(0, 0, NaN, 0), NaN);
assertEq(Math.hypot(0, 0, 0, NaN), NaN);
assertEq(Math.hypot(Number.MAX_VALUE, Number.MIN_VALUE, NaN), NaN);
assertEq(Math.hypot(Number.MAX_VALUE, Number.MIN_VALUE, Number.MIN_VALUE, NaN), NaN);
// If all arguments are either +0 or -0, the result is +0.
assertEq(Math.hypot(-0, -0), +0);
@ -53,5 +64,11 @@ assertEq(Math.hypot(+0, -0, -0), +0);
assertEq(Math.hypot(-0, +0, -0), +0);
assertEq(Math.hypot(+0, +0, -0), +0);
assertEq(Math.hypot(-0, -0, -0, -0), +0);
assertEq(Math.hypot(+0, -0, -0, -0), +0);
assertEq(Math.hypot(-0, -0, +0, -0), +0);
assertEq(Math.hypot(+0, +0, +0, -0), +0);
assertEq(Math.hypot(-0, -0, -0, +0), +0);
// The length property of the hypot function is 2.
assertEq(Math.hypot.length, 2);

View File

@ -1062,16 +1062,32 @@ function rtrunc_to_int32_string(i) {
return i;
}
var uceFault_hypot_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_hypot_number'));
function rhypot_number(i) {
var uceFault_hypot_number_2args = eval(uneval(uceFault).replace('uceFault', 'uceFault_hypot_number_2args'));
function rhypot_number_2args(i) {
var x = Math.hypot(i, i + 1);
if (uceFault_hypot_number(i) || uceFault_hypot_number(i))
if (uceFault_hypot_number_2args(i) || uceFault_hypot_number_2args(i))
assertEq(x, Math.sqrt(i * i + (i + 1) * (i + 1)));
return i;
}
var uceFault_hypot_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_hypot_object'));
function rhypot_object(i) {
var uceFault_hypot_number_3args = eval(uneval(uceFault).replace('uceFault', 'uceFault_hypot_number_3args'));
function rhypot_number_3args(i) {
var x = Math.hypot(i, i + 1, i + 2);
if (uceFault_hypot_number_3args(i) || uceFault_hypot_number_3args(i))
assertEq(x, Math.sqrt(i * i + (i + 1) * (i + 1) + (i + 2) * (i + 2)));
return i;
}
var uceFault_hypot_number_4args = eval(uneval(uceFault).replace('uceFault', 'uceFault_hypot_number_4args'));
function rhypot_number_4args(i) {
var x = Math.hypot(i, i + 1, i + 2, i + 3);
if (uceFault_hypot_number_4args(i) || uceFault_hypot_number_4args(i))
assertEq(x, Math.sqrt(i * i + (i + 1) * (i + 1) + (i + 2) * (i + 2) + (i + 3) * (i + 3)));
return i;
}
var uceFault_hypot_object_2args = eval(uneval(uceFault).replace('uceFault', 'uceFault_hypot_object_2args'));
function rhypot_object_2args(i) {
var t0 = i;
var t1 = i + 1;
var o0 = { valueOf: function () { return t0; } };
@ -1079,11 +1095,48 @@ function rhypot_object(i) {
var x = Math.hypot(o0, o1);
t0 = 1000;
t1 = 2000;
if (uceFault_hypot_object(i) || uceFault_hypot_object(i) )
if (uceFault_hypot_object_2args(i) || uceFault_hypot_object_2args(i) )
assertEq(x, Math.sqrt(i * i + (i + 1) * (i + 1)));
return i;
}
var uceFault_hypot_object_3args = eval(uneval(uceFault).replace('uceFault', 'uceFault_hypot_object_3args'));
function rhypot_object_3args(i) {
var t0 = i;
var t1 = i + 1;
var t2 = i + 2;
var o0 = { valueOf: function () { return t0; } };
var o1 = { valueOf: function () { return t1; } };
var o2 = { valueOf: function () { return t2; } };
var x = Math.hypot(o0, o1, o2);
t0 = 1000;
t1 = 2000;
t2 = 3000;
if (uceFault_hypot_object_3args(i) || uceFault_hypot_object_3args(i) )
assertEq(x, Math.sqrt(i * i + (i + 1) * (i + 1) + (i + 2) * (i + 2)));
return i;
}
var uceFault_hypot_object_4args = eval(uneval(uceFault).replace('uceFault', 'uceFault_hypot_object_4args'));
function rhypot_object_4args(i) {
var t0 = i;
var t1 = i + 1;
var t2 = i + 2;
var t3 = i + 3;
var o0 = { valueOf: function () { return t0; } };
var o1 = { valueOf: function () { return t1; } };
var o2 = { valueOf: function () { return t2; } };
var o3 = { valueOf: function () { return t3; } };
var x = Math.hypot(o0, o1, o2, o3);
t0 = 1000;
t1 = 2000;
t2 = 3000;
t3 = 4000;
if (uceFault_hypot_object_4args(i) || uceFault_hypot_object_4args(i) )
assertEq(x, Math.sqrt(i * i + (i + 1) * (i + 1) + (i + 2) * (i + 2) + (i + 3) * (i + 3)));
return i;
}
var uceFault_sin_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_sin_number'));
function rsin_number(i) {
var x = Math.sin(i);
@ -1224,8 +1277,12 @@ for (i = 0; i < 100; i++) {
rtrunc_to_int32_number(i);
rtrunc_to_int32_object(i);
rtrunc_to_int32_string(i);
rhypot_number(i);
rhypot_object(i);
rhypot_number_2args(i);
rhypot_number_3args(i);
rhypot_number_4args(i);
rhypot_object_2args(i);
rhypot_object_3args(i);
rhypot_object_4args(i);
rsin_number(i);
rsin_object(i);
rlog_number(i);

View File

@ -3908,14 +3908,25 @@ void
CodeGenerator::visitHypot(LHypot *lir)
{
Register temp = ToRegister(lir->temp());
FloatRegister x = ToFloatRegister(lir->x());
FloatRegister y = ToFloatRegister(lir->y());
uint32_t numArgs = lir->numArgs();
masm.setupUnalignedABICall(numArgs, temp);
masm.setupUnalignedABICall(2, temp);
masm.passABIArg(x, MoveOp::DOUBLE);
masm.passABIArg(y, MoveOp::DOUBLE);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ecmaHypot), MoveOp::DOUBLE);
for (uint32_t i = 0 ; i < numArgs; ++i)
masm.passABIArg(ToFloatRegister(lir->getOperand(i)), MoveOp::DOUBLE);
switch(numArgs) {
case 2:
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ecmaHypot), MoveOp::DOUBLE);
break;
case 3:
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, hypot3), MoveOp::DOUBLE);
break;
case 4:
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, hypot4), MoveOp::DOUBLE);
break;
default:
MOZ_CRASH("Unexpected number of arguments to hypot function.");
}
MOZ_ASSERT(ToFloatRegister(lir->output()) == ReturnDoubleReg);
}

View File

@ -636,7 +636,14 @@ enum ABIFunctionType
// int f(int, double)
Args_Int_IntDouble = Args_General0 |
(ArgType_Double << (ArgType_Shift * 1)) |
(ArgType_General << (ArgType_Shift * 2))
(ArgType_General << (ArgType_Shift * 2)),
// double f(double, double, double)
Args_Double_DoubleDoubleDouble = Args_Double_DoubleDouble | (ArgType_Double << (ArgType_Shift * 3)),
// double f(double, double, double, double)
Args_Double_DoubleDoubleDoubleDouble = Args_Double_DoubleDoubleDouble | (ArgType_Double << (ArgType_Shift * 4))
};
enum class BarrierKind : uint32_t {

View File

@ -2965,16 +2965,40 @@ class LAtan2D : public LCallInstructionHelper<1, 2, 1>
}
};
class LHypot : public LCallInstructionHelper<1, 2, 1>
class LHypot : public LCallInstructionHelper<1, 4, 1>
{
uint32_t numOperands_;
public:
LIR_HEADER(Hypot)
LHypot(const LAllocation &x, const LAllocation &y, const LDefinition &temp) {
LHypot(const LAllocation &x, const LAllocation &y, const LDefinition &temp)
: numOperands_(2)
{
setOperand(0, x);
setOperand(1, y);
setTemp(0, temp);
}
LHypot(const LAllocation &x, const LAllocation &y, const LAllocation &z, const LDefinition &temp)
: numOperands_(3)
{
setOperand(0, x);
setOperand(1, y);
setOperand(2, z);
setTemp(0, temp);
}
LHypot(const LAllocation &x, const LAllocation &y, const LAllocation &z, const LAllocation &w, const LDefinition &temp)
: numOperands_(4)
{
setOperand(0, x);
setOperand(1, y);
setOperand(2, z);
setOperand(3, w);
setTemp(0, temp);
}
uint32_t numArgs() const { return numOperands_; }
const LAllocation *x() {
return getOperand(0);
}

View File

@ -1306,13 +1306,34 @@ LIRGenerator::visitAtan2(MAtan2 *ins)
void
LIRGenerator::visitHypot(MHypot *ins)
{
MDefinition *x = ins->x();
MOZ_ASSERT(x->type() == MIRType_Double);
LHypot *lir = nullptr;
uint32_t length = ins->numOperands();
for (uint32_t i = 0; i < length; ++i)
MOZ_ASSERT(ins->getOperand(i)->type() == MIRType_Double);
MDefinition *y = ins->y();
MOZ_ASSERT(y->type() == MIRType_Double);
switch(length) {
case 2:
lir = new(alloc()) LHypot(useRegisterAtStart(ins->getOperand(0)),
useRegisterAtStart(ins->getOperand(1)),
tempFixed(CallTempReg0));
break;
case 3:
lir = new(alloc()) LHypot(useRegisterAtStart(ins->getOperand(0)),
useRegisterAtStart(ins->getOperand(1)),
useRegisterAtStart(ins->getOperand(2)),
tempFixed(CallTempReg0));
break;
case 4:
lir = new(alloc()) LHypot(useRegisterAtStart(ins->getOperand(0)),
useRegisterAtStart(ins->getOperand(1)),
useRegisterAtStart(ins->getOperand(2)),
useRegisterAtStart(ins->getOperand(3)),
tempFixed(CallTempReg0));
break;
default:
MOZ_CRASH("Unexpected number of arguments to LHypot.");
}
LHypot *lir = new(alloc()) LHypot(useRegisterAtStart(x), useRegisterAtStart(y), tempFixed(CallTempReg0));
defineReturn(lir, ins);
}

View File

@ -1002,21 +1002,30 @@ IonBuilder::inlineMathHypot(CallInfo &callInfo)
if (callInfo.constructing())
return InliningStatus_NotInlined;
if (callInfo.argc() != 2)
uint32_t argc = callInfo.argc();
if (argc < 2 || argc > 4)
return InliningStatus_NotInlined;
if (getInlineReturnType() != MIRType_Double)
return InliningStatus_NotInlined;
MIRType argType0 = callInfo.getArg(0)->type();
MIRType argType1 = callInfo.getArg(1)->type();
if (!IsNumberType(argType0) || !IsNumberType(argType1))
MDefinitionVector vector(alloc());
if (!vector.reserve(argc))
return InliningStatus_NotInlined;
callInfo.setImplicitlyUsedUnchecked();
for (uint32_t i = 0; i < argc; ++i) {
MDefinition * arg = callInfo.getArg(i);
if (!IsNumberType(arg->type()))
return InliningStatus_NotInlined;
vector.infallibleAppend(arg);
}
callInfo.setImplicitlyUsedUnchecked();
MHypot *hypot = MHypot::New(alloc(), vector);
if (!hypot)
return InliningStatus_NotInlined;
MHypot *hypot = MHypot::New(alloc(), callInfo.getArg(0), callInfo.getArg(1));
current->add(hypot);
current->push(hypot);
return InliningStatus_Inlined;

View File

@ -2231,6 +2231,18 @@ MMathFunction::trySpecializeFloat32(TempAllocator &alloc)
setPolicyType(MIRType_Float32);
}
MHypot *MHypot::New(TempAllocator &alloc, const MDefinitionVector & vector)
{
uint32_t length = vector.length();
MHypot * hypot = new(alloc) MHypot;
if (!hypot->init(alloc, length))
return nullptr;
for (uint32_t i = 0; i < length; ++i)
hypot->initOperand(i, vector[i]);
return hypot;
}
bool
MAdd::fallible() const
{

View File

@ -4794,8 +4794,8 @@ class MTruncateToInt32
}
#endif
bool writeRecoverData(CompactBufferWriter &writer) const;
bool canRecoverOnBailout() const {
bool writeRecoverData(CompactBufferWriter &writer) const MOZ_OVERRIDE;
bool canRecoverOnBailout() const MOZ_OVERRIDE {
return input()->type() < MIRType_Symbol;
}
@ -5507,11 +5507,10 @@ class MAtan2
// Inline implementation of Math.hypot().
class MHypot
: public MBinaryInstruction,
public MixPolicy<DoublePolicy<0>, DoublePolicy<1> >::Data
: public MVariadicInstruction,
public AllDoublePolicy::Data
{
MHypot(MDefinition *y, MDefinition *x)
: MBinaryInstruction(x, y)
MHypot()
{
setResultType(MIRType_Double);
setMovable();
@ -5519,17 +5518,7 @@ class MHypot
public:
INSTRUCTION_HEADER(Hypot)
static MHypot *New(TempAllocator &alloc, MDefinition *x, MDefinition *y) {
return new(alloc) MHypot(y, x);
}
MDefinition *x() const {
return getOperand(0);
}
MDefinition *y() const {
return getOperand(1);
}
static MHypot *New(TempAllocator &alloc, const MDefinitionVector &vector);
bool congruentTo(const MDefinition *ins) const MOZ_OVERRIDE {
return congruentIfOperandsEqual(ins);
@ -5548,7 +5537,13 @@ class MHypot
return true;
}
ALLOW_CLONE(MHypot)
bool canClone() const {
return true;
}
MInstruction *clone(TempAllocator &alloc, const MDefinitionVector &inputs) const {
return MHypot::New(alloc, inputs);
}
};
// Inline implementation of Math.pow().

View File

@ -874,10 +874,12 @@ MHypot::writeRecoverData(CompactBufferWriter &writer) const
{
MOZ_ASSERT(canRecoverOnBailout());
writer.writeUnsigned(uint32_t(RInstruction::Recover_Hypot));
writer.writeUnsigned(uint32_t(numOperands()));
return true;
}
RHypot::RHypot(CompactBufferReader &reader)
: numOperands_(reader.readUnsigned())
{ }
bool
@ -885,12 +887,11 @@ RHypot::recover(JSContext *cx, SnapshotIterator &iter) const
{
JS::AutoValueVector vec(cx);
// currently, only 2 args can be saved in MIR
if (!vec.reserve(2))
if (!vec.reserve(numOperands_))
return false;
vec.infallibleAppend(iter.read());
vec.infallibleAppend(iter.read());
for (uint32_t i = 0 ; i < numOperands_ ; ++i)
vec.infallibleAppend(iter.read());
RootedValue result(cx);

View File

@ -477,11 +477,14 @@ class RAtan2 MOZ_FINAL : public RInstruction
class RHypot MOZ_FINAL : public RInstruction
{
private:
uint32_t numOperands_;
public:
RINSTRUCTION_HEADER_(Hypot)
virtual uint32_t numOperands() const {
return 2;
return numOperands_;
}
bool recover(JSContext *cx, SnapshotIterator &iter) const;

View File

@ -94,6 +94,26 @@ ArithPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
return true;
}
bool
AllDoublePolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
{
for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
MDefinition *in = ins->getOperand(i);
if (in->type() == MIRType_Double)
continue;
MInstruction *replace = MToDouble::New(alloc, in);
ins->block()->insertBefore(ins, replace);
ins->replaceOperand(i, replace);
if (!replace->typePolicy()->adjustInputs(alloc, replace))
return false;
}
return true;
}
bool
ComparePolicy::adjustInputs(TempAllocator &alloc, MInstruction *def)
{
@ -1025,6 +1045,7 @@ FilterTypeSetPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
_(StoreTypedArrayPolicy) \
_(StoreUnboxedObjectOrNullPolicy) \
_(TestPolicy) \
_(AllDoublePolicy) \
_(ToDoublePolicy) \
_(ToInt32Policy) \
_(ToStringPolicy) \

View File

@ -93,6 +93,13 @@ class ArithPolicy MOZ_FINAL : public TypePolicy
virtual bool adjustInputs(TempAllocator &alloc, MInstruction *def) MOZ_OVERRIDE;
};
class AllDoublePolicy MOZ_FINAL : public TypePolicy
{
public:
EMPTY_DATA_;
bool adjustInputs(TempAllocator &alloc, MInstruction *def);
};
class BitwisePolicy MOZ_FINAL : public TypePolicy
{
public:

View File

@ -4160,6 +4160,8 @@ AssertValidABIFunctionType(uint32_t passedArgTypes)
case Args_Double_DoubleDouble:
case Args_Double_IntDouble:
case Args_Int_IntDouble:
case Args_Double_DoubleDoubleDouble:
case Args_Double_DoubleDoubleDoubleDouble:
break;
default:
MOZ_CRASH("Unexpected type");

View File

@ -1449,6 +1449,15 @@ Simulator::getFpArgs(double *x, double *y, int32_t *z)
}
}
void
Simulator::getFpFromStack(int32_t *stack, double *x)
{
MOZ_ASSERT(stack && x);
char buffer[2 * sizeof(stack[0])];
memcpy(buffer, stack, 2 * sizeof(stack[0]));
memcpy(x, buffer, 2 * sizeof(stack[0]));
}
void
Simulator::setCallResultDouble(double result)
{
@ -2078,6 +2087,9 @@ typedef double (*Prototype_Double_IntDouble)(int32_t arg0, double arg1);
typedef double (*Prototype_Double_DoubleDouble)(double arg0, double arg1);
typedef int32_t (*Prototype_Int_IntDouble)(int32_t arg0, double arg1);
typedef double (*Prototype_Double_DoubleDoubleDouble)(double arg0, double arg1, double arg2);
typedef double (*Prototype_Double_DoubleDoubleDoubleDouble)(double arg0, double arg1,
double arg2, double arg3);
// Fill the volatile registers with scratch values.
//
@ -2299,6 +2311,31 @@ Simulator::softwareInterrupt(SimInstruction *instr)
set_register(r0, result);
break;
}
case Args_Double_DoubleDoubleDouble: {
double dval0, dval1, dval2;
int32_t ival;
getFpArgs(&dval0, &dval1, &ival);
// the last argument is on stack
getFpFromStack(stack_pointer, &dval2);
Prototype_Double_DoubleDoubleDouble target = reinterpret_cast<Prototype_Double_DoubleDoubleDouble>(external);
double dresult = target(dval0, dval1, dval2);
scratchVolatileRegisters(/* scratchFloat = true */);
setCallResultDouble(dresult);
break;
}
case Args_Double_DoubleDoubleDoubleDouble: {
double dval0, dval1, dval2, dval3;
int32_t ival;
getFpArgs(&dval0, &dval1, &ival);
// the two last arguments are on stack
getFpFromStack(stack_pointer, &dval2);
getFpFromStack(stack_pointer + 2, &dval3);
Prototype_Double_DoubleDoubleDoubleDouble target = reinterpret_cast<Prototype_Double_DoubleDoubleDoubleDouble>(external);
double dresult = target(dval0, dval1, dval2, dval3);
scratchVolatileRegisters(/* scratchFloat = true */);
setCallResultDouble(dresult);
break;
}
default:
MOZ_CRASH("call");
}

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