зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to m-c a=merge
This commit is contained in:
Коммит
57a1b317fb
|
@ -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") {
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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'");
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ a {
|
|||
display: flex;
|
||||
}
|
||||
|
||||
.message-body {
|
||||
.message-body > * {
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
|
38
configure.in
38
configure.in
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "js/Conversions.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsIScriptContext;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 bar ! 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 bar ! 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 bar ! 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 bar ! 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 bar ! 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 bar ! 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 bar ! 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 bar ! 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=" foo bar ">foo bar</div>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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().
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
*/
|
||||
|
||||
interface SVGClipPathElement : SVGElement {
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedEnumeration clipPathUnits;
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedTransformList transform;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -10,6 +10,6 @@
|
|||
interface SVGDocument : Document {
|
||||
[Throws]
|
||||
readonly attribute DOMString domain;
|
||||
[Throws]
|
||||
[Pure, Throws]
|
||||
readonly attribute SVGElement? rootElement;
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@ interface SVGElement : Element {
|
|||
/* [SetterThrows]
|
||||
attribute DOMString xmlbase; */
|
||||
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedString className;
|
||||
[PutForwards=cssText, Constant]
|
||||
readonly attribute CSSStyleDeclaration style;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
|
||||
interface SVGFEComponentTransferElement : SVGElement {
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedString in1;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
*/
|
||||
|
||||
interface SVGFEDistantLightElement : SVGElement {
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedNumber azimuth;
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedNumber elevation;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
|
||||
interface SVGFEImageElement : SVGElement {
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio;
|
||||
};
|
||||
|
||||
|
|
|
@ -11,5 +11,6 @@
|
|||
*/
|
||||
|
||||
interface SVGFEMergeNodeElement : SVGElement {
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedString in1;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -11,8 +11,11 @@
|
|||
*/
|
||||
|
||||
interface SVGFEOffsetElement : SVGElement {
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedString in1;
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedNumber dx;
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedNumber dy;
|
||||
};
|
||||
|
||||
|
|
|
@ -11,7 +11,10 @@
|
|||
*/
|
||||
|
||||
interface SVGFEPointLightElement : SVGElement {
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedNumber x;
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedNumber y;
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedNumber z;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
|
||||
interface SVGFETileElement : SVGElement {
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedString in1;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
interface SVGPathElement : SVGGraphicsElement {
|
||||
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedNumber pathLength;
|
||||
|
||||
float getTotalLength();
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
|
||||
interface SVGStopElement : SVGElement {
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedNumber offset;
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
[NoInterfaceObject]
|
||||
interface SVGURIReference {
|
||||
[Constant]
|
||||
readonly attribute SVGAnimatedString href;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ public:
|
|||
|
||||
protected:
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
RefPtr<MacIOSurfaceTextureSourceOGL> mTextureSource;
|
||||
RefPtr<GLTextureSource> mTextureSource;
|
||||
RefPtr<MacIOSurface> mSurface;
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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().
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче