From adbb1297549f9d50e2153fdf8534f081bf600f27 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Tue, 27 Jan 2015 10:21:55 +0000 Subject: [PATCH 01/46] Bug 1124581 - Remove dead code related to conservative scanner r=terrence --- js/src/gc/Verifier.cpp | 1 - js/src/vm/Runtime.h | 16 ---------------- 2 files changed, 17 deletions(-) diff --git a/js/src/gc/Verifier.cpp b/js/src/gc/Verifier.cpp index c42acb383bc2..0a309500d729 100644 --- a/js/src/gc/Verifier.cpp +++ b/js/src/gc/Verifier.cpp @@ -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. */ diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index b768db59c4fd..fab44e6c96c2 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -496,22 +496,6 @@ class PerThreadData : public PerThreadDataFriendFields JSRuntime *runtime_; public: - /* - * We save all conservative scanned roots in this vector so that - * conservative scanning can be "replayed" deterministically. In DEBUG mode, - * this allows us to run a non-incremental GC after every incremental GC to - * ensure that no objects were missed. - */ -#ifdef DEBUG - struct SavedGCRoot { - void *thing; - JSGCTraceKind kind; - - SavedGCRoot(void *thing, JSGCTraceKind kind) : thing(thing), kind(kind) {} - }; - js::Vector gcSavedRoots; -#endif - #ifdef JS_TRACE_LOGGING TraceLoggerThread *traceLogger; #endif From 88299aaa556c4509c1f8fec8edc202c6194e865f Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Tue, 27 Jan 2015 12:11:47 +0100 Subject: [PATCH 02/46] Bug 1113863 - Move application configure after exporting MOZ_NO_DEBUG_RTL. r=glandium --- configure.in | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/configure.in b/configure.in index e50c167a75a6..f5201334eed4 100644 --- a/configure.in +++ b/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], @@ -7257,6 +7240,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 From 9e50499c7a0466555b1e456e39b465f6d2696a04 Mon Sep 17 00:00:00 2001 From: Masatoshi Kimura Date: Tue, 27 Jan 2015 20:46:27 +0900 Subject: [PATCH 03/46] Bug 1126017 - Use --enable-warnings-as-errors on Win64 builders. r=glandium --- browser/config/mozconfigs/win64/common-opt | 3 +++ browser/config/mozconfigs/win64/debug | 3 +++ 2 files changed, 6 insertions(+) diff --git a/browser/config/mozconfigs/win64/common-opt b/browser/config/mozconfigs/win64/common-opt index 431b35a3662b..6e6ca295a383 100644 --- a/browser/config/mozconfigs/win64/common-opt +++ b/browser/config/mozconfigs/win64/common-opt @@ -25,5 +25,8 @@ export MOZILLA_OFFICIAL=1 export MOZ_TELEMETRY_REPORTING=1 +# Treat warnings as errors in directories with FAIL_ON_WARNINGS. +ac_add_options --enable-warnings-as-errors + # Package js shell. export MOZ_PACKAGE_JSSHELL=1 diff --git a/browser/config/mozconfigs/win64/debug b/browser/config/mozconfigs/win64/debug index 7f5493182590..445ebbc1621d 100644 --- a/browser/config/mozconfigs/win64/debug +++ b/browser/config/mozconfigs/win64/debug @@ -20,6 +20,9 @@ ac_add_options --with-google-oauth-api-keyfile=${_google_oauth_api_keyfile} # Needed to enable breakpad in application.ini export MOZILLA_OFFICIAL=1 +# Treat warnings as errors in directories with FAIL_ON_WARNINGS. +ac_add_options --enable-warnings-as-errors + # Package js shell. export MOZ_PACKAGE_JSSHELL=1 From 9a1bc99b0c604f1e4cb5e7360d708956bc0a8a3c Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Tue, 27 Jan 2015 14:02:05 +0100 Subject: [PATCH 04/46] Backed out changeset c3c8794b37bf (bug 1126017) for bustage on a CLOSED TREE --- browser/config/mozconfigs/win64/common-opt | 3 --- browser/config/mozconfigs/win64/debug | 3 --- 2 files changed, 6 deletions(-) diff --git a/browser/config/mozconfigs/win64/common-opt b/browser/config/mozconfigs/win64/common-opt index 6e6ca295a383..431b35a3662b 100644 --- a/browser/config/mozconfigs/win64/common-opt +++ b/browser/config/mozconfigs/win64/common-opt @@ -25,8 +25,5 @@ export MOZILLA_OFFICIAL=1 export MOZ_TELEMETRY_REPORTING=1 -# Treat warnings as errors in directories with FAIL_ON_WARNINGS. -ac_add_options --enable-warnings-as-errors - # Package js shell. export MOZ_PACKAGE_JSSHELL=1 diff --git a/browser/config/mozconfigs/win64/debug b/browser/config/mozconfigs/win64/debug index 445ebbc1621d..7f5493182590 100644 --- a/browser/config/mozconfigs/win64/debug +++ b/browser/config/mozconfigs/win64/debug @@ -20,9 +20,6 @@ ac_add_options --with-google-oauth-api-keyfile=${_google_oauth_api_keyfile} # Needed to enable breakpad in application.ini export MOZILLA_OFFICIAL=1 -# Treat warnings as errors in directories with FAIL_ON_WARNINGS. -ac_add_options --enable-warnings-as-errors - # Package js shell. export MOZ_PACKAGE_JSSHELL=1 From bfc4d164a13a3ff085c70057f5d0a33fe9e9a9fc Mon Sep 17 00:00:00 2001 From: JW Wang Date: Mon, 26 Jan 2015 20:08:00 +0100 Subject: [PATCH 05/46] Bug 1124939 - Add "individualization-request" to MediaKeyMessageType. r=bz --- dom/media/eme/CDMProxy.cpp | 1 + dom/media/gmp-plugin/fake.info | 2 +- dom/media/gmp/gmp-api/gmp-decryption.h | 5 +++-- dom/webidl/MediaKeyMessageEvent.webidl | 3 ++- media/gmp-clearkey/0.1/clearkey.info | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/dom/media/eme/CDMProxy.cpp b/dom/media/eme/CDMProxy.cpp index e56fdaa69d79..3e57867e6420 100644 --- a/dom/media/eme/CDMProxy.cpp +++ b/dom/media/eme/CDMProxy.cpp @@ -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; }; }; diff --git a/dom/media/gmp-plugin/fake.info b/dom/media/gmp-plugin/fake.info index f40376323d14..5b29387b6b71 100644 --- a/dom/media/gmp-plugin/fake.info +++ b/dom/media/gmp-plugin/fake.info @@ -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 diff --git a/dom/media/gmp/gmp-api/gmp-decryption.h b/dom/media/gmp/gmp-api/gmp-decryption.h index fed2e3f5b3ee..de82c0a0d29f 100644 --- a/dom/media/gmp/gmp-api/gmp-decryption.h +++ b/dom/media/gmp/gmp-api/gmp-decryption.h @@ -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(). diff --git a/dom/webidl/MediaKeyMessageEvent.webidl b/dom/webidl/MediaKeyMessageEvent.webidl index 8cc5bca86ecc..3e04b1b9a1a1 100644 --- a/dom/webidl/MediaKeyMessageEvent.webidl +++ b/dom/webidl/MediaKeyMessageEvent.webidl @@ -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)] diff --git a/media/gmp-clearkey/0.1/clearkey.info b/media/gmp-clearkey/0.1/clearkey.info index 23f4efa47755..639fe84ee38e 100644 --- a/media/gmp-clearkey/0.1/clearkey.info +++ b/media/gmp-clearkey/0.1/clearkey.info @@ -1,4 +1,4 @@ Name: clearkey Description: ClearKey decrypt-only GMP plugin Version: 0.1 -APIs: eme-decrypt-v3[org.w3.clearkey] +APIs: eme-decrypt-v4[org.w3.clearkey] From 9cd10b7b4f6cf395322036e5918d1dd99df2d4c0 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 26 Jan 2015 21:09:59 -0500 Subject: [PATCH 06/46] Bug 1117034 - Mark some overridden functions in the tree as override --HG-- extra : rebase_source : a37ba6b69c02db90b8f3c440ac2dbca4d80c8bc5 --- dom/media/gstreamer/GStreamerReader.h | 16 ++++++++-------- dom/plugins/ipc/PluginModuleParent.h | 2 +- gfx/thebes/gfxPangoFonts.cpp | 8 ++++---- gfx/thebes/gfxPlatform.cpp | 2 +- js/src/jit/MIR.h | 4 ++-- toolkit/system/dbus/nsNetworkManagerListener.h | 6 +++--- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/dom/media/gstreamer/GStreamerReader.h b/dom/media/gstreamer/GStreamerReader.h index 097a00658f84..832314b1baff 100644 --- a/dom/media/gstreamer/GStreamerReader.h +++ b/dom/media/gstreamer/GStreamerReader.h @@ -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 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(); } diff --git a/dom/plugins/ipc/PluginModuleParent.h b/dom/plugins/ipc/PluginModuleParent.h index 88c79cf31ef9..bbb99516b394 100644 --- a/dom/plugins/ipc/PluginModuleParent.h +++ b/dom/plugins/ipc/PluginModuleParent.h @@ -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 diff --git a/gfx/thebes/gfxPangoFonts.cpp b/gfx/thebes/gfxPangoFonts.cpp index 9e8bd8328e42..e6f4ebaba741 100644 --- a/gfx/thebes/gfxPangoFonts.cpp +++ b/gfx/thebes/gfxPangoFonts.cpp @@ -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 - GetSubSuperscriptFont(int32_t aAppUnitsPerDevPixel); + GetSubSuperscriptFont(int32_t aAppUnitsPerDevPixel) MOZ_OVERRIDE; protected: virtual already_AddRefed MakeScaledFont(gfxFontStyle *aFontStyle, gfxFloat aFontScale); - virtual already_AddRefed GetSmallCapsFont(); + virtual already_AddRefed GetSmallCapsFont() MOZ_OVERRIDE; private: gfxFcFont(cairo_scaled_font_t *aCairoFont, gfxFcFontEntry *aFontEntry, diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 2454341c6880..671eb52c8559 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -169,7 +169,7 @@ public: explicit CrashStatsLogForwarder(const char* aKey); virtual void Log(const std::string& aString) MOZ_OVERRIDE; - virtual std::vector > StringsVectorCopy(); + virtual std::vector > StringsVectorCopy() MOZ_OVERRIDE; void SetCircularBufferSize(uint32_t aCapacity); diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 8d64878d13e2..ea98d9d77912 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -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; } diff --git a/toolkit/system/dbus/nsNetworkManagerListener.h b/toolkit/system/dbus/nsNetworkManagerListener.h index 4afda1a9fa85..a1a832828707 100644 --- a/toolkit/system/dbus/nsNetworkManagerListener.h +++ b/toolkit/system/dbus/nsNetworkManagerListener.h @@ -20,9 +20,9 @@ public: nsresult Init(); - virtual void RegisterWithConnection(DBusConnection* connection); - virtual void UnregisterWithConnection(DBusConnection* connection); - virtual bool HandleMessage(DBusMessage* msg); + virtual void RegisterWithConnection(DBusConnection* connection) MOZ_OVERRIDE; + virtual void UnregisterWithConnection(DBusConnection* connection) MOZ_OVERRIDE; + virtual bool HandleMessage(DBusMessage* msg) MOZ_OVERRIDE; /** * This gets called when NetworkManager sends us a StateChange signal, From b28b423c322405d58122a2dd73515e2846a249a6 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 26 Jan 2015 22:18:48 -0500 Subject: [PATCH 07/46] Bug 1126128 - Mark TestTrustDomain::VerifySignedData as override; r=bsmith --- security/pkix/test/gtest/pkixbuild_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/pkix/test/gtest/pkixbuild_tests.cpp b/security/pkix/test/gtest/pkixbuild_tests.cpp index df3a34d32753..2e96584f2089 100644 --- a/security/pkix/test/gtest/pkixbuild_tests.cpp +++ b/security/pkix/test/gtest/pkixbuild_tests.cpp @@ -142,7 +142,7 @@ private: } Result VerifySignedData(const SignedDataWithSignature& signedData, - Input subjectPublicKeyInfo) + Input subjectPublicKeyInfo) override { return TestVerifySignedData(signedData, subjectPublicKeyInfo); } From 5c46df76594e091617985f08bdf11fccb9d9dacb Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Sat, 17 Jan 2015 12:39:03 -0500 Subject: [PATCH 08/46] Bug 1122926 - Remove unhelpful configure messages suggesting to use --disable-webgl or install the DirectX SDK; r=glandium --disable-webgl was removed in bug 1052518, and we don't need a separate DirectX SDK installation any more. --- configure.in | 2 -- 1 file changed, 2 deletions(-) diff --git a/configure.in b/configure.in index f5201334eed4..4d6142e962d5 100644 --- a/configure.in +++ b/configure.in @@ -5947,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 @@ -5973,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 From c1ed75bd712b12417a62bc83b165885a4bda7735 Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Tue, 27 Jan 2015 13:39:48 +0000 Subject: [PATCH 09/46] Bug 1125647 - mark some webidl attributes as [Pure]. r=bzbarsky --- dom/webidl/SVGDocument.webidl | 2 +- dom/webidl/SVGPathSeg.webidl | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dom/webidl/SVGDocument.webidl b/dom/webidl/SVGDocument.webidl index 67235e607d59..add04a6b3ccf 100644 --- a/dom/webidl/SVGDocument.webidl +++ b/dom/webidl/SVGDocument.webidl @@ -10,6 +10,6 @@ interface SVGDocument : Document { [Throws] readonly attribute DOMString domain; - [Throws] + [Pure, Throws] readonly attribute SVGElement? rootElement; }; diff --git a/dom/webidl/SVGPathSeg.webidl b/dom/webidl/SVGPathSeg.webidl index 553a74f76b3c..b5ff1abd6099 100644 --- a/dom/webidl/SVGPathSeg.webidl +++ b/dom/webidl/SVGPathSeg.webidl @@ -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; }; From 9841023b4f762f52a65e776b672f195b3773356e Mon Sep 17 00:00:00 2001 From: Heiher Date: Sun, 25 Jan 2015 23:31:00 +0100 Subject: [PATCH 10/46] Bug 1125722 - IonMonkey: MIPS: Fix method ma_b with ImmGCPtr in MacroAssembler-mips. r=rankov --- js/src/jit/mips/MacroAssembler-mips.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jit/mips/MacroAssembler-mips.h b/js/src/jit/mips/MacroAssembler-mips.h index 4fa2cec01930..3b329f2dd264 100644 --- a/js/src/jit/mips/MacroAssembler-mips.h +++ b/js/src/jit/mips/MacroAssembler-mips.h @@ -232,7 +232,7 @@ class MacroAssemblerMIPS : public Assembler void ma_b(Register lhs, ImmGCPtr imm, Label *l, Condition c, JumpKind jumpKind = LongJump) { MOZ_ASSERT(lhs != ScratchRegister); ma_li(ScratchRegister, imm); - ma_b(lhs, Imm32(uint32_t(imm.value)), l, c, jumpKind); + ma_b(lhs, ScratchRegister, l, c, jumpKind); } void ma_b(Register lhs, Address addr, Label *l, Condition c, JumpKind jumpKind = LongJump); void ma_b(Address addr, Imm32 imm, Label *l, Condition c, JumpKind jumpKind = LongJump); From 822c6dc0a176947b4dc8b36e9cb6ec10785aa569 Mon Sep 17 00:00:00 2001 From: Heiher Date: Mon, 26 Jan 2015 17:17:00 +0100 Subject: [PATCH 11/46] Bug 1126097 - IonMonkey: MIPS: Fix mistakes in AssemblerMIPS::as_ins and as_ext. r=rankov --- js/src/jit/mips/Assembler-mips.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/jit/mips/Assembler-mips.cpp b/js/src/jit/mips/Assembler-mips.cpp index 2f452639f98d..9442e50c72e5 100644 --- a/js/src/jit/mips/Assembler-mips.cpp +++ b/js/src/jit/mips/Assembler-mips.cpp @@ -969,7 +969,7 @@ Assembler::as_clz(Register rd, Register rs) BufferOffset Assembler::as_ins(Register rt, Register rs, uint16_t pos, uint16_t size) { - MOZ_ASSERT(pos < 32 && size != 0 && size <= 32 && pos + size != 0 && pos + size >= 32); + MOZ_ASSERT(pos < 32 && size != 0 && size <= 32 && pos + size != 0 && pos + size <= 32); Register rd; rd = Register::FromCode(pos + size - 1); return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_ins).encode()); @@ -978,7 +978,7 @@ Assembler::as_ins(Register rt, Register rs, uint16_t pos, uint16_t size) BufferOffset Assembler::as_ext(Register rt, Register rs, uint16_t pos, uint16_t size) { - MOZ_ASSERT(pos < 32 && size != 0 && size <= 32 && pos + size != 0 && pos + size >= 32); + MOZ_ASSERT(pos < 32 && size != 0 && size <= 32 && pos + size != 0 && pos + size <= 32); Register rd; rd = Register::FromCode(size - 1); return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_ext).encode()); From 3e9595aa5ba3be669d3b7584885e2932c52dad22 Mon Sep 17 00:00:00 2001 From: Michal Novotny Date: Tue, 27 Jan 2015 15:50:18 +0100 Subject: [PATCH 12/46] Bug 1119406 - HTTP cache v2: Doom cache entry when writing of metadata fails, r=honzab --- netwerk/cache2/CacheFile.cpp | 3 ++- netwerk/cache2/CacheFileIOManager.cpp | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/netwerk/cache2/CacheFile.cpp b/netwerk/cache2/CacheFile.cpp index 78792a0096f1..0ed6d54521fa 100644 --- a/netwerk/cache2/CacheFile.cpp +++ b/netwerk/cache2/CacheFile.cpp @@ -612,8 +612,9 @@ CacheFile::OnMetadataWritten(nsresult aResult) MOZ_ASSERT(!mMemoryOnly); MOZ_ASSERT(!mOpeningFile); - if (NS_FAILED(aResult)) { + if (NS_WARN_IF(NS_FAILED(aResult))) { // TODO close streams with an error ??? + SetError(aResult); } if (mOutput || mInputs.Length() || mChunks.Count()) diff --git a/netwerk/cache2/CacheFileIOManager.cpp b/netwerk/cache2/CacheFileIOManager.cpp index 407d727cd5fe..54f1c9e2a193 100644 --- a/netwerk/cache2/CacheFileIOManager.cpp +++ b/netwerk/cache2/CacheFileIOManager.cpp @@ -706,6 +706,10 @@ public: } else { rv = CacheFileIOManager::gInstance->WriteInternal( mHandle, mOffset, mBuf, mCount, mValidate); + if (NS_FAILED(rv) && !mCallback) { + // No listener is going to handle the error, doom the file + CacheFileIOManager::gInstance->DoomFileInternal(mHandle); + } } MOZ_EVENT_TRACER_DONE(static_cast(this), "net::cache::write-background"); From 3402e21567ee708a9cf5c90bab38aa3f2529db10 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Mon, 19 Jan 2015 21:23:42 -0500 Subject: [PATCH 13/46] Bug 1125709. Avoiding using MacIOSurfaceTextureSourceOGL in MacIOSurfaceTextureHostOGL. r=nical Using GLTextureSource gives us better performance because we don't need to call CGLTexImageIOSurface2D everytime we draw. This will eventually let us drop MacIOSurfaceTextureSourceOGL once WebGL on OS X is using MacIOSurfaceTextureHostOGL. --HG-- extra : rebase_source : 95a9b0888d7ddfeae520141e7f932f8555fa58d5 --- gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp | 14 +++++++++++++- gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp index ff10cdd7e6d4..ec993b44a2fc 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp @@ -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; } diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h index a744376a1819..a94d0e6ca247 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h @@ -94,7 +94,7 @@ public: protected: RefPtr mCompositor; - RefPtr mTextureSource; + RefPtr mTextureSource; RefPtr mSurface; }; From 4283c03b52305f0690c952773ac8ea457c82ec91 Mon Sep 17 00:00:00 2001 From: David Major Date: Wed, 21 Jan 2015 18:52:00 -0500 Subject: [PATCH 14/46] Bug 1123778 - Block Lenovo Onekey Theater DLLs. r=bsmedberg --- mozglue/build/WindowsDllBlocklist.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mozglue/build/WindowsDllBlocklist.cpp b/mozglue/build/WindowsDllBlocklist.cpp index d16f44fdaa38..4ce958fdca08 100644 --- a/mozglue/build/WindowsDllBlocklist.cpp +++ b/mozglue/build/WindowsDllBlocklist.cpp @@ -159,6 +159,12 @@ static DllBlockInfo sWindowsDllBlocklist[] = { // Crashes with DesktopTemperature, bug 1046382 { "dtwxsvc.dll", 0x53153234, DllBlockInfo::USE_TIMESTAMP }, + // Startup crashes with Lenovo Onekey Theater, bug 1123778 + { "activedetect32.dll", UNVERSIONED }, + { "activedetect64.dll", UNVERSIONED }, + { "windowsapihookdll32.dll", UNVERSIONED }, + { "windowsapihookdll64.dll", UNVERSIONED }, + { nullptr, 0 } }; From b8fd2ef2f41ea464baa28af9101b8ea7e23fab8e Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Tue, 27 Jan 2015 15:18:43 +0000 Subject: [PATCH 15/46] Bug 1125647 - mark remaining SVGAnimatedXXX webidl attributes as [Constant]. r=dholbert, sr=bzbarsky --- dom/webidl/SVGClipPathElement.webidl | 2 ++ .../SVGComponentTransferFunctionElement.webidl | 7 +++++++ dom/webidl/SVGElement.webidl | 1 + dom/webidl/SVGFEBlendElement.webidl | 3 +++ dom/webidl/SVGFEColorMatrixElement.webidl | 3 +++ dom/webidl/SVGFEComponentTransferElement.webidl | 1 + dom/webidl/SVGFECompositeElement.webidl | 7 +++++++ dom/webidl/SVGFEConvolveMatrixElement.webidl | 12 ++++++++++++ dom/webidl/SVGFEDiffuseLightingElement.webidl | 5 +++++ dom/webidl/SVGFEDisplacementMapElement.webidl | 5 +++++ dom/webidl/SVGFEDistantLightElement.webidl | 2 ++ dom/webidl/SVGFEDropShadowElement.webidl | 5 +++++ dom/webidl/SVGFEGaussianBlurElement.webidl | 3 +++ dom/webidl/SVGFEImageElement.webidl | 1 + dom/webidl/SVGFEMergeNodeElement.webidl | 1 + dom/webidl/SVGFEMorphologyElement.webidl | 4 ++++ dom/webidl/SVGFEOffsetElement.webidl | 3 +++ dom/webidl/SVGFEPointLightElement.webidl | 3 +++ dom/webidl/SVGFESpecularLightingElement.webidl | 6 ++++++ dom/webidl/SVGFESpotLightElement.webidl | 8 ++++++++ dom/webidl/SVGFETileElement.webidl | 1 + dom/webidl/SVGFETurbulenceElement.webidl | 6 ++++++ dom/webidl/SVGFilterElement.webidl | 6 ++++++ .../SVGFilterPrimitiveStandardAttributes.webidl | 5 +++++ dom/webidl/SVGGradientElement.webidl | 3 +++ dom/webidl/SVGLinearGradientElement.webidl | 4 ++++ dom/webidl/SVGMarkerElement.webidl | 7 +++++++ dom/webidl/SVGMaskElement.webidl | 6 ++++++ dom/webidl/SVGPathElement.webidl | 1 + dom/webidl/SVGRadialGradientElement.webidl | 5 +++++ dom/webidl/SVGSVGElement.webidl | 4 ++++ dom/webidl/SVGStopElement.webidl | 1 + dom/webidl/SVGTextContentElement.webidl | 2 ++ dom/webidl/SVGTextPathElement.webidl | 3 +++ dom/webidl/SVGTextPositioningElement.webidl | 5 +++++ dom/webidl/SVGURIReference.webidl | 1 + 36 files changed, 142 insertions(+) diff --git a/dom/webidl/SVGClipPathElement.webidl b/dom/webidl/SVGClipPathElement.webidl index ea21f176d7a4..76a95c633362 100644 --- a/dom/webidl/SVGClipPathElement.webidl +++ b/dom/webidl/SVGClipPathElement.webidl @@ -11,7 +11,9 @@ */ interface SVGClipPathElement : SVGElement { + [Constant] readonly attribute SVGAnimatedEnumeration clipPathUnits; + [Constant] readonly attribute SVGAnimatedTransformList transform; }; diff --git a/dom/webidl/SVGComponentTransferFunctionElement.webidl b/dom/webidl/SVGComponentTransferFunctionElement.webidl index 2da8261b7118..1842fe6f5617 100644 --- a/dom/webidl/SVGComponentTransferFunctionElement.webidl +++ b/dom/webidl/SVGComponentTransferFunctionElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGElement.webidl b/dom/webidl/SVGElement.webidl index 89db7589abf5..6ae75b16a6f1 100644 --- a/dom/webidl/SVGElement.webidl +++ b/dom/webidl/SVGElement.webidl @@ -15,6 +15,7 @@ interface SVGElement : Element { /* [SetterThrows] attribute DOMString xmlbase; */ + [Constant] readonly attribute SVGAnimatedString className; [PutForwards=cssText, Constant] readonly attribute CSSStyleDeclaration style; diff --git a/dom/webidl/SVGFEBlendElement.webidl b/dom/webidl/SVGFEBlendElement.webidl index 2098627dd7a2..5cd469bd5ab6 100644 --- a/dom/webidl/SVGFEBlendElement.webidl +++ b/dom/webidl/SVGFEBlendElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGFEColorMatrixElement.webidl b/dom/webidl/SVGFEColorMatrixElement.webidl index b234f21bd2dc..61d91040d5d0 100644 --- a/dom/webidl/SVGFEColorMatrixElement.webidl +++ b/dom/webidl/SVGFEColorMatrixElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGFEComponentTransferElement.webidl b/dom/webidl/SVGFEComponentTransferElement.webidl index 5a41636e6a4e..6cf6f6d65df3 100644 --- a/dom/webidl/SVGFEComponentTransferElement.webidl +++ b/dom/webidl/SVGFEComponentTransferElement.webidl @@ -11,6 +11,7 @@ */ interface SVGFEComponentTransferElement : SVGElement { + [Constant] readonly attribute SVGAnimatedString in1; }; diff --git a/dom/webidl/SVGFECompositeElement.webidl b/dom/webidl/SVGFECompositeElement.webidl index ed0165089603..3ab983fe0d8b 100644 --- a/dom/webidl/SVGFECompositeElement.webidl +++ b/dom/webidl/SVGFECompositeElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGFEConvolveMatrixElement.webidl b/dom/webidl/SVGFEConvolveMatrixElement.webidl index 1ace1cf11673..27d8e80e764c 100644 --- a/dom/webidl/SVGFEConvolveMatrixElement.webidl +++ b/dom/webidl/SVGFEConvolveMatrixElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGFEDiffuseLightingElement.webidl b/dom/webidl/SVGFEDiffuseLightingElement.webidl index 98cf34c7d373..fb89721d8475 100644 --- a/dom/webidl/SVGFEDiffuseLightingElement.webidl +++ b/dom/webidl/SVGFEDiffuseLightingElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGFEDisplacementMapElement.webidl b/dom/webidl/SVGFEDisplacementMapElement.webidl index 114bc3a1f4f5..461faff91974 100644 --- a/dom/webidl/SVGFEDisplacementMapElement.webidl +++ b/dom/webidl/SVGFEDisplacementMapElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGFEDistantLightElement.webidl b/dom/webidl/SVGFEDistantLightElement.webidl index 78b396f82d02..933befc936ae 100644 --- a/dom/webidl/SVGFEDistantLightElement.webidl +++ b/dom/webidl/SVGFEDistantLightElement.webidl @@ -11,6 +11,8 @@ */ interface SVGFEDistantLightElement : SVGElement { + [Constant] readonly attribute SVGAnimatedNumber azimuth; + [Constant] readonly attribute SVGAnimatedNumber elevation; }; diff --git a/dom/webidl/SVGFEDropShadowElement.webidl b/dom/webidl/SVGFEDropShadowElement.webidl index becce186bbdf..b858fc91cd65 100644 --- a/dom/webidl/SVGFEDropShadowElement.webidl +++ b/dom/webidl/SVGFEDropShadowElement.webidl @@ -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); diff --git a/dom/webidl/SVGFEGaussianBlurElement.webidl b/dom/webidl/SVGFEGaussianBlurElement.webidl index 9a5193be8766..db2101b53516 100644 --- a/dom/webidl/SVGFEGaussianBlurElement.webidl +++ b/dom/webidl/SVGFEGaussianBlurElement.webidl @@ -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); diff --git a/dom/webidl/SVGFEImageElement.webidl b/dom/webidl/SVGFEImageElement.webidl index d691863e4aa6..3262c0d8a2fd 100644 --- a/dom/webidl/SVGFEImageElement.webidl +++ b/dom/webidl/SVGFEImageElement.webidl @@ -11,6 +11,7 @@ */ interface SVGFEImageElement : SVGElement { + [Constant] readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio; }; diff --git a/dom/webidl/SVGFEMergeNodeElement.webidl b/dom/webidl/SVGFEMergeNodeElement.webidl index bec3e5931e09..4ff217ba77a0 100644 --- a/dom/webidl/SVGFEMergeNodeElement.webidl +++ b/dom/webidl/SVGFEMergeNodeElement.webidl @@ -11,5 +11,6 @@ */ interface SVGFEMergeNodeElement : SVGElement { + [Constant] readonly attribute SVGAnimatedString in1; }; diff --git a/dom/webidl/SVGFEMorphologyElement.webidl b/dom/webidl/SVGFEMorphologyElement.webidl index 97190238ebf8..82910a6faa05 100644 --- a/dom/webidl/SVGFEMorphologyElement.webidl +++ b/dom/webidl/SVGFEMorphologyElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGFEOffsetElement.webidl b/dom/webidl/SVGFEOffsetElement.webidl index 0ff9a8187ad7..90132d528800 100644 --- a/dom/webidl/SVGFEOffsetElement.webidl +++ b/dom/webidl/SVGFEOffsetElement.webidl @@ -11,8 +11,11 @@ */ interface SVGFEOffsetElement : SVGElement { + [Constant] readonly attribute SVGAnimatedString in1; + [Constant] readonly attribute SVGAnimatedNumber dx; + [Constant] readonly attribute SVGAnimatedNumber dy; }; diff --git a/dom/webidl/SVGFEPointLightElement.webidl b/dom/webidl/SVGFEPointLightElement.webidl index fc906336e462..232edc45d056 100644 --- a/dom/webidl/SVGFEPointLightElement.webidl +++ b/dom/webidl/SVGFEPointLightElement.webidl @@ -11,7 +11,10 @@ */ interface SVGFEPointLightElement : SVGElement { + [Constant] readonly attribute SVGAnimatedNumber x; + [Constant] readonly attribute SVGAnimatedNumber y; + [Constant] readonly attribute SVGAnimatedNumber z; }; diff --git a/dom/webidl/SVGFESpecularLightingElement.webidl b/dom/webidl/SVGFESpecularLightingElement.webidl index fbe5ab19483b..42b6b0e9c8d4 100644 --- a/dom/webidl/SVGFESpecularLightingElement.webidl +++ b/dom/webidl/SVGFESpecularLightingElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGFESpotLightElement.webidl b/dom/webidl/SVGFESpotLightElement.webidl index c85ffa7d1aab..281d20c8c0bf 100644 --- a/dom/webidl/SVGFESpotLightElement.webidl +++ b/dom/webidl/SVGFESpotLightElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGFETileElement.webidl b/dom/webidl/SVGFETileElement.webidl index d414279bd1a9..38cad60409fc 100644 --- a/dom/webidl/SVGFETileElement.webidl +++ b/dom/webidl/SVGFETileElement.webidl @@ -11,6 +11,7 @@ */ interface SVGFETileElement : SVGElement { + [Constant] readonly attribute SVGAnimatedString in1; }; diff --git a/dom/webidl/SVGFETurbulenceElement.webidl b/dom/webidl/SVGFETurbulenceElement.webidl index 7bb08f557669..45c9d468b2e2 100644 --- a/dom/webidl/SVGFETurbulenceElement.webidl +++ b/dom/webidl/SVGFETurbulenceElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGFilterElement.webidl b/dom/webidl/SVGFilterElement.webidl index 0e4124b97ee6..cffd59ab24ca 100644 --- a/dom/webidl/SVGFilterElement.webidl +++ b/dom/webidl/SVGFilterElement.webidl @@ -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); diff --git a/dom/webidl/SVGFilterPrimitiveStandardAttributes.webidl b/dom/webidl/SVGFilterPrimitiveStandardAttributes.webidl index 9dc94c38bdc2..3319505866af 100644 --- a/dom/webidl/SVGFilterPrimitiveStandardAttributes.webidl +++ b/dom/webidl/SVGFilterPrimitiveStandardAttributes.webidl @@ -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; }; diff --git a/dom/webidl/SVGGradientElement.webidl b/dom/webidl/SVGGradientElement.webidl index fb82cdc889ea..eee562308ea4 100644 --- a/dom/webidl/SVGGradientElement.webidl +++ b/dom/webidl/SVGGradientElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGLinearGradientElement.webidl b/dom/webidl/SVGLinearGradientElement.webidl index 73ee2740699a..200bc47e67ed 100644 --- a/dom/webidl/SVGLinearGradientElement.webidl +++ b/dom/webidl/SVGLinearGradientElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGMarkerElement.webidl b/dom/webidl/SVGMarkerElement.webidl index fb1e9cd7f568..a4f819b2d09c 100644 --- a/dom/webidl/SVGMarkerElement.webidl +++ b/dom/webidl/SVGMarkerElement.webidl @@ -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(); diff --git a/dom/webidl/SVGMaskElement.webidl b/dom/webidl/SVGMaskElement.webidl index 3cf3439b4908..e470f0119f3e 100644 --- a/dom/webidl/SVGMaskElement.webidl +++ b/dom/webidl/SVGMaskElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGPathElement.webidl b/dom/webidl/SVGPathElement.webidl index f41cba008127..08a9904ec28f 100644 --- a/dom/webidl/SVGPathElement.webidl +++ b/dom/webidl/SVGPathElement.webidl @@ -11,6 +11,7 @@ */ interface SVGPathElement : SVGGraphicsElement { + [Constant] readonly attribute SVGAnimatedNumber pathLength; float getTotalLength(); diff --git a/dom/webidl/SVGRadialGradientElement.webidl b/dom/webidl/SVGRadialGradientElement.webidl index 009a9551f062..d4a3724f6aa7 100644 --- a/dom/webidl/SVGRadialGradientElement.webidl +++ b/dom/webidl/SVGRadialGradientElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGSVGElement.webidl b/dom/webidl/SVGSVGElement.webidl index 658d5cbfb445..d0c63f277ec0 100644 --- a/dom/webidl/SVGSVGElement.webidl +++ b/dom/webidl/SVGSVGElement.webidl @@ -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] diff --git a/dom/webidl/SVGStopElement.webidl b/dom/webidl/SVGStopElement.webidl index 9171bd6186cb..d75e52b73399 100644 --- a/dom/webidl/SVGStopElement.webidl +++ b/dom/webidl/SVGStopElement.webidl @@ -11,6 +11,7 @@ */ interface SVGStopElement : SVGElement { + [Constant] readonly attribute SVGAnimatedNumber offset; }; diff --git a/dom/webidl/SVGTextContentElement.webidl b/dom/webidl/SVGTextContentElement.webidl index 2eb949bcbf94..15ec9637309e 100644 --- a/dom/webidl/SVGTextContentElement.webidl +++ b/dom/webidl/SVGTextContentElement.webidl @@ -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(); diff --git a/dom/webidl/SVGTextPathElement.webidl b/dom/webidl/SVGTextPathElement.webidl index 7e330a8ef7df..73a50f3ff47d 100644 --- a/dom/webidl/SVGTextPathElement.webidl +++ b/dom/webidl/SVGTextPathElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGTextPositioningElement.webidl b/dom/webidl/SVGTextPositioningElement.webidl index cfecb839d02a..80b8b94fac9f 100644 --- a/dom/webidl/SVGTextPositioningElement.webidl +++ b/dom/webidl/SVGTextPositioningElement.webidl @@ -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; }; diff --git a/dom/webidl/SVGURIReference.webidl b/dom/webidl/SVGURIReference.webidl index 672349a03c9b..11f94c1917fb 100644 --- a/dom/webidl/SVGURIReference.webidl +++ b/dom/webidl/SVGURIReference.webidl @@ -12,6 +12,7 @@ [NoInterfaceObject] interface SVGURIReference { + [Constant] readonly attribute SVGAnimatedString href; }; From e1844a8d253f0bf02f801009f6d31900ab14139d Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Wed, 17 Dec 2014 13:50:20 -0800 Subject: [PATCH 16/46] Bug 1112774 - Add a raft of other conversion methods to js/public/Conversions.h past just JS::ToObject. r=jorendorff --HG-- extra : rebase_source : 5d04a08a8fd51952283ce2a819149da035311b59 --- dom/base/nsJSUtils.h | 1 + dom/bindings/BindingUtils.h | 1 + dom/bindings/PrimitiveConversions.h | 1 + js/public/Conversions.h | 234 ++++++++++++++++++++++++++-- js/src/jsapi.cpp | 6 +- js/src/jsapi.h | 196 ----------------------- js/src/jsobj.cpp | 2 +- js/src/jsobj.h | 1 + js/src/shell/OSObject.cpp | 2 + 9 files changed, 228 insertions(+), 216 deletions(-) diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h index 257ad344bd13..d696698d8c6b 100644 --- a/dom/base/nsJSUtils.h +++ b/dom/base/nsJSUtils.h @@ -17,6 +17,7 @@ #include "jsapi.h" #include "jsfriendapi.h" +#include "js/Conversions.h" #include "nsString.h" class nsIScriptContext; diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 53846fa2a5fd..7767a18150df 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -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" diff --git a/dom/bindings/PrimitiveConversions.h b/dom/bindings/PrimitiveConversions.h index 14772b7c8481..e09275cf24a3 100644 --- a/dom/bindings/PrimitiveConversions.h +++ b/dom/bindings/PrimitiveConversions.h @@ -16,6 +16,7 @@ #include #include "jsapi.h" +#include "js/Conversions.h" #include "mozilla/Assertions.h" #include "mozilla/ErrorResult.h" #include "mozilla/FloatingPoint.h" diff --git a/js/public/Conversions.h b/js/public/Conversions.h index fb15a4d7127c..0fbad91f4a8c 100644 --- a/js/public/Conversions.h +++ b/js/public/Conversions.h @@ -15,10 +15,228 @@ #include +#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(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 */ diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 9e84ab285a0d..42c72a9fa2ea 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -5942,15 +5942,15 @@ AutoGCRooter::AutoGCRooter(ContextFriendFields *cx, ptrdiff_t tag) *stackTop = this; } -#ifdef DEBUG +#ifdef JS_DEBUG JS_PUBLIC_API(void) -JS::AssertArgumentsAreSane(JSContext *cx, HandleValue value) +JS::detail::AssertArgumentsAreSane(JSContext *cx, HandleValue value) { AssertHeapIsIdle(cx); CHECK_REQUEST(cx); assertSameCompartment(cx, value); } -#endif /* DEBUG */ +#endif /* JS_DEBUG */ JS_PUBLIC_API(void *) JS_EncodeScript(JSContext *cx, HandleScript scriptArg, uint32_t *lengthp) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 89080ef10eeb..f1cde1d88365 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -61,20 +61,6 @@ class JS_PUBLIC_API(AutoCheckRequestDepth) #endif /* JS_DEBUG */ -#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. - */ -JS_PUBLIC_API(void) -AssertArgumentsAreSane(JSContext *cx, JS::HandleValue v); -#else -inline void AssertArgumentsAreSane(JSContext *cx, JS::HandleValue v) { - /* Do nothing */ -} -#endif /* JS_DEBUG */ - /* AutoValueArray roots an internal fixed-size array of Values. */ template class AutoValueArray : public AutoGCRooter @@ -1110,99 +1096,6 @@ JS_ValueToConstructor(JSContext *cx, JS::HandleValue v); extern JS_PUBLIC_API(JSString *) JS_ValueToSource(JSContext *cx, JS::Handle v); -namespace js { -/* - * 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::ToBoolean - */ -extern JS_PUBLIC_API(bool) -ToBooleanSlow(JS::HandleValue v); - -/* - * 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 vp, bool reportScanStack); - -} /* namespace js */ - -namespace JS { - -/* ES5 9.3 ToNumber. */ -MOZ_ALWAYS_INLINE bool -ToNumber(JSContext *cx, HandleValue v, double *out) -{ - AssertArgumentsAreSane(cx, v); - - if (v.isNumber()) { - *out = v.toNumber(); - return true; - } - return js::ToNumberSlow(cx, v, out); -} - -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); -} - -MOZ_ALWAYS_INLINE JSString* -ToString(JSContext *cx, HandleValue v) -{ - if (v.isString()) - return v.toString(); - return js::ToStringSlow(cx, v); -} - -/* ES5 9.9 ToObject. */ -MOZ_ALWAYS_INLINE JSObject* -ToObject(JSContext *cx, HandleValue vp) -{ - if (vp.isObject()) - return &vp.toObject(); - return js::ToObjectSlow(cx, vp, false); -} - -/* - * Implements ES6 draft rev 28 (2014 Oct 14) 7.1.1, second algorithm. - * - * Most users should not call this -- use JS::ToNumber, ToBoolean, or ToString - * instead. This should only be called from custom convert hooks. It implements - * the default conversion behavior shared by most objects in JS, so it's useful - * as a fallback. - */ -extern JS_PUBLIC_API(bool) -OrdinaryToPrimitive(JSContext *cx, JS::HandleObject obj, JSType type, - JS::MutableHandleValue vp); - -} /* namespace JS */ - extern JS_PUBLIC_API(bool) JS_DoubleIsInt32(double d, int32_t *ip); @@ -1212,95 +1105,6 @@ JS_DoubleToInt32(double d); extern JS_PUBLIC_API(uint32_t) JS_DoubleToUint32(double d); - -namespace js { -/* 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::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::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); -} /* namespace js */ - -namespace JS { - -MOZ_ALWAYS_INLINE bool -ToUint16(JSContext *cx, JS::HandleValue v, uint16_t *out) -{ - AssertArgumentsAreSane(cx, v); - - if (v.isInt32()) { - *out = uint16_t(v.toInt32()); - return true; - } - return js::ToUint16Slow(cx, v, out); -} - -MOZ_ALWAYS_INLINE bool -ToInt32(JSContext *cx, JS::HandleValue v, int32_t *out) -{ - AssertArgumentsAreSane(cx, v); - - if (v.isInt32()) { - *out = v.toInt32(); - return true; - } - return js::ToInt32Slow(cx, v, out); -} - -MOZ_ALWAYS_INLINE bool -ToUint32(JSContext *cx, JS::HandleValue v, uint32_t *out) -{ - AssertArgumentsAreSane(cx, v); - - if (v.isInt32()) { - *out = uint32_t(v.toInt32()); - return true; - } - return js::ToUint32Slow(cx, v, out); -} - -MOZ_ALWAYS_INLINE bool -ToInt64(JSContext *cx, JS::HandleValue v, int64_t *out) -{ - AssertArgumentsAreSane(cx, v); - - if (v.isInt32()) { - *out = int64_t(v.toInt32()); - return true; - } - return js::ToInt64Slow(cx, v, out); -} - -MOZ_ALWAYS_INLINE bool -ToUint64(JSContext *cx, JS::HandleValue v, uint64_t *out) -{ - AssertArgumentsAreSane(cx, v); - - if (v.isInt32()) { - /* Account for sign extension of negatives into the longer 64bit space. */ - *out = uint64_t(int64_t(v.toInt32())); - return true; - } - return js::ToUint64Slow(cx, v, out); -} - - -} /* namespace JS */ - extern JS_PUBLIC_API(JSType) JS_TypeOfValue(JSContext *cx, JS::Handle v); diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index d75161157bb7..4f935630d6c4 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3560,7 +3560,7 @@ js::PrimitiveToObject(JSContext *cx, const Value &v) * Callers must handle the already-object case. */ JSObject * -js::ToObjectSlow(JSContext *cx, HandleValue val, bool reportScanStack) +js::ToObjectSlow(JSContext *cx, JS::HandleValue val, bool reportScanStack) { MOZ_ASSERT(!val.isMagic()); MOZ_ASSERT(!val.isObject()); diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 2dee3116cd9a..c0b7b6c1f547 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -20,6 +20,7 @@ #include "gc/Barrier.h" #include "gc/Marking.h" +#include "js/Conversions.h" #include "js/GCAPI.h" #include "js/HeapAPI.h" #include "vm/Shape.h" diff --git a/js/src/shell/OSObject.cpp b/js/src/shell/OSObject.cpp index 6623fe20d777..d8509f8a6bc6 100644 --- a/js/src/shell/OSObject.cpp +++ b/js/src/shell/OSObject.cpp @@ -21,6 +21,8 @@ // For JSFunctionSpecWithHelp #include "jsfriendapi.h" +#include "js/Conversions.h" + using namespace JS; static bool From 66e43513dd2eaf6fa59cfac62dbcb4292d0e0818 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Wed, 7 Jan 2015 10:06:03 -0600 Subject: [PATCH 17/46] Bug 1112774 - Remove JS_DoubleTo{Ui,I}nt32 in favor of JS::To{Ui,I}nt32. r=jorendorff --HG-- extra : rebase_source : 0f526faad2330aea9b8738d476aed5ce9aefde1e --- dom/canvas/CanvasRenderingContext2D.cpp | 25 +++++++++++++------------ js/src/jsapi.cpp | 12 ------------ js/src/jsapi.h | 6 ------ 3 files changed, 13 insertions(+), 30 deletions(-) diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 2104589657a4..3fd0a0935c0c 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -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 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 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); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 42c72a9fa2ea..fa325d05fd0c 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -452,18 +452,6 @@ JS_DoubleIsInt32(double d, int32_t *ip) return mozilla::NumberIsInt32(d, ip); } -JS_PUBLIC_API(int32_t) -JS_DoubleToInt32(double d) -{ - return ToInt32(d); -} - -JS_PUBLIC_API(uint32_t) -JS_DoubleToUint32(double d) -{ - return ToUint32(d); -} - JS_PUBLIC_API(JSType) JS_TypeOfValue(JSContext *cx, HandleValue value) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index f1cde1d88365..57978766bba7 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1099,12 +1099,6 @@ JS_ValueToSource(JSContext *cx, JS::Handle v); extern JS_PUBLIC_API(bool) JS_DoubleIsInt32(double d, int32_t *ip); -extern JS_PUBLIC_API(int32_t) -JS_DoubleToInt32(double d); - -extern JS_PUBLIC_API(uint32_t) -JS_DoubleToUint32(double d); - extern JS_PUBLIC_API(JSType) JS_TypeOfValue(JSContext *cx, JS::Handle v); From 2b8436c2749e280f14c289ec1a7526d8b84e5dd8 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 22 Jan 2015 16:42:12 -0800 Subject: [PATCH 18/46] Bug 1122286 - Add custom line numbers to every expected error in ecma_6/Comprehensions/error-messages.js. The numbers for three error messages are obviously wrong, but they're (before and after this patch) unchecked, so it's not a problem. These numbers will be checked and fixed in followup patches. r=shu --HG-- extra : rebase_source : 96c5bd096fcc4f9c51b3ce4a752459aa124ffae7 --- .../ecma_6/Comprehensions/error-messages.js | 88 ++++++++++--------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/js/src/tests/ecma_6/Comprehensions/error-messages.js b/js/src/tests/ecma_6/Comprehensions/error-messages.js index ee8f9c213fcf..fb5af3fb4e44 100644 --- a/js/src/tests/ecma_6/Comprehensions/error-messages.js +++ b/js/src/tests/ecma_6/Comprehensions/error-messages.js @@ -31,62 +31,64 @@ const FOR_OF_PAREN = error("(for (x of y, z) w)").message; const cases = [ // Expressions involving yield without a value, not currently implemented. Many -// of these errors would need to be updated. -//{ expr: "yield", top: TOP_YIELD, fun: null, gen: GENEXP_YIELD, desc: "simple yield" }, -//{ expr: "1, yield", top: TOP_YIELD, fun: null, gen: GENEXP_YIELD, desc: "simple yield at end of list" }, -//{ expr: "yield, 1", top: TOP_YIELD, fun: YIELD_PAREN, gen: YIELD_PAREN, desc: "simple yield in list" }, -//{ expr: "(yield)", top: TOP_YIELD, fun: null, gen: GENEXP_YIELD, desc: "simple yield, parenthesized" }, -//{ expr: "(1, yield)", top: TOP_YIELD, fun: null, gen: GENEXP_YIELD, desc: "simple yield at end of list, parenthesized" }, -//{ expr: "(yield, 1)", top: TOP_YIELD, fun: YIELD_PAREN, gen: YIELD_PAREN, desc: "simple yield in list, parenthesized" }, -//{ expr: "((((yield))))", top: TOP_YIELD, fun: null, gen: GENEXP_YIELD, desc: "deeply nested yield" }, -//{ expr: "(for (x of []) yield)", top: TOP_YIELD, fun: GENERIC, gen: GENERIC, desc: "simple yield in genexp" }, -//{ expr: "(for (x of []) yield, 1)", top: TOP_YIELD, fun: YIELD_PAREN, gen: YIELD_PAREN, desc: "simple yield in list in genexp" }, -//{ expr: "(for (x of []) 1, yield)", top: TOP_YIELD, fun: GENERIC, gen: GENERIC, desc: "simple yield at end of list in genexp" }, -//{ expr: "(for (x of []) (yield))", top: TOP_YIELD, fun: GENEXP_YIELD, gen: GENEXP_YIELD, desc: "simple yield, parenthesized in genexp" }, -//{ expr: "(for (x of []) 1, (yield))", top: TOP_YIELD, fun: GENEXP_YIELD, gen: GENEXP_YIELD, desc: "simple yield, parenthesized in list in genexp" }, -//{ expr: "(for (x of []) (1, yield))", top: TOP_YIELD, fun: GENEXP_YIELD, gen: GENEXP_YIELD, desc: "simple yield at end of list, parenthesized in genexp" }, -//{ expr: "(for (x of []) 1, (2, yield))", top: TOP_YIELD, fun: GENEXP_YIELD, gen: GENEXP_YIELD, desc: "simple yield at end of list, parenthesized in list in genexp" }, -//{ expr: "(for (x of []) (yield, 1))", top: TOP_YIELD, fun: YIELD_PAREN, gen: YIELD_PAREN, desc: "simple yield in list, parenthesized in genexp" }, -//{ expr: "(for (x of []) 1, (yield, 2))", top: TOP_YIELD, fun: YIELD_PAREN, gen: YIELD_PAREN, desc: "simple yield in list, parenthesized in list in genexp" }, +// of these errors would need to be updated. (Note: line numbers below might be +// mere placeholders, not actually the expected correct behavior -- check before +// blindly uncommenting.) +//{ expr: "yield", top: [TOP_YIELD, 777], fun: null, gen: [GENEXP_YIELD, 2], desc: "simple yield" }, +//{ expr: "1, yield", top: [TOP_YIELD, 777], fun: null, gen: [GENEXP_YIELD, 2], desc: "simple yield at end of list" }, +//{ expr: "yield, 1", top: [TOP_YIELD, 777], fun: [YIELD_PAREN, 2], gen: [YIELD_PAREN, 2], desc: "simple yield in list" }, +//{ expr: "(yield)", top: [TOP_YIELD, 777], fun: null, gen: [GENEXP_YIELD, 2], desc: "simple yield, parenthesized" }, +//{ expr: "(1, yield)", top: [TOP_YIELD, 777], fun: null, gen: [GENEXP_YIELD, 2], desc: "simple yield at end of list, parenthesized" }, +//{ expr: "(yield, 1)", top: [TOP_YIELD, 777], fun: [YIELD_PAREN, 2], gen: [YIELD_PAREN, 2], desc: "simple yield in list, parenthesized" }, +//{ expr: "((((yield))))", top: [TOP_YIELD, 777], fun: null, gen: [GENEXP_YIELD, 2], desc: "deeply nested yield" }, +//{ expr: "(for (x of []) yield)", top: [TOP_YIELD, 777], fun: [GENERIC, 777], gen: [GENERIC, 777], desc: "simple yield in genexp" }, +//{ expr: "(for (x of []) yield, 1)", top: [TOP_YIELD, 777], fun: [YIELD_PAREN, 2], gen: [YIELD_PAREN, 2], desc: "simple yield in list in genexp" }, +//{ expr: "(for (x of []) 1, yield)", top: [TOP_YIELD, 777], fun: [GENERIC, 777], gen: [GENERIC, 777], desc: "simple yield at end of list in genexp" }, +//{ expr: "(for (x of []) (yield))", top: [TOP_YIELD, 777], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], desc: "simple yield, parenthesized in genexp" }, +//{ expr: "(for (x of []) 1, (yield))", top: [TOP_YIELD, 777], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], desc: "simple yield, parenthesized in list in genexp" }, +//{ expr: "(for (x of []) (1, yield))", top: [TOP_YIELD, 777], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], desc: "simple yield at end of list, parenthesized in genexp" }, +//{ expr: "(for (x of []) 1, (2, yield))", top: [TOP_YIELD, 777], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], desc: "simple yield at end of list, parenthesized in list in genexp" }, +//{ expr: "(for (x of []) (yield, 1))", top: [TOP_YIELD, 777], fun: [YIELD_PAREN, 2], gen: [YIELD_PAREN, 2], desc: "simple yield in list, parenthesized in genexp" }, +//{ expr: "(for (x of []) 1, (yield, 2))", top: [TOP_YIELD, 777], fun: [YIELD_PAREN, 2], gen: [YIELD_PAREN, 2], desc: "simple yield in list, parenthesized in list in genexp" }, //{ expr: "(for (x of []) (function*() { yield }))", top: null, fun: null, gen: null, desc: "legal yield in nested function" }, // yield expressions - { expr: "yield 1", top: MISSING_SEMI, fun: MISSING_SEMI, gen: null, genexp: GENEXP_YIELD, desc: "yield w/ arg" }, - { expr: "1, yield 2", top: MISSING_SEMI, fun: MISSING_SEMI, gen: null, genexp: FOR_OF_PAREN, desc: "yield w/ arg at end of list" }, - { expr: "yield 1, 2", top: MISSING_SEMI, fun: MISSING_SEMI, gen: null, genexp: FOR_OF_PAREN, desc: "yield w/ arg in list" }, - { expr: "(yield 1)", top: MISSING_PAREN, fun: MISSING_PAREN, gen: null, genexp: GENEXP_YIELD, desc: "yield w/ arg, parenthesized" }, - { expr: "(1, yield 2)", top: MISSING_PAREN, fun: MISSING_PAREN, gen: null, genexp: GENEXP_YIELD, desc: "yield w/ arg at end of list, parenthesized" }, - { expr: "(yield 1, 2)", top: MISSING_PAREN, fun: MISSING_PAREN, gen: null, genexp: YIELD_PAREN, desc: "yield w/ arg in list, parenthesized" }, + { expr: "yield 1", top: [MISSING_SEMI, 2], fun: [MISSING_SEMI, 2], gen: null, genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg" }, + { expr: "1, yield 2", top: [MISSING_SEMI, 2], fun: [MISSING_SEMI, 2], gen: null, genexp: [FOR_OF_PAREN, 9999], desc: "yield w/ arg at end of list" }, + { expr: "yield 1, 2", top: [MISSING_SEMI, 2], fun: [MISSING_SEMI, 2], gen: null, genexp: [FOR_OF_PAREN, 9999], desc: "yield w/ arg in list" }, + { expr: "(yield 1)", top: [MISSING_PAREN, 2], fun: [MISSING_PAREN, 2], gen: null, genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg, parenthesized" }, + { expr: "(1, yield 2)", top: [MISSING_PAREN, 2], fun: [MISSING_PAREN, 2], gen: null, genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg at end of list, parenthesized" }, + { expr: "(yield 1, 2)", top: [MISSING_PAREN, 2], fun: [MISSING_PAREN, 2], gen: null, genexp: [YIELD_PAREN, 2], desc: "yield w/ arg in list, parenthesized" }, // deeply nested yield expressions - { expr: "((((yield 1))))", top: MISSING_PAREN, fun: MISSING_PAREN, gen: null, genexp: GENEXP_YIELD, desc: "deeply nested yield w/ arg" }, + { expr: "((((yield 1))))", top: [MISSING_PAREN, 2], fun: [MISSING_PAREN, 2], gen: null, genexp: [GENEXP_YIELD, 2], desc: "deeply nested yield w/ arg" }, // arguments { expr: "arguments", top: null, fun: null, gen: null, genexp: null, desc: "arguments in list" }, - { expr: "1, arguments", top: null, fun: null, gen: null, genexp: FOR_OF_PAREN, desc: "arguments in list" }, + { expr: "1, arguments", top: null, fun: null, gen: null, genexp: [FOR_OF_PAREN, 9999], desc: "arguments in list" }, // yield in generator expressions - { expr: "(for (x of []) yield 1)", top: GENEXP_YIELD, fun: GENEXP_YIELD, gen: GENEXP_YIELD, genexp: GENEXP_YIELD, desc: "yield w/ arg in genexp" }, - { expr: "(for (x of []) yield 1, 2)", top: GENEXP_YIELD, fun: GENEXP_YIELD, gen: GENEXP_YIELD, genexp: GENEXP_YIELD, desc: "yield w/ arg in list in genexp" }, - { expr: "(for (x of []) 1, yield 2)", top: PAREN_PAREN, fun: PAREN_PAREN, gen: PAREN_PAREN, genexp: PAREN_PAREN, desc: "yield w/ arg at end of list in genexp" }, - { expr: "(for (x of []) (yield 1))", top: GENEXP_YIELD, fun: GENEXP_YIELD, gen: GENEXP_YIELD, genexp: GENEXP_YIELD, desc: "yield w/ arg, parenthesized in genexp" }, - { expr: "(for (x of []) 1, (yield 2))", top: PAREN_PAREN, fun: PAREN_PAREN, gen: PAREN_PAREN, genexp: PAREN_PAREN, desc: "yield w/ arg, parenthesized in list in genexp" }, - { expr: "(for (x of []) (1, yield 2))", top: GENEXP_YIELD, fun: GENEXP_YIELD, gen: GENEXP_YIELD, genexp: GENEXP_YIELD, desc: "yield w/ arg at end of list, parenthesized in genexp" }, - { expr: "(for (x of []) 1, (2, yield 3))", top: PAREN_PAREN, fun: PAREN_PAREN, gen: PAREN_PAREN, genexp: PAREN_PAREN, desc: "yield w/ arg at end of list, parenthesized in list in genexp" }, - { expr: "(for (x of []) (yield 1, 2))", top: YIELD_PAREN, fun: YIELD_PAREN, gen: YIELD_PAREN, genexp: YIELD_PAREN, desc: "yield w/ arg in list, parenthesized in genexp" }, - { expr: "(for (x of []) 1, (yield 2, 3))", top: PAREN_PAREN, fun: PAREN_PAREN, gen: PAREN_PAREN, genexp: PAREN_PAREN, desc: "yield w/ arg in list, parenthesized in list in genexp" }, + { expr: "(for (x of []) yield 1)", top: [GENEXP_YIELD, 2], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg in genexp" }, + { expr: "(for (x of []) yield 1, 2)", top: [GENEXP_YIELD, 2], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg in list in genexp" }, + { expr: "(for (x of []) 1, yield 2)", top: [PAREN_PAREN, 9999], fun: [PAREN_PAREN, 9999], gen: [PAREN_PAREN, 9999], genexp: [PAREN_PAREN, 9999], desc: "yield w/ arg at end of list in genexp" }, + { expr: "(for (x of []) (yield 1))", top: [GENEXP_YIELD, 2], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg, parenthesized in genexp" }, + { expr: "(for (x of []) 1, (yield 2))", top: [PAREN_PAREN, 9999], fun: [PAREN_PAREN, 9999], gen: [PAREN_PAREN, 9999], genexp: [PAREN_PAREN, 9999], desc: "yield w/ arg, parenthesized in list in genexp" }, + { expr: "(for (x of []) (1, yield 2))", top: [GENEXP_YIELD, 2], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg at end of list, parenthesized in genexp" }, + { expr: "(for (x of []) 1, (2, yield 3))", top: [PAREN_PAREN, 9999], fun: [PAREN_PAREN, 9999], gen: [PAREN_PAREN, 9999], genexp: [PAREN_PAREN, 9999], desc: "yield w/ arg at end of list, parenthesized in list in genexp" }, + { expr: "(for (x of []) (yield 1, 2))", top: [YIELD_PAREN, 2], fun: [YIELD_PAREN, 2], gen: [YIELD_PAREN, 2], genexp: [YIELD_PAREN, 2], desc: "yield w/ arg in list, parenthesized in genexp" }, + { expr: "(for (x of []) 1, (yield 2, 3))", top: [PAREN_PAREN, 9999], fun: [PAREN_PAREN, 9999], gen: [PAREN_PAREN, 9999], genexp: [PAREN_PAREN, 9999], desc: "yield w/ arg in list, parenthesized in list in genexp" }, // deeply nested yield in generator expressions - { expr: "(for (x of []) (((1, yield 2))))", top: GENEXP_YIELD, fun: GENEXP_YIELD, gen: GENEXP_YIELD, genexp: GENEXP_YIELD, desc: "deeply nested yield in genexp" }, - { expr: "(for (y of []) (for (x of []) ((1, yield 2))))", top: GENEXP_YIELD, fun: GENEXP_YIELD, gen: GENEXP_YIELD, genexp: GENEXP_YIELD, desc: "deeply nested yield in multiple genexps" }, + { expr: "(for (x of []) (((1, yield 2))))", top: [GENEXP_YIELD, 2], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], genexp: [GENEXP_YIELD, 2], desc: "deeply nested yield in genexp" }, + { expr: "(for (y of []) (for (x of []) ((1, yield 2))))", top: [GENEXP_YIELD, 2], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], genexp: [GENEXP_YIELD, 2], desc: "deeply nested yield in multiple genexps" }, // arguments in generator expressions { expr: "(for (x of []) arguments)", top: null, fun: null, gen: null, genexp: null, desc: "simple arguments in genexp" }, - { expr: "(for (x of []) 1, arguments)", top: BAD_GENERATOR_SYNTAX, fun: BAD_GENERATOR_SYNTAX, gen: BAD_GENERATOR_SYNTAX, genexp: BAD_GENERATOR_SYNTAX, desc: "arguments in list in genexp" }, + { expr: "(for (x of []) 1, arguments)", top: [BAD_GENERATOR_SYNTAX, 9999], fun: [BAD_GENERATOR_SYNTAX, 9999], gen: [BAD_GENERATOR_SYNTAX, 9999], genexp: [BAD_GENERATOR_SYNTAX, 9999], desc: "arguments in list in genexp" }, { expr: "(for (x of []) (arguments))", top: null, fun: null, gen: null, genexp: null, desc: "arguments, parenthesized in genexp" }, - { expr: "(for (x of []) 1, (arguments))", top: BAD_GENERATOR_SYNTAX, fun: BAD_GENERATOR_SYNTAX, gen: BAD_GENERATOR_SYNTAX, genexp: BAD_GENERATOR_SYNTAX, desc: "arguments, parenthesized in list in genexp" }, + { expr: "(for (x of []) 1, (arguments))", top: [BAD_GENERATOR_SYNTAX, 9999], fun: [BAD_GENERATOR_SYNTAX, 9999], gen: [BAD_GENERATOR_SYNTAX, 9999], genexp: [BAD_GENERATOR_SYNTAX, 9999], desc: "arguments, parenthesized in list in genexp" }, { expr: "(for (x of []) (1, arguments))", top: null, fun: null, gen: null, genexp: null, desc: "arguments in list, parenthesized in genexp" }, - { expr: "(for (x of []) 1, (2, arguments))", top: BAD_GENERATOR_SYNTAX, fun: BAD_GENERATOR_SYNTAX, gen: BAD_GENERATOR_SYNTAX, genexp: BAD_GENERATOR_SYNTAX, desc: "arguments in list, parenthesized in list in genexp" }, + { expr: "(for (x of []) 1, (2, arguments))", top: [BAD_GENERATOR_SYNTAX, 9999], fun: [BAD_GENERATOR_SYNTAX, 9999], gen: [BAD_GENERATOR_SYNTAX, 9999], genexp: [BAD_GENERATOR_SYNTAX, 9999], desc: "arguments in list, parenthesized in list in genexp" }, // deeply nested arguments in generator expressions { expr: "(for (x of []) (((1, arguments))))", top: null, fun: null, gen: null, genexp: null, desc: "deeply nested arguments in genexp" }, @@ -110,15 +112,15 @@ function splitKeyword(str) { replace(/arguments/, '\narguments\n'); } -function expectError1(err, ctx, msg) { +function expectError1(err, ctx, msg, lineNumber) { reportCompare('object', typeof err, 'exn for: ' + msg); reportCompare(ctx, err.message, 'exn message for: ' + msg); if (ctx !== BAD_GENERATOR_SYNTAX && ctx != PAREN_PAREN && ctx != FOR_OF_PAREN) - reportCompare(2, err.lineNumber, 'exn token for: ' + msg); + reportCompare(lineNumber, err.lineNumber, 'exn token for: ' + msg); } -function expectError(expr, wrapCtx, expect, msg) { - expectError1(error(wrapCtx(expr)), expect, msg); +function expectError(expr, wrapCtx, [expect, lineNumber], msg) { + expectError1(error(wrapCtx(expr)), expect, msg, lineNumber); } function expectSuccess(err, msg) { From 3c497259118f095450b65fcd140b7b9e2cf6a65e Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 22 Jan 2015 16:57:22 -0800 Subject: [PATCH 19/46] Bug 1122286 - Add correct line numbers to the tests checking for the correct error parsing the iterable in a for-of comprehension. r=shu --HG-- extra : rebase_source : c6ba002caccfb9d74f8a54b86405a3bd424228ce --- js/src/tests/ecma_6/Comprehensions/error-messages.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/src/tests/ecma_6/Comprehensions/error-messages.js b/js/src/tests/ecma_6/Comprehensions/error-messages.js index fb5af3fb4e44..f121cc2c5516 100644 --- a/js/src/tests/ecma_6/Comprehensions/error-messages.js +++ b/js/src/tests/ecma_6/Comprehensions/error-messages.js @@ -54,8 +54,8 @@ const cases = [ // yield expressions { expr: "yield 1", top: [MISSING_SEMI, 2], fun: [MISSING_SEMI, 2], gen: null, genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg" }, - { expr: "1, yield 2", top: [MISSING_SEMI, 2], fun: [MISSING_SEMI, 2], gen: null, genexp: [FOR_OF_PAREN, 9999], desc: "yield w/ arg at end of list" }, - { expr: "yield 1, 2", top: [MISSING_SEMI, 2], fun: [MISSING_SEMI, 2], gen: null, genexp: [FOR_OF_PAREN, 9999], desc: "yield w/ arg in list" }, + { expr: "1, yield 2", top: [MISSING_SEMI, 2], fun: [MISSING_SEMI, 2], gen: null, genexp: [FOR_OF_PAREN, 1], desc: "yield w/ arg at end of list" }, + { expr: "yield 1, 2", top: [MISSING_SEMI, 2], fun: [MISSING_SEMI, 2], gen: null, genexp: [FOR_OF_PAREN, 3], desc: "yield w/ arg in list" }, { expr: "(yield 1)", top: [MISSING_PAREN, 2], fun: [MISSING_PAREN, 2], gen: null, genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg, parenthesized" }, { expr: "(1, yield 2)", top: [MISSING_PAREN, 2], fun: [MISSING_PAREN, 2], gen: null, genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg at end of list, parenthesized" }, { expr: "(yield 1, 2)", top: [MISSING_PAREN, 2], fun: [MISSING_PAREN, 2], gen: null, genexp: [YIELD_PAREN, 2], desc: "yield w/ arg in list, parenthesized" }, @@ -65,7 +65,7 @@ const cases = [ // arguments { expr: "arguments", top: null, fun: null, gen: null, genexp: null, desc: "arguments in list" }, - { expr: "1, arguments", top: null, fun: null, gen: null, genexp: [FOR_OF_PAREN, 9999], desc: "arguments in list" }, + { expr: "1, arguments", top: null, fun: null, gen: null, genexp: [FOR_OF_PAREN, 1], desc: "arguments in list" }, // yield in generator expressions { expr: "(for (x of []) yield 1)", top: [GENEXP_YIELD, 2], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg in genexp" }, @@ -115,7 +115,7 @@ function splitKeyword(str) { function expectError1(err, ctx, msg, lineNumber) { reportCompare('object', typeof err, 'exn for: ' + msg); reportCompare(ctx, err.message, 'exn message for: ' + msg); - if (ctx !== BAD_GENERATOR_SYNTAX && ctx != PAREN_PAREN && ctx != FOR_OF_PAREN) + if (ctx !== BAD_GENERATOR_SYNTAX && ctx != PAREN_PAREN) reportCompare(lineNumber, err.lineNumber, 'exn token for: ' + msg); } From a52edb0d6a3a201da21774d1928a7d16a19f5c57 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 22 Jan 2015 17:10:25 -0800 Subject: [PATCH 20/46] Bug 1122286 - Add proper expected line numbers for all unparenthesized comma expressions as tail expression in comprehensions (that is, |(for (x of []) 1, 2)|). The comma isn't considered part of the expression, so a closing parenthesis is expected where the comma is. And because *all* of these strings have |1, | at the starts of these, every single one has line number 1. r=shu --HG-- extra : rebase_source : 1eef0f2cec1c4de3dabfb98779b4e49ad25d364c --- .../ecma_6/Comprehensions/error-messages.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/js/src/tests/ecma_6/Comprehensions/error-messages.js b/js/src/tests/ecma_6/Comprehensions/error-messages.js index f121cc2c5516..31b09875da2d 100644 --- a/js/src/tests/ecma_6/Comprehensions/error-messages.js +++ b/js/src/tests/ecma_6/Comprehensions/error-messages.js @@ -70,13 +70,13 @@ const cases = [ // yield in generator expressions { expr: "(for (x of []) yield 1)", top: [GENEXP_YIELD, 2], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg in genexp" }, { expr: "(for (x of []) yield 1, 2)", top: [GENEXP_YIELD, 2], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg in list in genexp" }, - { expr: "(for (x of []) 1, yield 2)", top: [PAREN_PAREN, 9999], fun: [PAREN_PAREN, 9999], gen: [PAREN_PAREN, 9999], genexp: [PAREN_PAREN, 9999], desc: "yield w/ arg at end of list in genexp" }, + { expr: "(for (x of []) 1, yield 2)", top: [PAREN_PAREN, 1], fun: [PAREN_PAREN, 1], gen: [PAREN_PAREN, 1], genexp: [PAREN_PAREN, 1], desc: "yield w/ arg at end of list in genexp" }, { expr: "(for (x of []) (yield 1))", top: [GENEXP_YIELD, 2], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg, parenthesized in genexp" }, - { expr: "(for (x of []) 1, (yield 2))", top: [PAREN_PAREN, 9999], fun: [PAREN_PAREN, 9999], gen: [PAREN_PAREN, 9999], genexp: [PAREN_PAREN, 9999], desc: "yield w/ arg, parenthesized in list in genexp" }, + { expr: "(for (x of []) 1, (yield 2))", top: [PAREN_PAREN, 1], fun: [PAREN_PAREN, 1], gen: [PAREN_PAREN, 1], genexp: [PAREN_PAREN, 1], desc: "yield w/ arg, parenthesized in list in genexp" }, { expr: "(for (x of []) (1, yield 2))", top: [GENEXP_YIELD, 2], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg at end of list, parenthesized in genexp" }, - { expr: "(for (x of []) 1, (2, yield 3))", top: [PAREN_PAREN, 9999], fun: [PAREN_PAREN, 9999], gen: [PAREN_PAREN, 9999], genexp: [PAREN_PAREN, 9999], desc: "yield w/ arg at end of list, parenthesized in list in genexp" }, + { expr: "(for (x of []) 1, (2, yield 3))", top: [PAREN_PAREN, 1], fun: [PAREN_PAREN, 1], gen: [PAREN_PAREN, 1], genexp: [PAREN_PAREN, 1], desc: "yield w/ arg at end of list, parenthesized in list in genexp" }, { expr: "(for (x of []) (yield 1, 2))", top: [YIELD_PAREN, 2], fun: [YIELD_PAREN, 2], gen: [YIELD_PAREN, 2], genexp: [YIELD_PAREN, 2], desc: "yield w/ arg in list, parenthesized in genexp" }, - { expr: "(for (x of []) 1, (yield 2, 3))", top: [PAREN_PAREN, 9999], fun: [PAREN_PAREN, 9999], gen: [PAREN_PAREN, 9999], genexp: [PAREN_PAREN, 9999], desc: "yield w/ arg in list, parenthesized in list in genexp" }, + { expr: "(for (x of []) 1, (yield 2, 3))", top: [PAREN_PAREN, 1], fun: [PAREN_PAREN, 1], gen: [PAREN_PAREN, 1], genexp: [PAREN_PAREN, 1], desc: "yield w/ arg in list, parenthesized in list in genexp" }, // deeply nested yield in generator expressions { expr: "(for (x of []) (((1, yield 2))))", top: [GENEXP_YIELD, 2], fun: [GENEXP_YIELD, 2], gen: [GENEXP_YIELD, 2], genexp: [GENEXP_YIELD, 2], desc: "deeply nested yield in genexp" }, @@ -84,11 +84,11 @@ const cases = [ // arguments in generator expressions { expr: "(for (x of []) arguments)", top: null, fun: null, gen: null, genexp: null, desc: "simple arguments in genexp" }, - { expr: "(for (x of []) 1, arguments)", top: [BAD_GENERATOR_SYNTAX, 9999], fun: [BAD_GENERATOR_SYNTAX, 9999], gen: [BAD_GENERATOR_SYNTAX, 9999], genexp: [BAD_GENERATOR_SYNTAX, 9999], desc: "arguments in list in genexp" }, + { expr: "(for (x of []) 1, arguments)", top: [BAD_GENERATOR_SYNTAX, 1], fun: [BAD_GENERATOR_SYNTAX, 1], gen: [BAD_GENERATOR_SYNTAX, 1], genexp: [BAD_GENERATOR_SYNTAX, 1], desc: "arguments in list in genexp" }, { expr: "(for (x of []) (arguments))", top: null, fun: null, gen: null, genexp: null, desc: "arguments, parenthesized in genexp" }, - { expr: "(for (x of []) 1, (arguments))", top: [BAD_GENERATOR_SYNTAX, 9999], fun: [BAD_GENERATOR_SYNTAX, 9999], gen: [BAD_GENERATOR_SYNTAX, 9999], genexp: [BAD_GENERATOR_SYNTAX, 9999], desc: "arguments, parenthesized in list in genexp" }, + { expr: "(for (x of []) 1, (arguments))", top: [BAD_GENERATOR_SYNTAX, 1], fun: [BAD_GENERATOR_SYNTAX, 1], gen: [BAD_GENERATOR_SYNTAX, 1], genexp: [BAD_GENERATOR_SYNTAX, 1], desc: "arguments, parenthesized in list in genexp" }, { expr: "(for (x of []) (1, arguments))", top: null, fun: null, gen: null, genexp: null, desc: "arguments in list, parenthesized in genexp" }, - { expr: "(for (x of []) 1, (2, arguments))", top: [BAD_GENERATOR_SYNTAX, 9999], fun: [BAD_GENERATOR_SYNTAX, 9999], gen: [BAD_GENERATOR_SYNTAX, 9999], genexp: [BAD_GENERATOR_SYNTAX, 9999], desc: "arguments in list, parenthesized in list in genexp" }, + { expr: "(for (x of []) 1, (2, arguments))", top: [BAD_GENERATOR_SYNTAX, 1], fun: [BAD_GENERATOR_SYNTAX, 1], gen: [BAD_GENERATOR_SYNTAX, 1], genexp: [BAD_GENERATOR_SYNTAX, 1], desc: "arguments in list, parenthesized in list in genexp" }, // deeply nested arguments in generator expressions { expr: "(for (x of []) (((1, arguments))))", top: null, fun: null, gen: null, genexp: null, desc: "deeply nested arguments in genexp" }, @@ -115,8 +115,7 @@ function splitKeyword(str) { function expectError1(err, ctx, msg, lineNumber) { reportCompare('object', typeof err, 'exn for: ' + msg); reportCompare(ctx, err.message, 'exn message for: ' + msg); - if (ctx !== BAD_GENERATOR_SYNTAX && ctx != PAREN_PAREN) - reportCompare(lineNumber, err.lineNumber, 'exn token for: ' + msg); + reportCompare(lineNumber, err.lineNumber, 'exn token for: ' + msg); } function expectError(expr, wrapCtx, [expect, lineNumber], msg) { From d6dbb2722c24d9716159322f7774f6d97d121036 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 15 Jan 2015 15:01:54 -0800 Subject: [PATCH 21/46] Bug 1122286 - Correctly detect unparenthesized yield expressions in argument lists when syntax parsing and report a syntax error. r=jorendorff on the first version, f=shu on a version functionally equivalent but with a different paint job --HG-- extra : rebase_source : 4b630f573b90981c0c6cee8b3bfd92ce06173127 --- js/src/frontend/FullParseHandler.h | 42 +++++-- js/src/frontend/Parser.cpp | 33 +++-- js/src/frontend/SyntaxParseHandler.h | 113 ++++++++++++++---- .../ecma_6/Comprehensions/error-messages.js | 4 +- js/src/tests/ecma_6/Generators/syntax.js | 2 +- 5 files changed, 144 insertions(+), 50 deletions(-) diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 60b153c6350c..247cc7a079a8 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -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 *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_(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; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 88ad13efdd73..b9bfbf45fc39 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -2884,10 +2884,9 @@ Parser::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::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::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::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::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::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::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::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::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(); diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index 49f44f51cf9c..d020aa403747 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -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 *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 *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) {} diff --git a/js/src/tests/ecma_6/Comprehensions/error-messages.js b/js/src/tests/ecma_6/Comprehensions/error-messages.js index 31b09875da2d..ccbea8d8c344 100644 --- a/js/src/tests/ecma_6/Comprehensions/error-messages.js +++ b/js/src/tests/ecma_6/Comprehensions/error-messages.js @@ -55,10 +55,10 @@ const cases = [ // yield expressions { expr: "yield 1", top: [MISSING_SEMI, 2], fun: [MISSING_SEMI, 2], gen: null, genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg" }, { expr: "1, yield 2", top: [MISSING_SEMI, 2], fun: [MISSING_SEMI, 2], gen: null, genexp: [FOR_OF_PAREN, 1], desc: "yield w/ arg at end of list" }, - { expr: "yield 1, 2", top: [MISSING_SEMI, 2], fun: [MISSING_SEMI, 2], gen: null, genexp: [FOR_OF_PAREN, 3], desc: "yield w/ arg in list" }, + { expr: "yield 1, 2", top: [MISSING_SEMI, 2], fun: [MISSING_SEMI, 2], gen: [YIELD_PAREN, 3], genexp: [FOR_OF_PAREN, 3], desc: "yield w/ arg in list" }, { expr: "(yield 1)", top: [MISSING_PAREN, 2], fun: [MISSING_PAREN, 2], gen: null, genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg, parenthesized" }, { expr: "(1, yield 2)", top: [MISSING_PAREN, 2], fun: [MISSING_PAREN, 2], gen: null, genexp: [GENEXP_YIELD, 2], desc: "yield w/ arg at end of list, parenthesized" }, - { expr: "(yield 1, 2)", top: [MISSING_PAREN, 2], fun: [MISSING_PAREN, 2], gen: null, genexp: [YIELD_PAREN, 2], desc: "yield w/ arg in list, parenthesized" }, + { expr: "(yield 1, 2)", top: [MISSING_PAREN, 2], fun: [MISSING_PAREN, 2], gen: [YIELD_PAREN, 3], genexp: [YIELD_PAREN, 2], desc: "yield w/ arg in list, parenthesized" }, // deeply nested yield expressions { expr: "((((yield 1))))", top: [MISSING_PAREN, 2], fun: [MISSING_PAREN, 2], gen: null, genexp: [GENEXP_YIELD, 2], desc: "deeply nested yield w/ arg" }, diff --git a/js/src/tests/ecma_6/Generators/syntax.js b/js/src/tests/ecma_6/Generators/syntax.js index 8c5f851773a3..98af714204e3 100644 --- a/js/src/tests/ecma_6/Generators/syntax.js +++ b/js/src/tests/ecma_6/Generators/syntax.js @@ -34,7 +34,7 @@ function* g() { function* g() { (yield) } function* g() { [yield] } function* g() { {yield} } -function* g() { yield, yield } +function* g() { (yield), (yield) } function* g() { yield; yield } function* g() { (yield) ? yield : yield } function* g() { From cfc0f2faadb804cb5192c3855229ff4057637385 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Sat, 24 Jan 2015 04:16:50 -0800 Subject: [PATCH 22/46] Bug 1111101 - Add a test. (This was fixed by another bug since its filing, woo.) r=test --HG-- extra : rebase_source : 5e2fca4e1f1f84e38634af7090c222330c4a42e7 --- ...e-parenthesized-early-error-strict-mode.js | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 js/src/tests/ecma_6/Expressions/delete-name-parenthesized-early-error-strict-mode.js diff --git a/js/src/tests/ecma_6/Expressions/delete-name-parenthesized-early-error-strict-mode.js b/js/src/tests/ecma_6/Expressions/delete-name-parenthesized-early-error-strict-mode.js new file mode 100644 index 000000000000..d28afb665c2c --- /dev/null +++ b/js/src/tests/ecma_6/Expressions/delete-name-parenthesized-early-error-strict-mode.js @@ -0,0 +1,76 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 1111101; +var summary = + "delete (foo), delete ((foo)), and so on are strict mode early errors"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function checkSyntaxError(code) +{ + function helper(maker) + { + var earlyError = false; + try + { + var f = maker(code); + + var error = "no early error, created a function with code <" + code + ">"; + try + { + f(); + error += ", and the function can be called without error"; + } + catch (e) + { + error +=", and calling the function throws " + e; + } + + throw new Error(error); + } + catch (e) + { + assertEq(e instanceof SyntaxError, true, + "expected syntax error, got " + e); + } + } + + helper(Function); + helper(eval); +} + +checkSyntaxError("function f() { 'use strict'; delete escape; } f();"); +checkSyntaxError("function f() { 'use strict'; delete escape; }"); +checkSyntaxError("function f() { 'use strict'; delete (escape); } f();"); +checkSyntaxError("function f() { 'use strict'; delete (escape); }"); +checkSyntaxError("function f() { 'use strict'; delete ((escape)); } f();"); +checkSyntaxError("function f() { 'use strict'; delete ((escape)); }"); + +// Meanwhile, non-strict all of these should work + +function checkFine(code) +{ + Function(code); + (1, eval)(code); // indirect, to be consistent w/above +} + +checkFine("function f() { delete escape; } f();"); +checkFine("function f() { delete escape; }"); +checkFine("function f() { delete (escape); } f();"); +checkFine("function f() { delete (escape); }"); +checkFine("function f() { delete ((escape)); } f();"); +checkFine("function f() { delete ((escape)); }"); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); From 246a76fd61189c3cf58eb1634490923e0a9f6e17 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Mon, 26 Jan 2015 17:14:59 -0800 Subject: [PATCH 23/46] Bug 949220 - Make all the Intl objects' finalizers tiptoe around an unavoidable, intermediate-state OOM bug during construction of these objects. The underlying issue sadly remains. r=efaust --HG-- extra : rebase_source : 3f771c10849284253e2f6b4a367142c67b4e7fee --- js/src/builtin/Intl.cpp | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/js/src/builtin/Intl.cpp b/js/src/builtin/Intl.cpp index 3e5714567892..425a08075ef1 100644 --- a/js/src/builtin/Intl.cpp +++ b/js/src/builtin/Intl.cpp @@ -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(obj->as().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().getReservedSlot(UCOLLATOR_SLOT); + if (!slot.isUndefined()) { + if (UCollator *coll = static_cast(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(obj->as().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().getReservedSlot(UNUMBER_FORMAT_SLOT); + if (!slot.isUndefined()) { + if (UNumberFormat *nf = static_cast(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(obj->as().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().getReservedSlot(UDATE_FORMAT_SLOT); + if (!slot.isUndefined()) { + if (UDateFormat *df = static_cast(slot.toPrivate())) + udat_close(df); + } } static JSObject * From c93d203e5c999a771bda59a0cb7f5c772b9088d3 Mon Sep 17 00:00:00 2001 From: Nikhil Marathe Date: Fri, 19 Dec 2014 05:01:53 -0800 Subject: [PATCH 24/46] Bug 1113627 - Refactor lifecycle event dispatching and handling. r=baku,bz --HG-- extra : transplant_source : %E9%C4%13%80%CA%EEj%8D%17%A0LE%F3Tm%0F%EB%2B%3D3 extra : histedit_source : e16da08aa5dca392ad6270a3b03c05c74d1a5ad6 --- dom/events/Event.h | 18 ++ dom/webidl/InstallEvent.webidl | 2 +- dom/workers/ServiceWorkerEvents.h | 10 + dom/workers/ServiceWorkerManager.cpp | 337 +++++++++++---------------- dom/workers/ServiceWorkerManager.h | 7 + 5 files changed, 166 insertions(+), 208 deletions(-) diff --git a/dom/events/Event.h b/dom/events/Event.h index a1cb30bcf6c0..fbcbd5b249a3 100644 --- a/dom/events/Event.h +++ b/dom/events/Event.h @@ -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 diff --git a/dom/webidl/InstallEvent.webidl b/dom/webidl/InstallEvent.webidl index 7b770191bef4..aeb436077ebb 100644 --- a/dom/webidl/InstallEvent.webidl +++ b/dom/webidl/InstallEvent.webidl @@ -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; }; diff --git a/dom/workers/ServiceWorkerEvents.h b/dom/workers/ServiceWorkerEvents.h index ef52f8c692c0..9c267260d99d 100644 --- a/dom/workers/ServiceWorkerEvents.h +++ b/dom/workers/ServiceWorkerEvents.h @@ -69,6 +69,11 @@ public: nsRefPtr 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 diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index 55e8b1b258d5..4bb7e54717ef 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -106,26 +106,6 @@ ServiceWorkerRegistrationInfo::~ServiceWorkerRegistrationInfo() } } -class QueueFireUpdateFoundRunnable MOZ_FINAL : public nsRunnable -{ - nsRefPtr mRegistration; -public: - explicit QueueFireUpdateFoundRunnable(ServiceWorkerRegistrationInfo* aReg) - : mRegistration(aReg) - { - MOZ_ASSERT(aReg); - } - - NS_IMETHOD - Run() - { - nsRefPtr 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 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 mJob; + +public: + explicit ContinueInstallTask(ServiceWorkerRegisterJob* aJob) + : mJob(aJob) + { } + + void ContinueAfterWorkerEvent(bool aSuccess, bool aActivateImmediately) MOZ_OVERRIDE; +}; + +class ContinueActivateTask MOZ_FINAL : public ContinueLifecycleTask +{ + nsRefPtr 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 mTask; bool mSuccess; bool mActivateImmediately; public: - explicit FinishInstallRunnable(const nsMainThreadPtrHandle& aJob, - bool aSuccess, - bool aActivateImmediately) - : mJob(aJob) + ContinueLifecycleRunnable(const nsMainThreadPtrHandle& 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 mJob; - nsCString mScope; + nsString mEventName; + nsMainThreadPtrHandle mTask; public: - InstallEventRunnable(WorkerPrivate* aWorkerPrivate, - const nsMainThreadPtrHandle& aJob, - const nsCString& aScope) - : WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount), - mJob(aJob), - mScope(aScope) + LifecycleEventWorkerRunnable(WorkerPrivate* aWorkerPrivate, + const nsString& aEventName, + const nsMainThreadPtrHandle& 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; @@ -531,15 +559,14 @@ public: Succeed(); - nsRefPtr upr = - new QueueFireUpdateFoundRunnable(mRegistration); + nsCOMPtr upr = + NS_NewRunnableMethodWithArg(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 upcasted = this; - nsMainThreadPtrHandle handle( - new nsMainThreadPtrHolder(upcasted)); + nsMainThreadPtrHandle handle( + new nsMainThreadPtrHolder(new ContinueInstallTask(this))); nsRefPtr serviceWorker; nsresult rv = @@ -552,8 +579,8 @@ public: return; } - nsRefPtr r = - new InstallEventRunnable(serviceWorker->GetWorkerPrivate(), handle, mRegistration->mScope); + nsRefPtr r = + new LifecycleEventWorkerRunnable(serviceWorker->GetWorkerPrivate(), NS_LITERAL_STRING("install"), handle); AutoJSAPI jsapi; jsapi.Init(); @@ -705,6 +732,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 +886,23 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow, return NS_OK; } -NS_IMETHODIMP -FinishInstallRunnable::Run() -{ - AssertIsOnMainThread(); - nsRefPtr job = static_cast(mJob.get()); - nsRefPtr upjob = static_cast(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 mJob; + nsMainThreadPtrHandle mTask; bool mActivateImmediately; virtual - ~FinishInstallHandler() + ~LifecycleEventPromiseHandler() { } public: - FinishInstallHandler(const nsMainThreadPtrHandle& aJob, - bool aActivateImmediately) - : mJob(aJob) + LifecycleEventPromiseHandler(const nsMainThreadPtrHandle& aTask, + bool aActivateImmediately) + : mTask(aTask) , mActivateImmediately(aActivateImmediately) { MOZ_ASSERT(!NS_IsMainThread()); @@ -892,33 +915,47 @@ public: MOZ_ASSERT(workerPrivate); workerPrivate->AssertIsOnWorkerThread(); - nsRefPtr r = new FinishInstallRunnable(mJob, true, mActivateImmediately); + nsRefPtr r = + new ContinueLifecycleRunnable(mTask, true /* success */, mActivateImmediately); NS_DispatchToMainThread(r); } void RejectedCallback(JSContext* aCx, JS::Handle aValue) MOZ_OVERRIDE { - nsRefPtr r = new FinishInstallRunnable(mJob, false, mActivateImmediately); + WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(workerPrivate); + workerPrivate->AssertIsOnWorkerThread(); + + nsRefPtr 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 event; nsRefPtr target = aWorkerPrivate->GlobalScope(); - nsRefPtr 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 +989,21 @@ InstallEventRunnable::DispatchInstallEvent(JSContext* aCx, WorkerPrivate* aWorke return false; } - nsRefPtr 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 handler = + new LifecycleEventPromiseHandler(mTask, activateImmediately); waitUntilPromise->AppendNativeHandler(handler); return true; } -class FinishActivationRunnable MOZ_FINAL : public nsRunnable -{ - bool mSuccess; - nsMainThreadPtrHandle mRegistration; - -public: - FinishActivationRunnable(bool aSuccess, - const nsMainThreadPtrHandle& 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 mRegistration; - -public: - explicit FinishActivateHandler(const nsMainThreadPtrHandle& aRegistration) - : mRegistration(aRegistration) - { - MOZ_ASSERT(!NS_IsMainThread()); - } - - virtual - ~FinishActivateHandler() - { } - - void - ResolvedCallback(JSContext* aCx, JS::Handle aValue) MOZ_OVERRIDE - { - nsRefPtr r = new FinishActivationRunnable(true /* success */, mRegistration); - NS_DispatchToMainThread(r); - } - - void - RejectedCallback(JSContext* aCx, JS::Handle aValue) MOZ_OVERRIDE - { - nsRefPtr r = new FinishActivationRunnable(false /* success */, mRegistration); - NS_DispatchToMainThread(r); - } -}; - -class ActivateEventRunnable : public WorkerRunnable -{ - nsMainThreadPtrHandle mRegistration; - -public: - ActivateEventRunnable(WorkerPrivate* aWorkerPrivate, - const nsMainThreadPtrHandle& 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 target = do_QueryObject(aWorkerPrivate->GlobalScope()); - - // FIXME(nsm): Set activeWorker to the correct thing. - EventInit init; - init.mBubbles = false; - init.mCancelable = true; - nsRefPtr event = - ExtendableEvent::Constructor(target, NS_LITERAL_STRING("activate"), init); - - event->SetTrusted(true); - - nsRefPtr 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 global = - do_QueryObject(aWorkerPrivate->GlobalScope()); - waitUntilPromise = - Promise::Resolve(global, - aCx, JS::UndefinedHandleValue, result); - } - } else { - nsCOMPtr global = - do_QueryObject(aWorkerPrivate->GlobalScope()); - // Continue with a canceled install. - waitUntilPromise = Promise::Reject(global, aCx, - JS::UndefinedHandleValue, result); - } - - if (result.Failed()) { - return false; - } - - nsRefPtr handler = new FinishActivateHandler(mRegistration); - waitUntilPromise->AppendNativeHandler(handler); - return true; - } -}; - void ServiceWorkerRegistrationInfo::TryToActivate() { @@ -1138,11 +1061,11 @@ ServiceWorkerRegistrationInfo::Activate() return; } - nsMainThreadPtrHandle handle( - new nsMainThreadPtrHolder(this)); + nsMainThreadPtrHandle handle( + new nsMainThreadPtrHolder(new ContinueActivateTask(this))); - nsRefPtr r = - new ActivateEventRunnable(serviceWorker->GetWorkerPrivate(), handle); + nsRefPtr r = + new LifecycleEventWorkerRunnable(serviceWorker->GetWorkerPrivate(), NS_LITERAL_STRING("activate"), handle); AutoJSAPI jsapi; jsapi.Init(); diff --git a/dom/workers/ServiceWorkerManager.h b/dom/workers/ServiceWorkerManager.h index 4760edd39b1f..879919f4f70b 100644 --- a/dom/workers/ServiceWorkerManager.h +++ b/dom/workers/ServiceWorkerManager.h @@ -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); From bdbece8200a276ab6ef9d76a7d282cb75ebaed0b Mon Sep 17 00:00:00 2001 From: Nikhil Marathe Date: Wed, 5 Nov 2014 14:43:51 -0800 Subject: [PATCH 25/46] Bug 1113631 - Remove registration when installation failure occurs. Fixes spec issue #547. r=baku --HG-- extra : transplant_source : l%8C%98%C3%19%7C/%5C%076ZS%26%8DR%EDzM%CB%04 extra : histedit_source : 3acd229eebf3367ccf98faaf02d1330942c1cda0 --- dom/workers/ServiceWorkerManager.cpp | 35 +++++++++++++++---- .../test_installation_simple.html | 4 +++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index 4bb7e54717ef..51e56b2fa61e 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -532,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. @@ -661,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 newest = mRegistration->Newest(); + if (!newest) { + nsRefPtr swm = ServiceWorkerManager::GetInstance(); + nsRefPtr domainInfo = + swm->GetDomainInfo(mRegistration->mScope); + MOZ_ASSERT(domainInfo); + domainInfo->RemoveRegistration(mRegistration); + } } void @@ -693,6 +715,7 @@ private: mRegistration->mInstallingWorker = nullptr; swm->InvalidateServiceWorkerRegistrationWorker(mRegistration, WhichServiceWorker::INSTALLING_WORKER); + MaybeRemoveRegistration(); return Done(NS_ERROR_DOM_ABORT_ERR); } diff --git a/dom/workers/test/serviceworkers/test_installation_simple.html b/dom/workers/test/serviceworkers/test_installation_simple.html index 756a28bb263d..c0fc0ef3483b 100644 --- a/dom/workers/test/serviceworkers/test_installation_simple.html +++ b/dom/workers/test/serviceworkers/test_installation_simple.html @@ -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"); From 067250b41d4ae1f5d31aae91c6c1a4198f2d20f1 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Tue, 27 Jan 2015 09:36:09 -0800 Subject: [PATCH 26/46] Bug 1126088 - Fallibly allocate MP4Stream CacheBlocks. r=jya,r=njn --- dom/media/fmp4/MP4Stream.cpp | 7 +++++-- dom/media/fmp4/MP4Stream.h | 19 +++++++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/dom/media/fmp4/MP4Stream.cpp b/dom/media/fmp4/MP4Stream.cpp index 3b9679e82857..11d5654d4d4e 100644 --- a/dom/media/fmp4/MP4Stream.cpp +++ b/dom/media/fmp4/MP4Stream.cpp @@ -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(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; } diff --git a/dom/media/fmp4/MP4Stream.h b/dom/media/fmp4/MP4Stream.h index 96bee87590e8..912d4f00fe90 100644 --- a/dom/media/fmp4/MP4Stream.h +++ b/dom/media/fmp4/MP4Stream.h @@ -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 mBuffer; + + bool Init() + { + mBuffer = new ((fallible_t())) char[mCount]; + return !!mBuffer; + } + + char* Buffer() + { + MOZ_ASSERT(mBuffer.get()); + return mBuffer.get(); + } + + private: + nsAutoArrayPtr mBuffer; }; nsTArray mCache; }; From 3e3b6fb8c0da0fa1d706e14b06382f52eea054a6 Mon Sep 17 00:00:00 2001 From: Nikhil Marathe Date: Thu, 22 Jan 2015 14:10:38 -0800 Subject: [PATCH 27/46] Bug 1113957 - ServiceWorker unregistration uses job queue. r=baku --HG-- extra : transplant_source : %B3%AA%CF%C5%05%409%D9%15Ly%FA%FF%E3%FA%5E%9B%3F%9F. --- dom/workers/ServiceWorkerManager.cpp | 166 +++++++++++------- dom/workers/ServiceWorkerManager.h | 2 +- dom/workers/ServiceWorkerRegistration.cpp | 3 +- dom/workers/test/serviceworkers/mochitest.ini | 1 - .../test/serviceworkers/test_unregister.html | 16 -- 5 files changed, 102 insertions(+), 86 deletions(-) diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index 51e56b2fa61e..fbf8a47987c6 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -1421,6 +1421,90 @@ ServiceWorkerManager::CheckReadyPromise(nsPIDOMWindow* aWindow, return false; } +class ServiceWorkerUnregisterJob MOZ_FINAL : public ServiceWorkerJob +{ + nsRefPtr mRegistration; + const nsCString mScope; + nsCOMPtr mCallback; + + ~ServiceWorkerUnregisterJob() + { } + +public: + ServiceWorkerUnregisterJob(ServiceWorkerJobQueue* aQueue, + const nsACString& aScope, + nsIServiceWorkerUnregisterCallback* aCallback) + : ServiceWorkerJob(aQueue) + , mScope(aScope) + , mCallback(aCallback) + { + AssertIsOnMainThread(); + } + + void + Start() MOZ_OVERRIDE + { + AssertIsOnMainThread(); + nsCOMPtr r = + NS_NewRunnableMethod(this, &ServiceWorkerUnregisterJob::UnregisterAndDone); + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(r))); + } + +private: + // You probably want UnregisterAndDone(). + nsresult + Unregister() + { + AssertIsOnMainThread(); + + nsRefPtr swm = ServiceWorkerManager::GetInstance(); + + nsRefPtr domainInfo = + swm->GetDomainInfo(mScope); + MOZ_ASSERT(domainInfo); + + // "Let registration be the result of running [[Get Registration]] + // algorithm passing scope as the argument." + nsRefPtr 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) @@ -1428,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 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 mCallback; - nsCOMPtr mScopeURI; + NS_ConvertUTF16toUTF8 scope(aScope); + nsRefPtr 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 swm = ServiceWorkerManager::GetInstance(); - - nsRefPtr 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 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 unregisterRunnable = - new UnregisterRunnable(aCallback, scopeURI); - return NS_DispatchToCurrentThread(unregisterRunnable); + nsRefPtr job = + new ServiceWorkerUnregisterJob(queue, scope, aCallback); + queue->Append(job); + return NS_OK; } /* static */ @@ -2193,8 +2225,8 @@ ServiceWorkerManager::Update(const nsAString& aScope) nsRefPtr cb = new ServiceWorkerUpdateFinishCallback(); - nsRefPtr job - = new ServiceWorkerRegisterJob(queue, registration, cb); + nsRefPtr job = + new ServiceWorkerRegisterJob(queue, registration, cb); queue->Append(job); return NS_OK; } diff --git a/dom/workers/ServiceWorkerManager.h b/dom/workers/ServiceWorkerManager.h index 879919f4f70b..2e9f58bac332 100644 --- a/dom/workers/ServiceWorkerManager.h +++ b/dom/workers/ServiceWorkerManager.h @@ -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 diff --git a/dom/workers/ServiceWorkerRegistration.cpp b/dom/workers/ServiceWorkerRegistration.cpp index 2cc82b51f50e..c2d24d9e7151 100644 --- a/dom/workers/ServiceWorkerRegistration.cpp +++ b/dom/workers/ServiceWorkerRegistration.cpp @@ -164,6 +164,7 @@ ServiceWorkerRegistration::Unregister(ErrorResult& aRv) nsCOMPtr scopeURI; nsCOMPtr 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; } diff --git a/dom/workers/test/serviceworkers/mochitest.ini b/dom/workers/test/serviceworkers/mochitest.ini index ede96abbdcd5..5183aed44b96 100644 --- a/dom/workers/test/serviceworkers/mochitest.ini +++ b/dom/workers/test/serviceworkers/mochitest.ini @@ -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. diff --git a/dom/workers/test/serviceworkers/test_unregister.html b/dom/workers/test/serviceworkers/test_unregister.html index 88752d8eadcc..8cd48010841b 100644 --- a/dom/workers/test/serviceworkers/test_unregister.html +++ b/dom/workers/test/serviceworkers/test_unregister.html @@ -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) { From 6fd135f8aece668dd240b8c166fe86abea921536 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 27 Jan 2015 09:28:45 -0500 Subject: [PATCH 28/46] Bug 1126295 - Move TestAtoms.cpp to gtest and enable it; r=froydnj --HG-- rename : xpcom/tests/TestAtoms.cpp => xpcom/tests/gtest/TestAtoms.cpp rename : xpcom/tests/UTFStrings.h => xpcom/tests/gtest/UTFStrings.h extra : rebase_source : 16340d826f39339dd38e77810cd08e59b324c380 --- xpcom/tests/UTFStrings.h | 110 -------------- xpcom/tests/{ => gtest}/TestAtoms.cpp | 208 +++++++++----------------- xpcom/tests/gtest/UTFStrings.h | 110 ++++++++++++++ xpcom/tests/gtest/moz.build | 1 + xpcom/tests/moz.build | 1 - 5 files changed, 181 insertions(+), 249 deletions(-) delete mode 100644 xpcom/tests/UTFStrings.h rename xpcom/tests/{ => gtest}/TestAtoms.cpp (52%) create mode 100644 xpcom/tests/gtest/UTFStrings.h diff --git a/xpcom/tests/UTFStrings.h b/xpcom/tests/UTFStrings.h deleted file mode 100644 index 91468f1b033f..000000000000 --- a/xpcom/tests/UTFStrings.h +++ /dev/null @@ -1,110 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef utfstrings_h__ -#define utfstrings_h__ - -struct UTFStringsStringPair - { - char16_t m16[16]; - char m8[16]; - }; - -static const UTFStringsStringPair ValidStrings[] = - { - { { 'a', 'b', 'c', 'd' }, - { 'a', 'b', 'c', 'd' } }, - { { '1', '2', '3', '4' }, - { '1', '2', '3', '4' } }, - { { 0x7F, 'A', 0x80, 'B', 0x101, 0x200 }, - { 0x7F, 'A', 0xC2, 0x80, 'B', 0xC4, 0x81, 0xC8, 0x80 } }, - { { 0x7FF, 0x800, 0x1000 }, - { 0xDF, 0xBF, 0xE0, 0xA0, 0x80, 0xE1, 0x80, 0x80 } }, - { { 0xD7FF, 0xE000, 0xF00F, 'A', 0xFFF0 }, - { 0xED, 0x9F, 0xBF, 0xEE, 0x80, 0x80, 0xEF, 0x80, 0x8F, 'A', 0xEF, 0xBF, 0xB0 } }, - { { 0xFFF7, 0xFFFC, 0xFFFD, 0xFFFD }, - { 0xEF, 0xBF, 0xB7, 0xEF, 0xBF, 0xBC, 0xEF, 0xBF, 0xBD, 0xEF, 0xBF, 0xBD } }, - { { 0xD800, 0xDC00, 0xD800, 0xDCFF }, - { 0xF0, 0x90, 0x80, 0x80, 0xF0, 0x90, 0x83, 0xBF } }, - { { 0xDBFF, 0xDFFF, 0xDBB7, 0xDCBA }, - { 0xF4, 0x8F, 0xBF, 0xBF, 0xF3, 0xBD, 0xB2, 0xBA } }, - { { 0xFFFD, 0xFFFF }, - { 0xEF, 0xBF, 0xBD, 0xEF, 0xBF, 0xBF } }, - { { 0xFFFD, 0xFFFE, 0xFFFF }, - { 0xEF, 0xBF, 0xBD, 0xEF, 0xBF, 0xBE, 0xEF, 0xBF, 0xBF } }, - }; - -static const UTFStringsStringPair Invalid16Strings[] = - { - { { 'a', 'b', 0xD800 }, - { 'a', 'b', 0xEF, 0xBF, 0xBD } }, - { { 0xD8FF, 'b' }, - { 0xEF, 0xBF, 0xBD, 'b' } }, - { { 0xD821 }, - { 0xEF, 0xBF, 0xBD } }, - { { 0xDC21 }, - { 0xEF, 0xBF, 0xBD } }, - { { 0xDC00, 0xD800, 'b' }, - { 0xEF, 0xBF, 0xBD, 0xEF, 0xBF, 0xBD, 'b' } }, - { { 'b', 0xDC00, 0xD800 }, - { 'b', 0xEF, 0xBF, 0xBD, 0xEF, 0xBF, 0xBD } }, - { { 0xDC00, 0xD800 }, - { 0xEF, 0xBF, 0xBD, 0xEF, 0xBF, 0xBD } }, - { { 0xDC00, 0xD800, 0xDC00, 0xD800 }, - { 0xEF, 0xBF, 0xBD, 0xF0, 0x90, 0x80, 0x80, 0xEF, 0xBF, 0xBD } }, - { { 0xDC00, 0xD800, 0xD800, 0xDC00 }, - { 0xEF, 0xBF, 0xBD, 0xEF, 0xBF, 0xBD, 0xF0, 0x90, 0x80, 0x80 } }, - }; - -static const UTFStringsStringPair Invalid8Strings[] = - { - { { 'a', 0xFFFD, 'b' }, - { 'a', 0xC0, 0x80, 'b' } }, - { { 0xFFFD, 0x80 }, - { 0xC1, 0xBF, 0xC2, 0x80 } }, - { { 0xFFFD }, - { 0xC1, 0xBF } }, - { { 0xFFFD, 'x', 0x0800 }, - { 0xE0, 0x80, 0x80, 'x', 0xE0, 0xA0, 0x80 } }, - { { 0xFFFD, 'x', 0xFFFD }, - { 0xF0, 0x80, 0x80, 0x80, 'x', 0xF0, 0x80, 0x8F, 0x80 } }, - { { 0xFFFD, 0xFFFD }, - { 0xF4, 0x90, 0x80, 0x80, 0xF7, 0xBF, 0xBF, 0xBF } }, - { { 0xFFFD, 'x', 0xD800, 0xDC00, 0xFFFD }, - { 0xF0, 0x8F, 0xBF, 0xBF, 'x', 0xF0, 0x90, 0x80, 0x80, 0xF0, 0x8F, 0xBF, 0xBF } }, - { { 0xFFFD, 'x', 0xFFFD }, - { 0xF8, 0x80, 0x80, 0x80, 0x80, 'x', 0xF8, 0x88, 0x80, 0x80, 0x80 } }, - { { 0xFFFD, 0xFFFD }, - { 0xFB, 0xBF, 0xBF, 0xBF, 0xBF, 0xFC, 0xA0, 0x80, 0x80, 0x80, 0x80 } }, - { { 0xFFFD, 0xFFFD }, - { 0xFC, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFD, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF } }, - }; - -// Don't use this array in debug builds as that intentionally asserts. -#ifndef DEBUG -static const char Malformed8Strings[][16] = - { - { 0x80 }, - { 'a', 0xC8, 'c' }, - { 'a', 0xC0 }, - { 'a', 0xE8, 'c' }, - { 'a', 0xE8, 0x80, 'c' }, - { 'a', 0xE8, 0x80 }, - { 0xE8, 0x7F, 0x80 }, - { 'a', 0xE8, 0xE8, 0x80 }, - { 'a', 0xF4 }, - { 'a', 0xF4, 0x80, 0x80, 'c', 'c' }, - { 'a', 0xF4, 0x80, 'x', 0x80 }, - { 0xF4, 0x80, 0x80, 0x80, 0x80 }, - { 'a', 0xFA, 'c' }, - { 'a', 0xFA, 0x80, 0x80, 0x7F, 0x80, 'c' }, - { 'a', 0xFA, 0x80, 0x80, 0x80, 0x80, 0x80, 'c' }, - { 'a', 0xFD }, - { 'a', 0xFD, 0x80, 0x80, 0x80, 0x80, 'c' }, - { 'a', 0xFD, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, - { 'a', 0xFC, 0x80, 0x80, 0x40, 0x80, 0x80, 'c' }, - }; -#endif - -#endif diff --git a/xpcom/tests/TestAtoms.cpp b/xpcom/tests/gtest/TestAtoms.cpp similarity index 52% rename from xpcom/tests/TestAtoms.cpp rename to xpcom/tests/gtest/TestAtoms.cpp index 7da8f4c17212..54e896ee4039 100644 --- a/xpcom/tests/TestAtoms.cpp +++ b/xpcom/tests/gtest/TestAtoms.cpp @@ -11,98 +11,85 @@ #include "nsIServiceManager.h" #include "nsStaticAtom.h" +#include "gtest/gtest.h" + using namespace mozilla; namespace TestAtoms { -bool -test_basic() +TEST(Atoms, Basic) { for (unsigned int i = 0; i < ArrayLength(ValidStrings); ++i) { nsDependentString str16(ValidStrings[i].m16); nsDependentCString str8(ValidStrings[i].m8); nsCOMPtr atom = do_GetAtom(str16); - - if (!atom->Equals(str16) || !atom->EqualsUTF8(str8)) - return false; + + EXPECT_TRUE(atom->Equals(str16)); + EXPECT_TRUE(atom->EqualsUTF8(str8)); nsString tmp16; nsCString tmp8; atom->ToString(tmp16); atom->ToUTF8String(tmp8); - if (!str16.Equals(tmp16) || !str8.Equals(tmp8)) - return false; + EXPECT_TRUE(str16.Equals(tmp16)); + EXPECT_TRUE(str8.Equals(tmp8)); - if (!nsDependentString(atom->GetUTF16String()).Equals(str16)) - return false; + EXPECT_TRUE(nsDependentString(atom->GetUTF16String()).Equals(str16)); - if (!nsAtomString(atom).Equals(str16) || - !nsDependentAtomString(atom).Equals(str16) || - !nsAtomCString(atom).Equals(str8)) - return false; + EXPECT_TRUE(nsAtomString(atom).Equals(str16)); + EXPECT_TRUE(nsDependentAtomString(atom).Equals(str16)); + EXPECT_TRUE(nsAtomCString(atom).Equals(str8)); } - - return true; } -bool -test_16vs8() +TEST(Atoms, 16vs8) { for (unsigned int i = 0; i < ArrayLength(ValidStrings); ++i) { nsCOMPtr atom16 = do_GetAtom(ValidStrings[i].m16); nsCOMPtr atom8 = do_GetAtom(ValidStrings[i].m8); - if (atom16 != atom8) - return false; + EXPECT_EQ(atom16, atom8); } - - return true; } -bool -test_buffersharing() +TEST(Atoms, BufferSharing) { nsString unique; unique.AssignLiteral("this is a unique string !@#$"); - + nsCOMPtr atom = do_GetAtom(unique); - - return unique.get() == atom->GetUTF16String(); + + EXPECT_EQ(unique.get(), atom->GetUTF16String()); } -bool -test_null() +TEST(Atoms, NUll) { nsAutoString str(NS_LITERAL_STRING("string with a \0 char")); nsDependentString strCut(str.get()); - if (str.Equals(strCut)) - return false; - + EXPECT_FALSE(str.Equals(strCut)); + nsCOMPtr atomCut = do_GetAtom(strCut); nsCOMPtr atom = do_GetAtom(str); - - return atom->GetLength() == str.Length() && - atom->Equals(str) && - atom->EqualsUTF8(NS_ConvertUTF16toUTF8(str)) && - atom != atomCut && - atomCut->Equals(strCut); + + EXPECT_EQ(atom->GetLength(), str.Length()); + EXPECT_TRUE(atom->Equals(str)); + EXPECT_TRUE(atom->EqualsUTF8(NS_ConvertUTF16toUTF8(str))); + EXPECT_NE(atom, atomCut); + EXPECT_TRUE(atomCut->Equals(strCut)); } -bool -test_invalid() +TEST(Atoms, Invalid) { for (unsigned int i = 0; i < ArrayLength(Invalid16Strings); ++i) { nsrefcnt count = NS_GetNumberOfAtoms(); { nsCOMPtr atom16 = do_GetAtom(Invalid16Strings[i].m16); - if (!atom16->Equals(nsDependentString(Invalid16Strings[i].m16))) - return false; + EXPECT_TRUE(atom16->Equals(nsDependentString(Invalid16Strings[i].m16))); } - - if (count != NS_GetNumberOfAtoms()) - return false; + + EXPECT_EQ(count, NS_GetNumberOfAtoms()); } for (unsigned int i = 0; i < ArrayLength(Invalid8Strings); ++i) { @@ -111,13 +98,11 @@ test_invalid() { nsCOMPtr atom8 = do_GetAtom(Invalid8Strings[i].m8); nsCOMPtr atom16 = do_GetAtom(Invalid8Strings[i].m16); - if (atom16 != atom8 || - !atom16->Equals(nsDependentString(Invalid8Strings[i].m16))) - return false; + EXPECT_EQ(atom16, atom8); + EXPECT_TRUE(atom16->Equals(nsDependentString(Invalid8Strings[i].m16))); } - - if (count != NS_GetNumberOfAtoms()) - return false; + + EXPECT_EQ(count, NS_GetNumberOfAtoms()); } // Don't run this test in debug builds as that intentionally asserts. @@ -128,13 +113,10 @@ test_invalid() nsrefcnt count = NS_GetNumberOfAtoms(); nsCOMPtr atom8 = do_GetAtom(Malformed8Strings[i]); - if (atom8 != emptyAtom || - count != NS_GetNumberOfAtoms()) - return false; + EXPECT_EQ(atom8, emptyAtom); + EXPECT_EQ(count, NS_GetNumberOfAtoms()); } #endif - - return true; } #define FIRST_ATOM_STR "first static atom. Hello!" @@ -167,112 +149,62 @@ isStaticAtom(nsIAtom* atom) (atom->Release() == 1); } -bool -test_atomtable() +TEST(Atoms, Table) { nsrefcnt count = NS_GetNumberOfAtoms(); - - nsCOMPtr thirdNonPerm = do_GetAtom(THIRD_ATOM_STR); - - if (isStaticAtom(thirdNonPerm)) - return false; - if (!thirdNonPerm || NS_GetNumberOfAtoms() != count + 1) - return false; + nsCOMPtr thirdNonPerm = do_GetAtom(THIRD_ATOM_STR); + + EXPECT_FALSE(isStaticAtom(thirdNonPerm)); + + EXPECT_TRUE(thirdNonPerm); + EXPECT_EQ(NS_GetNumberOfAtoms(), count + 1); NS_RegisterStaticAtoms(sAtoms_info); - return sAtom1 && - sAtom1->Equals(NS_LITERAL_STRING(FIRST_ATOM_STR)) && - isStaticAtom(sAtom1) && - sAtom2 && - sAtom2->Equals(NS_LITERAL_STRING(SECOND_ATOM_STR)) && - isStaticAtom(sAtom2) && - sAtom3 && - sAtom3->Equals(NS_LITERAL_STRING(THIRD_ATOM_STR)) && - isStaticAtom(sAtom3) && - NS_GetNumberOfAtoms() == count + 3 && - thirdNonPerm == sAtom3; + EXPECT_TRUE(sAtom1); + EXPECT_TRUE(sAtom1->Equals(NS_LITERAL_STRING(FIRST_ATOM_STR))); + EXPECT_TRUE(isStaticAtom(sAtom1)); + EXPECT_TRUE(sAtom2); + EXPECT_TRUE(sAtom2->Equals(NS_LITERAL_STRING(SECOND_ATOM_STR))); + EXPECT_TRUE(isStaticAtom(sAtom2)); + EXPECT_TRUE(sAtom3); + EXPECT_TRUE(sAtom3->Equals(NS_LITERAL_STRING(THIRD_ATOM_STR))); + EXPECT_TRUE(isStaticAtom(sAtom3)); + EXPECT_EQ(NS_GetNumberOfAtoms(), count + 3); + EXPECT_EQ(thirdNonPerm, sAtom3); } #define FIRST_PERM_ATOM_STR "first permanent atom. Hello!" #define SECOND_PERM_ATOM_STR "second permanent atom. @World!" -bool -test_permanent() +TEST(Atoms, Permanent) { nsrefcnt count = NS_GetNumberOfAtoms(); { nsCOMPtr first = do_GetAtom(FIRST_PERM_ATOM_STR); - if (!first->Equals(NS_LITERAL_STRING(FIRST_PERM_ATOM_STR)) || - isStaticAtom(first)) - return false; - + EXPECT_TRUE(first->Equals(NS_LITERAL_STRING(FIRST_PERM_ATOM_STR))); + EXPECT_FALSE(isStaticAtom(first)); + nsCOMPtr first_p = NS_NewPermanentAtom(NS_LITERAL_STRING(FIRST_PERM_ATOM_STR)); - if (!first_p->Equals(NS_LITERAL_STRING(FIRST_PERM_ATOM_STR)) || - !isStaticAtom(first_p) || - first != first_p) - return false; - + EXPECT_TRUE(first_p->Equals(NS_LITERAL_STRING(FIRST_PERM_ATOM_STR))); + EXPECT_TRUE(isStaticAtom(first_p)); + EXPECT_EQ(first, first_p); + nsCOMPtr second_p = NS_NewPermanentAtom(NS_LITERAL_STRING(SECOND_PERM_ATOM_STR)); - if (!second_p->Equals(NS_LITERAL_STRING(SECOND_PERM_ATOM_STR)) || - !isStaticAtom(second_p)) - return false; - + EXPECT_TRUE(second_p->Equals(NS_LITERAL_STRING(SECOND_PERM_ATOM_STR))); + EXPECT_TRUE(isStaticAtom(second_p)); + nsCOMPtr second = do_GetAtom(SECOND_PERM_ATOM_STR); - if (!second->Equals(NS_LITERAL_STRING(SECOND_PERM_ATOM_STR)) || - !isStaticAtom(second) || - second != second_p) - return false; + EXPECT_TRUE(second->Equals(NS_LITERAL_STRING(SECOND_PERM_ATOM_STR))); + EXPECT_TRUE(isStaticAtom(second)); + EXPECT_EQ(second, second_p); } - return NS_GetNumberOfAtoms() == count + 2; + EXPECT_EQ(NS_GetNumberOfAtoms(), count + 2); } -typedef bool (*TestFunc)(); - -static const struct Test - { - const char* name; - TestFunc func; - } -tests[] = - { - { "test_basic", test_basic }, - { "test_16vs8", test_16vs8 }, - { "test_buffersharing", test_buffersharing }, - { "test_null", test_null }, - { "test_invalid", test_invalid }, -// FIXME: Bug 577500 TestAtoms fails when run in dist/bin due to -// static atom table already being closed. TestStaticAtoms has similar -// failure. -#if 0 - { "test_atomtable", test_atomtable }, - { "test_permanent", test_permanent }, -#endif - { nullptr, nullptr } - }; - } - -using namespace TestAtoms; - -int main() - { - { - nsCOMPtr servMan; - NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr); - - for (const Test* t = tests; t->name != nullptr; ++t) - { - printf("%25s : %s\n", t->name, t->func() ? "SUCCESS" : "FAILURE <--"); - } - } - - NS_ShutdownXPCOM(nullptr); - - return 0; - } diff --git a/xpcom/tests/gtest/UTFStrings.h b/xpcom/tests/gtest/UTFStrings.h new file mode 100644 index 000000000000..44f34ac8c7ae --- /dev/null +++ b/xpcom/tests/gtest/UTFStrings.h @@ -0,0 +1,110 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef utfstrings_h__ +#define utfstrings_h__ + +struct UTFStringsStringPair + { + char16_t m16[16]; + char m8[16]; + }; + +static const UTFStringsStringPair ValidStrings[] = + { + { { 'a', 'b', 'c', 'd' }, + { 'a', 'b', 'c', 'd' } }, + { { '1', '2', '3', '4' }, + { '1', '2', '3', '4' } }, + { { 0x7F, 'A', 0x80, 'B', 0x101, 0x200 }, + { 0x7F, 'A', char(0xC2), char(0x80), 'B', char(0xC4), char(0x81), char(0xC8), char(0x80) } }, + { { 0x7FF, 0x800, 0x1000 }, + { char(0xDF), char(0xBF), char(0xE0), char(0xA0), char(0x80), char(0xE1), char(0x80), char(0x80) } }, + { { 0xD7FF, 0xE000, 0xF00F, 'A', 0xFFF0 }, + { char(0xED), char(0x9F), char(0xBF), char(0xEE), char(0x80), char(0x80), char(0xEF), char(0x80), char(0x8F), 'A', char(0xEF), char(0xBF), char(0xB0) } }, + { { 0xFFF7, 0xFFFC, 0xFFFD, 0xFFFD }, + { char(0xEF), char(0xBF), char(0xB7), char(0xEF), char(0xBF), char(0xBC), char(0xEF), char(0xBF), char(0xBD), char(0xEF), char(0xBF), char(0xBD) } }, + { { 0xD800, 0xDC00, 0xD800, 0xDCFF }, + { char(0xF0), char(0x90), char(0x80), char(0x80), char(0xF0), char(0x90), char(0x83), char(0xBF) } }, + { { 0xDBFF, 0xDFFF, 0xDBB7, 0xDCBA }, + { char(0xF4), char(0x8F), char(0xBF), char(0xBF), char(0xF3), char(0xBD), char(0xB2), char(0xBA) } }, + { { 0xFFFD, 0xFFFF }, + { char(0xEF), char(0xBF), char(0xBD), char(0xEF), char(0xBF), char(0xBF) } }, + { { 0xFFFD, 0xFFFE, 0xFFFF }, + { char(0xEF), char(0xBF), char(0xBD), char(0xEF), char(0xBF), char(0xBE), char(0xEF), char(0xBF), char(0xBF) } }, + }; + +static const UTFStringsStringPair Invalid16Strings[] = + { + { { 'a', 'b', 0xD800 }, + { 'a', 'b', char(0xEF), char(0xBF), char(0xBD) } }, + { { 0xD8FF, 'b' }, + { char(0xEF), char(0xBF), char(0xBD), 'b' } }, + { { 0xD821 }, + { char(0xEF), char(0xBF), char(0xBD) } }, + { { 0xDC21 }, + { char(0xEF), char(0xBF), char(0xBD) } }, + { { 0xDC00, 0xD800, 'b' }, + { char(0xEF), char(0xBF), char(0xBD), char(0xEF), char(0xBF), char(0xBD), 'b' } }, + { { 'b', 0xDC00, 0xD800 }, + { 'b', char(0xEF), char(0xBF), char(0xBD), char(0xEF), char(0xBF), char(0xBD) } }, + { { 0xDC00, 0xD800 }, + { char(0xEF), char(0xBF), char(0xBD), char(0xEF), char(0xBF), char(0xBD) } }, + { { 0xDC00, 0xD800, 0xDC00, 0xD800 }, + { char(0xEF), char(0xBF), char(0xBD), char(0xF0), char(0x90), char(0x80), char(0x80), char(0xEF), char(0xBF), char(0xBD) } }, + { { 0xDC00, 0xD800, 0xD800, 0xDC00 }, + { char(0xEF), char(0xBF), char(0xBD), char(0xEF), char(0xBF), char(0xBD), char(0xF0), char(0x90), char(0x80), char(0x80) } }, + }; + +static const UTFStringsStringPair Invalid8Strings[] = + { + { { 'a', 0xFFFD, 'b' }, + { 'a', char(0xC0), char(0x80), 'b' } }, + { { 0xFFFD, 0x80 }, + { char(0xC1), char(0xBF), char(0xC2), char(0x80) } }, + { { 0xFFFD }, + { char(0xC1), char(0xBF) } }, + { { 0xFFFD, 'x', 0x0800 }, + { char(0xE0), char(0x80), char(0x80), 'x', char(0xE0), char(0xA0), char(0x80) } }, + { { 0xFFFD, 'x', 0xFFFD }, + { char(0xF0), char(0x80), char(0x80), char(0x80), 'x', char(0xF0), char(0x80), char(0x8F), char(0x80) } }, + { { 0xFFFD, 0xFFFD }, + { char(0xF4), char(0x90), char(0x80), char(0x80), char(0xF7), char(0xBF), char(0xBF), char(0xBF) } }, + { { 0xFFFD, 'x', 0xD800, 0xDC00, 0xFFFD }, + { char(0xF0), char(0x8F), char(0xBF), char(0xBF), 'x', char(0xF0), char(0x90), char(0x80), char(0x80), char(0xF0), char(0x8F), char(0xBF), char(0xBF) } }, + { { 0xFFFD, 'x', 0xFFFD }, + { char(0xF8), char(0x80), char(0x80), char(0x80), char(0x80), 'x', char(0xF8), char(0x88), char(0x80), char(0x80), char(0x80) } }, + { { 0xFFFD, 0xFFFD }, + { char(0xFB), char(0xBF), char(0xBF), char(0xBF), char(0xBF), char(0xFC), char(0xA0), char(0x80), char(0x80), char(0x80), char(0x80) } }, + { { 0xFFFD, 0xFFFD }, + { char(0xFC), char(0x80), char(0x80), char(0x80), char(0x80), char(0x80), char(0xFD), char(0xBF), char(0xBF), char(0xBF), char(0xBF), char(0xBF) } }, + }; + +// Don't use this array in debug builds as that intentionally asserts. +#ifndef DEBUG +static const char Malformed8Strings[][16] = + { + { char(0x80) }, + { 'a', char(0xC8), 'c' }, + { 'a', char(0xC0) }, + { 'a', char(0xE8), 'c' }, + { 'a', char(0xE8), char(0x80), 'c' }, + { 'a', char(0xE8), char(0x80) }, + { char(0xE8), 0x7F, char(0x80) }, + { 'a', char(0xE8), char(0xE8), char(0x80) }, + { 'a', char(0xF4) }, + { 'a', char(0xF4), char(0x80), char(0x80), 'c', 'c' }, + { 'a', char(0xF4), char(0x80), 'x', char(0x80) }, + { char(0xF4), char(0x80), char(0x80), char(0x80), char(0x80) }, + { 'a', char(0xFA), 'c' }, + { 'a', char(0xFA), char(0x80), char(0x80), 0x7F, char(0x80), 'c' }, + { 'a', char(0xFA), char(0x80), char(0x80), char(0x80), char(0x80), char(0x80), 'c' }, + { 'a', char(0xFD) }, + { 'a', char(0xFD), char(0x80), char(0x80), char(0x80), char(0x80), 'c' }, + { 'a', char(0xFD), char(0x80), char(0x80), char(0x80), char(0x80), char(0x80), char(0x80) }, + { 'a', char(0xFC), char(0x80), char(0x80), 0x40, char(0x80), char(0x80), 'c' }, + }; +#endif + +#endif diff --git a/xpcom/tests/gtest/moz.build b/xpcom/tests/gtest/moz.build index 2d9e273e564b..48762875c09a 100644 --- a/xpcom/tests/gtest/moz.build +++ b/xpcom/tests/gtest/moz.build @@ -5,6 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. UNIFIED_SOURCES += [ + 'TestAtoms.cpp', 'TestCRT.cpp', 'TestEncoding.cpp', 'TestExpirationTracker.cpp', diff --git a/xpcom/tests/moz.build b/xpcom/tests/moz.build index 33642af31468..0e81ba8bd9d8 100644 --- a/xpcom/tests/moz.build +++ b/xpcom/tests/moz.build @@ -83,7 +83,6 @@ if CONFIG['MOZ_MEMORY']: # 'TestThreads', # 'TestXPIDLString', # 'TestUTF', -# 'TestAtoms', #] # FIXME: bug 577500 TestStaticAtoms fails when run in dist/bin From 313bd50abd9e50114ca1e3765ac35a18def3d144 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 27 Jan 2015 12:38:44 -0500 Subject: [PATCH 29/46] Bug 1126301 - Move TestUTF.cpp to gtest and enable it; r=froydnj --HG-- rename : xpcom/tests/TestUTF.cpp => xpcom/tests/gtest/TestUTF.cpp extra : rebase_source : db5e0418f89bb1cf71a0543a48a6a063f61e4033 --- xpcom/tests/TestUTF.cpp | 189 ---------------------------------- xpcom/tests/gtest/TestUTF.cpp | 123 ++++++++++++++++++++++ xpcom/tests/gtest/moz.build | 1 + xpcom/tests/moz.build | 1 - 4 files changed, 124 insertions(+), 190 deletions(-) delete mode 100644 xpcom/tests/TestUTF.cpp create mode 100644 xpcom/tests/gtest/TestUTF.cpp diff --git a/xpcom/tests/TestUTF.cpp b/xpcom/tests/TestUTF.cpp deleted file mode 100644 index a4f068721170..000000000000 --- a/xpcom/tests/TestUTF.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/ArrayUtils.h" - -#include -#include -#include "nsString.h" -#include "nsStringBuffer.h" -#include "nsReadableUtils.h" -#include "UTFStrings.h" -#include "nsUnicharUtils.h" -#include "mozilla/HashFunctions.h" - -using namespace mozilla; - -namespace TestUTF { - -bool -test_valid() -{ - for (unsigned int i = 0; i < ArrayLength(ValidStrings); ++i) { - nsDependentCString str8(ValidStrings[i].m8); - nsDependentString str16(ValidStrings[i].m16); - - if (!NS_ConvertUTF16toUTF8(str16).Equals(str8)) - return false; - - if (!NS_ConvertUTF8toUTF16(str8).Equals(str16)) - return false; - - nsCString tmp8("string "); - AppendUTF16toUTF8(str16, tmp8); - if (!tmp8.Equals(NS_LITERAL_CSTRING("string ") + str8)) - return false; - - nsString tmp16(NS_LITERAL_STRING("string ")); - AppendUTF8toUTF16(str8, tmp16); - if (!tmp16.Equals(NS_LITERAL_STRING("string ") + str16)) - return false; - - if (CompareUTF8toUTF16(str8, str16) != 0) - return false; - } - - return true; -} - -bool -test_invalid16() -{ - for (unsigned int i = 0; i < ArrayLength(Invalid16Strings); ++i) { - nsDependentString str16(Invalid16Strings[i].m16); - nsDependentCString str8(Invalid16Strings[i].m8); - - if (!NS_ConvertUTF16toUTF8(str16).Equals(str8)) - return false; - - nsCString tmp8("string "); - AppendUTF16toUTF8(str16, tmp8); - if (!tmp8.Equals(NS_LITERAL_CSTRING("string ") + str8)) - return false; - - if (CompareUTF8toUTF16(str8, str16) != 0) - return false; - } - - return true; -} - -bool -test_invalid8() -{ - for (unsigned int i = 0; i < ArrayLength(Invalid8Strings); ++i) { - nsDependentString str16(Invalid8Strings[i].m16); - nsDependentCString str8(Invalid8Strings[i].m8); - - if (!NS_ConvertUTF8toUTF16(str8).Equals(str16)) - return false; - - nsString tmp16(NS_LITERAL_STRING("string ")); - AppendUTF8toUTF16(str8, tmp16); - if (!tmp16.Equals(NS_LITERAL_STRING("string ") + str16)) - return false; - - if (CompareUTF8toUTF16(str8, str16) != 0) - return false; - } - - return true; -} - -bool -test_malformed8() -{ -// Don't run this test in debug builds as that intentionally asserts. -#ifndef DEBUG - for (unsigned int i = 0; i < ArrayLength(Malformed8Strings); ++i) { - nsDependentCString str8(Malformed8Strings[i]); - - if (!NS_ConvertUTF8toUTF16(str8).IsEmpty()) - return false; - - nsString tmp16(NS_LITERAL_STRING("string")); - AppendUTF8toUTF16(str8, tmp16); - if (!tmp16.EqualsLiteral("string")) - return false; - - if (CompareUTF8toUTF16(str8, EmptyString()) == 0) - return false; - } -#endif - - return true; -} - -bool -test_hashas16() -{ - for (unsigned int i = 0; i < ArrayLength(ValidStrings); ++i) { - nsDependentCString str8(ValidStrings[i].m8); - bool err; - if (HashString(ValidStrings[i].m16) != - HashUTF8AsUTF16(str8.get(), str8.Length(), &err) || - err) - return false; - } - - for (unsigned int i = 0; i < ArrayLength(Invalid8Strings); ++i) { - nsDependentCString str8(Invalid8Strings[i].m8); - bool err; - if (HashString(Invalid8Strings[i].m16) != - HashUTF8AsUTF16(str8.get(), str8.Length(), &err) || - err) - return false; - } - -// Don't run this test in debug builds as that intentionally asserts. -#ifndef DEBUG - for (unsigned int i = 0; i < ArrayLength(Malformed8Strings); ++i) { - nsDependentCString str8(Malformed8Strings[i]); - bool err; - if (HashUTF8AsUTF16(str8.get(), str8.Length(), &err) != 0 || - !err) - return false; - } -#endif - - return true; -} - -typedef bool (*TestFunc)(); - -static const struct Test - { - const char* name; - TestFunc func; - } -tests[] = - { - { "test_valid", test_valid }, - { "test_invalid16", test_invalid16 }, - { "test_invalid8", test_invalid8 }, - { "test_malformed8", test_malformed8 }, - { "test_hashas16", test_hashas16 }, - { nullptr, nullptr } - }; - -} - -using namespace TestUTF; - -int main(int argc, char **argv) - { - int count = 1; - if (argc > 1) - count = atoi(argv[1]); - - while (count--) - { - for (const Test* t = tests; t->name != nullptr; ++t) - { - printf("%25s : %s\n", t->name, t->func() ? "SUCCESS" : "FAILURE <--"); - } - } - - return 0; - } diff --git a/xpcom/tests/gtest/TestUTF.cpp b/xpcom/tests/gtest/TestUTF.cpp new file mode 100644 index 000000000000..621c1d27b8a8 --- /dev/null +++ b/xpcom/tests/gtest/TestUTF.cpp @@ -0,0 +1,123 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/ArrayUtils.h" + +#include +#include +#include "nsString.h" +#include "nsStringBuffer.h" +#include "nsReadableUtils.h" +#include "UTFStrings.h" +#include "nsUnicharUtils.h" +#include "mozilla/HashFunctions.h" + +#include "gtest/gtest.h" + +using namespace mozilla; + +namespace TestUTF { + +TEST(UTF, Valid) +{ + for (unsigned int i = 0; i < ArrayLength(ValidStrings); ++i) { + nsDependentCString str8(ValidStrings[i].m8); + nsDependentString str16(ValidStrings[i].m16); + + EXPECT_TRUE(NS_ConvertUTF16toUTF8(str16).Equals(str8)); + + EXPECT_TRUE(NS_ConvertUTF8toUTF16(str8).Equals(str16)); + + nsCString tmp8("string "); + AppendUTF16toUTF8(str16, tmp8); + EXPECT_TRUE(tmp8.Equals(NS_LITERAL_CSTRING("string ") + str8)); + + nsString tmp16(NS_LITERAL_STRING("string ")); + AppendUTF8toUTF16(str8, tmp16); + EXPECT_TRUE(tmp16.Equals(NS_LITERAL_STRING("string ") + str16)); + + EXPECT_EQ(CompareUTF8toUTF16(str8, str16), 0); + } +} + +TEST(UTF, Invalid16) +{ + for (unsigned int i = 0; i < ArrayLength(Invalid16Strings); ++i) { + nsDependentString str16(Invalid16Strings[i].m16); + nsDependentCString str8(Invalid16Strings[i].m8); + + EXPECT_TRUE(NS_ConvertUTF16toUTF8(str16).Equals(str8)); + + nsCString tmp8("string "); + AppendUTF16toUTF8(str16, tmp8); + EXPECT_TRUE(tmp8.Equals(NS_LITERAL_CSTRING("string ") + str8)); + + EXPECT_EQ(CompareUTF8toUTF16(str8, str16), 0); + } +} + +TEST(UTF, Invalid8) +{ + for (unsigned int i = 0; i < ArrayLength(Invalid8Strings); ++i) { + nsDependentString str16(Invalid8Strings[i].m16); + nsDependentCString str8(Invalid8Strings[i].m8); + + EXPECT_TRUE(NS_ConvertUTF8toUTF16(str8).Equals(str16)); + + nsString tmp16(NS_LITERAL_STRING("string ")); + AppendUTF8toUTF16(str8, tmp16); + EXPECT_TRUE(tmp16.Equals(NS_LITERAL_STRING("string ") + str16)); + + EXPECT_EQ(CompareUTF8toUTF16(str8, str16), 0); + } +} + +TEST(UTF, Malformed8) +{ +// Don't run this test in debug builds as that intentionally asserts. +#ifndef DEBUG + for (unsigned int i = 0; i < ArrayLength(Malformed8Strings); ++i) { + nsDependentCString str8(Malformed8Strings[i]); + + EXPECT_TRUE(NS_ConvertUTF8toUTF16(str8).IsEmpty()); + + nsString tmp16(NS_LITERAL_STRING("string")); + AppendUTF8toUTF16(str8, tmp16); + EXPECT_TRUE(tmp16.EqualsLiteral("string")); + + EXPECT_NE(CompareUTF8toUTF16(str8, EmptyString()), 0); + } +#endif +} + +TEST(UTF, Hash16) +{ + for (unsigned int i = 0; i < ArrayLength(ValidStrings); ++i) { + nsDependentCString str8(ValidStrings[i].m8); + bool err; + EXPECT_EQ(HashString(ValidStrings[i].m16), + HashUTF8AsUTF16(str8.get(), str8.Length(), &err)); + EXPECT_FALSE(err); + } + + for (unsigned int i = 0; i < ArrayLength(Invalid8Strings); ++i) { + nsDependentCString str8(Invalid8Strings[i].m8); + bool err; + EXPECT_EQ(HashString(Invalid8Strings[i].m16), + HashUTF8AsUTF16(str8.get(), str8.Length(), &err)); + EXPECT_FALSE(err); + } + +// Don't run this test in debug builds as that intentionally asserts. +#ifndef DEBUG + for (unsigned int i = 0; i < ArrayLength(Malformed8Strings); ++i) { + nsDependentCString str8(Malformed8Strings[i]); + bool err; + EXPECT_EQ(HashUTF8AsUTF16(str8.get(), str8.Length(), &err), 0); + EXPECT_FALSE(err); + } +#endif +} + +} diff --git a/xpcom/tests/gtest/moz.build b/xpcom/tests/gtest/moz.build index 48762875c09a..2431cd38b65d 100644 --- a/xpcom/tests/gtest/moz.build +++ b/xpcom/tests/gtest/moz.build @@ -17,6 +17,7 @@ UNIFIED_SOURCES += [ 'TestSynchronization.cpp', 'TestThreadPool.cpp', 'TestTimeStamp.cpp', + 'TestUTF.cpp', ] FINAL_LIBRARY = 'xul-gtest' diff --git a/xpcom/tests/moz.build b/xpcom/tests/moz.build index 0e81ba8bd9d8..00f79480ca08 100644 --- a/xpcom/tests/moz.build +++ b/xpcom/tests/moz.build @@ -82,7 +82,6 @@ if CONFIG['MOZ_MEMORY']: #CPP_UNIT_TESTS += [ # 'TestThreads', # 'TestXPIDLString', -# 'TestUTF', #] # FIXME: bug 577500 TestStaticAtoms fails when run in dist/bin From ab3efc22ff1ab43fd943568866728f059f040112 Mon Sep 17 00:00:00 2001 From: Nikhil Marathe Date: Fri, 23 Jan 2015 11:23:55 -0800 Subject: [PATCH 30/46] Bug 1081293 - Silently ignore lack of ServiceWorkerManager when shutting down ServiceWorkerContainer. r=baku --HG-- extra : rebase_source : 65066288a5cec4bb9e97adbaf6bbe9cd32835394 extra : amend_source : b3e2cd0f05150d290050d99926fb0d48659929d4 --- dom/workers/ServiceWorkerContainer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dom/workers/ServiceWorkerContainer.cpp b/dom/workers/ServiceWorkerContainer.cpp index cc2f45068290..9d37400ef169 100644 --- a/dom/workers/ServiceWorkerContainer.cpp +++ b/dom/workers/ServiceWorkerContainer.cpp @@ -56,7 +56,10 @@ ServiceWorkerContainer::RemoveReadyPromise() if (window) { nsCOMPtr 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); } From 98fd7110d56e5939f7abb53cb949c1219f9ff9cb Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 27 Jan 2015 09:48:54 -0800 Subject: [PATCH 31/46] Bug 1125632 followup: Mark remaining CollectReports impls in nsMemoryReporterManager.cpp and SystemMemoryReporter.cpp as MOZ_OVERRIDE. --- xpcom/base/SystemMemoryReporter.cpp | 2 +- xpcom/base/nsMemoryReporterManager.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/xpcom/base/SystemMemoryReporter.cpp b/xpcom/base/SystemMemoryReporter.cpp index c4ff85d052c6..166e3e3bfc2a 100644 --- a/xpcom/base/SystemMemoryReporter.cpp +++ b/xpcom/base/SystemMemoryReporter.cpp @@ -159,7 +159,7 @@ public: REPORT_WITH_CLEANUP(_path, UNITS_BYTES, _amount, _desc, (void)0) NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, - nsISupports* aData, bool aAnonymize) + nsISupports* aData, bool aAnonymize) MOZ_OVERRIDE { // There is lots of privacy-sensitive data in /proc. Just skip this // reporter entirely when anonymization is required. diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index f375b4232960..22b558755c28 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -555,7 +555,7 @@ public: NS_DECL_ISUPPORTS NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport, - nsISupports* aData, bool aAnonymize) + nsISupports* aData, bool aAnonymize) MOZ_OVERRIDE { int64_t amount; nsresult rv = VsizeMaxContiguousDistinguishedAmount(&amount); @@ -578,7 +578,7 @@ public: NS_DECL_ISUPPORTS NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport, - nsISupports* aData, bool aAnonymize) + nsISupports* aData, bool aAnonymize) MOZ_OVERRIDE { int64_t amount; nsresult rv = PrivateDistinguishedAmount(&amount); @@ -922,7 +922,7 @@ public: NS_DECL_ISUPPORTS NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, - nsISupports* aData, bool aAnonymize) + nsISupports* aData, bool aAnonymize) MOZ_OVERRIDE { dmd::Sizes sizes; dmd::SizeOf(&sizes); From 18a949c8943adec2310f3207e9b3227f97e095e9 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 27 Jan 2015 12:56:15 -0500 Subject: [PATCH 32/46] Bug 1126301 follow-up: Fix a signed/unsigned comparison fatal warning, landed on a CLOSED TREE --- xpcom/tests/gtest/TestUTF.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xpcom/tests/gtest/TestUTF.cpp b/xpcom/tests/gtest/TestUTF.cpp index 621c1d27b8a8..99a44885780f 100644 --- a/xpcom/tests/gtest/TestUTF.cpp +++ b/xpcom/tests/gtest/TestUTF.cpp @@ -114,7 +114,7 @@ TEST(UTF, Hash16) for (unsigned int i = 0; i < ArrayLength(Malformed8Strings); ++i) { nsDependentCString str8(Malformed8Strings[i]); bool err; - EXPECT_EQ(HashUTF8AsUTF16(str8.get(), str8.Length(), &err), 0); + EXPECT_EQ(HashUTF8AsUTF16(str8.get(), str8.Length(), &err), 0u); EXPECT_FALSE(err); } #endif From 1c83e49c5e74423bc413a175d3a20ef842a22557 Mon Sep 17 00:00:00 2001 From: Jarda Date: Tue, 27 Jan 2015 18:58:17 +0100 Subject: [PATCH 33/46] Bug 1101356 arm part - Arm Simulator: Support for calling functions that have three and four double parameters. r=mjrosenb --- js/src/jit/arm/MacroAssembler-arm.cpp | 2 ++ js/src/jit/arm/Simulator-arm.cpp | 37 +++++++++++++++++++++++++++ js/src/jit/arm/Simulator-arm.h | 1 + 3 files changed, 40 insertions(+) diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp index 0a6c42ad5682..e1cc282edeb2 100644 --- a/js/src/jit/arm/MacroAssembler-arm.cpp +++ b/js/src/jit/arm/MacroAssembler-arm.cpp @@ -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"); diff --git a/js/src/jit/arm/Simulator-arm.cpp b/js/src/jit/arm/Simulator-arm.cpp index c68cc10700b6..ba1280f056df 100644 --- a/js/src/jit/arm/Simulator-arm.cpp +++ b/js/src/jit/arm/Simulator-arm.cpp @@ -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(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(external); + double dresult = target(dval0, dval1, dval2, dval3); + scratchVolatileRegisters(/* scratchFloat = true */); + setCallResultDouble(dresult); + break; + } default: MOZ_CRASH("call"); } diff --git a/js/src/jit/arm/Simulator-arm.h b/js/src/jit/arm/Simulator-arm.h index a44960fa0a4e..6125a5ea4b61 100644 --- a/js/src/jit/arm/Simulator-arm.h +++ b/js/src/jit/arm/Simulator-arm.h @@ -289,6 +289,7 @@ class Simulator private: // Handle arguments and return value for runtime FP functions. void getFpArgs(double *x, double *y, int32_t *z); + void getFpFromStack(int32_t *stack, double *x1); void setCallResultDouble(double result); void setCallResultFloat(float result); void setCallResult(int64_t res); From 659f621d171951df5eda32778475467b5aea4f8f Mon Sep 17 00:00:00 2001 From: Jarda Date: Tue, 27 Jan 2015 18:58:17 +0100 Subject: [PATCH 34/46] Bug 1101356 mips part - MIPS Simulator: Support for calling functions that have three and four double parameters. r=rankov --- js/src/jit/mips/MacroAssembler-mips.cpp | 2 ++ js/src/jit/mips/Simulator-mips.cpp | 35 +++++++++++++++++++++++++ js/src/jit/mips/Simulator-mips.h | 1 + 3 files changed, 38 insertions(+) diff --git a/js/src/jit/mips/MacroAssembler-mips.cpp b/js/src/jit/mips/MacroAssembler-mips.cpp index 8b4aea05ccb5..c37ef9eaa4b5 100644 --- a/js/src/jit/mips/MacroAssembler-mips.cpp +++ b/js/src/jit/mips/MacroAssembler-mips.cpp @@ -3472,6 +3472,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"); diff --git a/js/src/jit/mips/Simulator-mips.cpp b/js/src/jit/mips/Simulator-mips.cpp index b8ebac703cbb..6f942293cde3 100644 --- a/js/src/jit/mips/Simulator-mips.cpp +++ b/js/src/jit/mips/Simulator-mips.cpp @@ -1550,6 +1550,14 @@ Simulator::getFpArgs(double *x, double *y, int32_t *z) *z = getRegister(a2); } +void +Simulator::getFpFromStack(int32_t *stack, double *x) +{ + MOZ_ASSERT(stack); + MOZ_ASSERT(x); + memcpy(x, stack, sizeof(double)); +} + void Simulator::setCallResultDouble(double result) { @@ -1857,6 +1865,10 @@ 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); + // Software interrupt instructions are used by the simulator to call into C++. void Simulator::softwareInterrupt(SimInstruction *instr) @@ -2022,6 +2034,29 @@ Simulator::softwareInterrupt(SimInstruction *instr) setRegister(v0, 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 + 4, &dval2); + Prototype_Double_DoubleDoubleDouble target = reinterpret_cast(external); + double dresult = target(dval0, dval1, dval2); + 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 + 4, &dval2); + getFpFromStack(stack_pointer + 6, &dval3); + Prototype_Double_DoubleDoubleDoubleDouble target = reinterpret_cast(external); + double dresult = target(dval0, dval1, dval2, dval3); + setCallResultDouble(dresult); + break; + } default: MOZ_CRASH("call"); } diff --git a/js/src/jit/mips/Simulator-mips.h b/js/src/jit/mips/Simulator-mips.h index f27dc6e5a508..4f08de306e56 100644 --- a/js/src/jit/mips/Simulator-mips.h +++ b/js/src/jit/mips/Simulator-mips.h @@ -297,6 +297,7 @@ class Simulator { // Handle arguments and return value for runtime FP functions. void getFpArgs(double *x, double *y, int32_t *z); + void getFpFromStack(int32_t *stack, double *x); void setCallResultDouble(double result); void setCallResultFloat(float result); From cc6c44b80ffec630591cb5d1a2b725987fc7a37b Mon Sep 17 00:00:00 2001 From: Jarda Date: Tue, 27 Jan 2015 18:58:17 +0100 Subject: [PATCH 35/46] Bug 1101356 - MHypot Instruction supports up to four arguments. r=nbp --- js/src/jit-test/tests/basic/hypot-approx.js | 11 ++- js/src/jit-test/tests/basic/hypot-exact.js | 17 +++++ .../tests/ion/dce-with-rinstructions.js | 73 +++++++++++++++++-- js/src/jit/CodeGenerator.cpp | 23 ++++-- js/src/jit/IonTypes.h | 9 ++- js/src/jit/LIR-Common.h | 28 ++++++- js/src/jit/Lowering.cpp | 31 ++++++-- js/src/jit/MCallOptimize.cpp | 23 ++++-- js/src/jit/MIR.cpp | 12 +++ js/src/jit/MIR.h | 27 +++---- js/src/jit/Recover.cpp | 9 ++- js/src/jit/Recover.h | 5 +- js/src/jit/TypePolicy.cpp | 21 ++++++ js/src/jit/TypePolicy.h | 7 ++ js/src/jsmath.cpp | 53 ++++++++++++-- js/src/jsmath.h | 6 ++ 16 files changed, 296 insertions(+), 59 deletions(-) diff --git a/js/src/jit-test/tests/basic/hypot-approx.js b/js/src/jit-test/tests/basic/hypot-approx.js index ce6b05fc73d0..452e6c633e3c 100644 --- a/js/src/jit-test/tests/basic/hypot-approx.js +++ b/js/src/jit-test/tests/basic/hypot-approx.js @@ -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)); diff --git a/js/src/jit-test/tests/basic/hypot-exact.js b/js/src/jit-test/tests/basic/hypot-exact.js index a47b40a5d2bd..7c208d5143b9 100644 --- a/js/src/jit-test/tests/basic/hypot-exact.js +++ b/js/src/jit-test/tests/basic/hypot-exact.js @@ -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); diff --git a/js/src/jit-test/tests/ion/dce-with-rinstructions.js b/js/src/jit-test/tests/ion/dce-with-rinstructions.js index 6761020fe1e9..82295b32ca3a 100644 --- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js +++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js @@ -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); diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 3620cf488440..497280cde000 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -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); } diff --git a/js/src/jit/IonTypes.h b/js/src/jit/IonTypes.h index 74c62749bc16..b277859c89f4 100644 --- a/js/src/jit/IonTypes.h +++ b/js/src/jit/IonTypes.h @@ -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 { diff --git a/js/src/jit/LIR-Common.h b/js/src/jit/LIR-Common.h index a0eae739cd05..dd4f402bd257 100644 --- a/js/src/jit/LIR-Common.h +++ b/js/src/jit/LIR-Common.h @@ -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); } diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index 5f276c119699..94c6e96931e2 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -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); } diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index 6cb83a763692..97f7116e1e2a 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -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; diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index a431ef2c1c6e..e83653bcd0af 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -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 { diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index ea98d9d77912..9f89f9512fb9 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -5507,11 +5507,10 @@ class MAtan2 // Inline implementation of Math.hypot(). class MHypot - : public MBinaryInstruction, - public MixPolicy, 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(). diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp index 88ab1c9914cd..b0bfada9ecf6 100644 --- a/js/src/jit/Recover.cpp +++ b/js/src/jit/Recover.cpp @@ -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); diff --git a/js/src/jit/Recover.h b/js/src/jit/Recover.h index aac42bea0bfc..dd94f9701951 100644 --- a/js/src/jit/Recover.h +++ b/js/src/jit/Recover.h @@ -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; diff --git a/js/src/jit/TypePolicy.cpp b/js/src/jit/TypePolicy.cpp index 335dc62eff83..31ae3666e6a4 100644 --- a/js/src/jit/TypePolicy.cpp +++ b/js/src/jit/TypePolicy.cpp @@ -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) \ diff --git a/js/src/jit/TypePolicy.h b/js/src/jit/TypePolicy.h index 64a02a26f3c2..54153a683042 100644 --- a/js/src/jit/TypePolicy.h +++ b/js/src/jit/TypePolicy.h @@ -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: diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index ac257df8835c..f92458b3ce26 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -1378,6 +1378,50 @@ js::ecmaHypot(double x, double y) return hypot(x, y); } +static inline +void +hypot_step(double &scale, double &sumsq, double x) +{ + double xabs = mozilla::Abs(x); + if (scale < xabs) { + sumsq = 1 + sumsq * (scale / xabs) * (scale / xabs); + scale = xabs; + } else if (scale != 0) { + sumsq += (xabs / scale) * (xabs / scale); + } +} + +double +js::hypot4(double x, double y, double z, double w) +{ + /* Check for infinity or NaNs so that we can return immediatelly. + * Does not need to be WIN_XP specific as ecmaHypot + */ + if (mozilla::IsInfinite(x) || mozilla::IsInfinite(y) || + mozilla::IsInfinite(z) || mozilla::IsInfinite(w)) + return mozilla::PositiveInfinity(); + + if (mozilla::IsNaN(x) || mozilla::IsNaN(y) || mozilla::IsNaN(z) || + mozilla::IsNaN(w)) + return GenericNaN(); + + double scale = 0; + double sumsq = 1; + + hypot_step(scale, sumsq, x); + hypot_step(scale, sumsq, y); + hypot_step(scale, sumsq, z); + hypot_step(scale, sumsq, w); + + return scale * sqrt(sumsq); +} + +double +js::hypot3(double x, double y, double z) +{ + return hypot4(x, y, z, 0.0); +} + bool js::math_hypot(JSContext *cx, unsigned argc, Value *vp) { @@ -1418,14 +1462,7 @@ js::math_hypot_handle(JSContext *cx, HandleValueArray args, MutableHandleValue r if (isInfinite || isNaN) continue; - double xabs = mozilla::Abs(x); - - if (scale < xabs) { - sumsq = 1 + sumsq * (scale / xabs) * (scale / xabs); - scale = xabs; - } else if (scale != 0) { - sumsq += (xabs / scale) * (xabs / scale); - } + hypot_step(scale, sumsq, x); } double result = isInfinite ? PositiveInfinity() : diff --git a/js/src/jsmath.h b/js/src/jsmath.h index 2c0da2877526..0f0ee6bd6a16 100644 --- a/js/src/jsmath.h +++ b/js/src/jsmath.h @@ -245,6 +245,12 @@ math_atanh(JSContext *cx, unsigned argc, js::Value *vp); extern double ecmaHypot(double x, double y); +extern double +hypot3(double x, double y, double z); + +extern double +hypot4(double x, double y, double z, double w); + extern bool math_hypot(JSContext *cx, unsigned argc, Value *vp); From 737d6f9309d36c2d9862ff043ff1dd8ac9625ba6 Mon Sep 17 00:00:00 2001 From: Sotaro Ikeda Date: Tue, 27 Jan 2015 10:05:35 -0800 Subject: [PATCH 36/46] Bug 1125913 - Use GraphicBuffer::lockAsync() on gonk LL r=nical --- gfx/layers/client/TextureClient.h | 2 +- gfx/layers/opengl/GrallocTextureClient.cpp | 24 ++++++++++++++++++++-- gfx/layers/opengl/GrallocTextureClient.h | 2 +- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h index c50971862664..9ebd3c351ce3 100644 --- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -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. diff --git a/gfx/layers/opengl/GrallocTextureClient.cpp b/gfx/layers/opengl/GrallocTextureClient.cpp index 769c5459d041..f86df1fbc936 100644 --- a/gfx/layers/opengl/GrallocTextureClient.cpp +++ b/gfx/layers/opengl/GrallocTextureClient.cpp @@ -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 = 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(&mMappedBuffer)); +#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21 + android::sp fence = android::Fence::NO_FENCE; + if (mReleaseFenceHandle.IsValid()) { + fence = mReleaseFenceHandle.mFence; + } + mReleaseFenceHandle = FenceHandle(); + int32_t rv = mGraphicBuffer->lockAsync(usage, + reinterpret_cast(&mMappedBuffer), + fence->dup()); +#else + int32_t rv = mGraphicBuffer->lock(usage, + reinterpret_cast(&mMappedBuffer)); +#endif if (rv) { mMappedBuffer = nullptr; NS_WARNING("Couldn't lock graphic buffer"); diff --git a/gfx/layers/opengl/GrallocTextureClient.h b/gfx/layers/opengl/GrallocTextureClient.h index fcb5716853fc..0eef814f93ea 100644 --- a/gfx/layers/opengl/GrallocTextureClient.h +++ b/gfx/layers/opengl/GrallocTextureClient.h @@ -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); From 971f76a2b4f94328eaf0a4c60a5bf497abf6a4ad Mon Sep 17 00:00:00 2001 From: "Byron Campen [:bwc]" Date: Mon, 26 Jan 2015 15:24:37 -0800 Subject: [PATCH 37/46] Bug 1126036: Queue runnables for starting gathering and checking in PCMedia until the proxy lookup is complete. r=mt --HG-- extra : rebase_source : 3265e13f669d08c663ab908cf96d3fb26a683f16 --- .../nICEr/src/stun/stun_server_ctx.c | 1 + .../peerconnection/PeerConnectionMedia.cpp | 66 +++++++++++++------ .../src/peerconnection/PeerConnectionMedia.h | 12 +++- 3 files changed, 57 insertions(+), 22 deletions(-) diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.c b/media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.c index accf4018148f..cd1aa028c065 100644 --- a/media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.c +++ b/media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.c @@ -109,6 +109,7 @@ static int nr_stun_server_client_create(nr_stun_server_ctx *ctx, char *client_la if(r=r_data_copy(&clnt->password,pass)) ABORT(r); + r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-SERVER(%s)/CLIENT(%s): Adding client for %s",ctx->label, client_label, user); clnt->stun_server_cb=cb; clnt->cb_arg=cb_arg; diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp index c2ab75a58dd9..547db2052855 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp @@ -213,6 +213,7 @@ OnProxyAvailable(nsICancelable *request, CSFLogInfo(logTag, "%s: Proxy Available: %d", __FUNCTION__, (int)result); if (NS_SUCCEEDED(result) && proxyinfo) { + CSFLogInfo(logTag, "%s: Had proxyinfo", __FUNCTION__); nsresult rv; nsCString httpsProxyHost; int32_t httpsProxyPort; @@ -243,7 +244,7 @@ OnProxyAvailable(nsICancelable *request, if (result != NS_ERROR_ABORT) { // NS_ERROR_ABORT means that the PeerConnectionMedia is no longer waiting pcm_->mProxyResolveCompleted = true; - pcm_->GatherIfReady(); + pcm_->FlushIceCtxOperationQueueIfReady(); } return NS_OK; @@ -261,7 +262,6 @@ PeerConnectionMedia::PeerConnectionMedia(PeerConnectionImpl *parent) mUuidGen(MakeUnique()), mMainThread(mParent->GetMainThread()), mSTSThread(mParent->GetSTSThread()), - mTransportsUpdated(false), mProxyResolveCompleted(false) { nsresult rv; @@ -400,7 +400,6 @@ PeerConnectionMedia::UpdateTransports(const mozilla::JsepSession& session) { // TODO(bug 1017888): Need to deal properly with renegotatiation. // For now just start gathering. - mTransportsUpdated = true; GatherIfReady(); } @@ -467,16 +466,17 @@ PeerConnectionMedia::StartIceChecks(const mozilla::JsepSession& session) { } } - RUN_ON_THREAD(GetSTSThread(), - WrapRunnable( - RefPtr(this), - &PeerConnectionMedia::StartIceChecks_s, - session.IsIceControlling(), - session.RemoteIsIceLite(), - // Copy, just in case API changes to return a ref - std::vector(session.GetIceOptions()), - numComponentsByLevel), - NS_DISPATCH_NORMAL); + nsRefPtr runnable( + WrapRunnable( + RefPtr(this), + &PeerConnectionMedia::StartIceChecks_s, + session.IsIceControlling(), + session.RemoteIsIceLite(), + // Copy, just in case API changes to return a ref + std::vector(session.GetIceOptions()), + numComponentsByLevel)); + + PerformOrEnqueueIceCtxOperation(runnable); } void @@ -556,17 +556,43 @@ PeerConnectionMedia::AddIceCandidate_s(const std::string& aCandidate, } } +void +PeerConnectionMedia::FlushIceCtxOperationQueueIfReady() +{ + ASSERT_ON_THREAD(mMainThread); + + if (IsIceCtxReady()) { + for (auto i = mQueuedIceCtxOperations.begin(); + i != mQueuedIceCtxOperations.end(); + ++i) { + GetSTSThread()->Dispatch(*i, NS_DISPATCH_NORMAL); + } + mQueuedIceCtxOperations.clear(); + } +} + +void +PeerConnectionMedia::PerformOrEnqueueIceCtxOperation( + const nsRefPtr& runnable) +{ + ASSERT_ON_THREAD(mMainThread); + + if (IsIceCtxReady()) { + GetSTSThread()->Dispatch(runnable, NS_DISPATCH_NORMAL); + } else { + mQueuedIceCtxOperations.push_back(runnable); + } +} + void PeerConnectionMedia::GatherIfReady() { ASSERT_ON_THREAD(mMainThread); - if (mTransportsUpdated && mProxyResolveCompleted) { - RUN_ON_THREAD(GetSTSThread(), - WrapRunnable( - RefPtr(this), - &PeerConnectionMedia::EnsureIceGathering_s), - NS_DISPATCH_NORMAL); - } + nsRefPtr runnable(WrapRunnable( + RefPtr(this), + &PeerConnectionMedia::EnsureIceGathering_s)); + + PerformOrEnqueueIceCtxOperation(runnable); } void diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h index 312d4176541d..b04ccd1fc2c7 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h @@ -466,6 +466,8 @@ class PeerConnectionMedia : public sigslot::has_slots<> { const std::string& aPassword, const std::vector& aCandidateList); void GatherIfReady(); + void FlushIceCtxOperationQueueIfReady(); + void PerformOrEnqueueIceCtxOperation(const nsRefPtr& runnable); void EnsureIceGathering_s(); void StartIceChecks_s(bool aIsControlling, bool aIsIceLite, @@ -497,6 +499,9 @@ class PeerConnectionMedia : public sigslot::has_slots<> { void EndOfLocalCandidates_m(const std::string& aDefaultAddr, uint16_t aDefaultPort, uint16_t aMLine); + bool IsIceCtxReady() const { + return mProxyResolveCompleted; + } // The parent PC @@ -539,8 +544,11 @@ class PeerConnectionMedia : public sigslot::has_slots<> { // The STS thread. nsCOMPtr mSTSThread; - // Used to track when transports are updated and are ready to start gathering - bool mTransportsUpdated; + // Used whenever we need to dispatch a runnable to STS to tweak something + // on our ICE ctx, but are not ready to do so at the moment (eg; we are + // waiting to get a callback with our http proxy config before we start + // gathering or start checking) + std::vector> mQueuedIceCtxOperations; // Used to cancel any ongoing proxy request. nsCOMPtr mProxyRequest; From c66aed798cfa9a00dbe5d2d385a95137c5267026 Mon Sep 17 00:00:00 2001 From: "Byron Campen [:bwc]" Date: Fri, 14 Nov 2014 15:58:56 -0800 Subject: [PATCH 38/46] Bug 1099414: Use RefPtr logic instead of delete when nr_socket_local_create fails. r=ekr --HG-- extra : rebase_source : 8be15d27527166b0dfb322b90e6f5244bcabcc95 --- media/mtransport/nr_socket_prsock.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/media/mtransport/nr_socket_prsock.cpp b/media/mtransport/nr_socket_prsock.cpp index 116614aecef0..ceefb2acf16c 100644 --- a/media/mtransport/nr_socket_prsock.cpp +++ b/media/mtransport/nr_socket_prsock.cpp @@ -1107,7 +1107,7 @@ static nr_socket_vtbl nr_socket_local_vtbl={ }; int nr_socket_local_create(nr_transport_addr *addr, nr_socket **sockp) { - NrSocketBase *sock = nullptr; + RefPtr sock; // create IPC bridge for content process if (XRE_GetProcessType() == GeckoProcessType_Default) { @@ -1129,15 +1129,16 @@ int nr_socket_local_create(nr_transport_addr *addr, nr_socket **sockp) { if (r) ABORT(r); - // Add a reference so that we can delete it in destroy() - sock->AddRef(); - _status = 0; -abort: - if (_status) { - delete sock; + { + // We will release this reference in destroy(), not exactly the normal + // ownership model, but it is what it is. + NrSocketBase* dummy = sock.forget().take(); + (void)dummy; } + +abort: return _status; } From 98910d890f10a07da58df2c55ae49c4a85071a93 Mon Sep 17 00:00:00 2001 From: "Byron Campen [:bwc]" Date: Tue, 23 Dec 2014 16:22:02 -0800 Subject: [PATCH 39/46] Bug 1099414: Ensure that NrSocketIpc is destroyed on STS, for consistency. r=ekr --HG-- extra : rebase_source : e706370706dd0d9ec938798966c752f298a260bf --- media/mtransport/nr_socket_prsock.cpp | 62 +++++++++++++++++++++++++-- media/mtransport/nr_socket_prsock.h | 32 ++++++++++++-- media/mtransport/runnable_utils.h | 19 ++++++++ 3 files changed, 106 insertions(+), 7 deletions(-) diff --git a/media/mtransport/nr_socket_prsock.cpp b/media/mtransport/nr_socket_prsock.cpp index ceefb2acf16c..5fe41bed7578 100644 --- a/media/mtransport/nr_socket_prsock.cpp +++ b/media/mtransport/nr_socket_prsock.cpp @@ -693,9 +693,57 @@ abort: return(_status); } -// NrSocketIpc Implementation -NS_IMPL_ISUPPORTS(NrSocketIpc, nsIUDPSocketInternal) +NS_IMPL_ISUPPORTS(NrSocketIpcProxy, nsIUDPSocketInternal) +nsresult +NrSocketIpcProxy::Init(const nsRefPtr& socket) +{ + nsresult rv; + sts_thread_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); + if (NS_FAILED(rv)) { + MOZ_ASSERT(false, "Failed to get STS thread"); + return rv; + } + + socket_ = socket; + return NS_OK; +} + +NrSocketIpcProxy::~NrSocketIpcProxy() +{ + // Send our ref to STS to be released + RUN_ON_THREAD(sts_thread_, + mozilla::WrapRelease(socket_.forget()), + NS_DISPATCH_NORMAL); +} + +// IUDPSocketInternal interfaces +// callback while error happened in UDP socket operation +NS_IMETHODIMP NrSocketIpcProxy::CallListenerError(const nsACString &message, + const nsACString &filename, + uint32_t line_number) { + return socket_->CallListenerError(message, filename, line_number); +} + +// callback while receiving UDP packet +NS_IMETHODIMP NrSocketIpcProxy::CallListenerReceivedData(const nsACString &host, + uint16_t port, + const uint8_t *data, + uint32_t data_length) { + return socket_->CallListenerReceivedData(host, port, data, data_length); +} + +// callback while UDP socket is opened +NS_IMETHODIMP NrSocketIpcProxy::CallListenerOpened() { + return socket_->CallListenerOpened(); +} + +// callback while UDP socket is closed +NS_IMETHODIMP NrSocketIpcProxy::CallListenerClosed() { + return socket_->CallListenerClosed(); +} + +// NrSocketIpc Implementation NrSocketIpc::NrSocketIpc(const nsCOMPtr &main_thread) : err_(false), state_(NR_INIT), @@ -1022,7 +1070,15 @@ void NrSocketIpc::create_m(const nsACString &host, const uint16_t port) { socket_child_ = new nsMainThreadPtrHolder(socketChild); socket_child_->SetFilterName(nsCString("stun")); - if (NS_FAILED(socket_child_->Bind(this, host, port, + nsRefPtr proxy(new NrSocketIpcProxy); + rv = proxy->Init(this); + if (NS_FAILED(rv)) { + err_ = true; + mon.NotifyAll(); + return; + } + + if (NS_FAILED(socket_child_->Bind(proxy, host, port, /* reuse = */ false, /* loopback = */ false))) { err_ = true; diff --git a/media/mtransport/nr_socket_prsock.h b/media/mtransport/nr_socket_prsock.h index 0da801435980..476a36587ada 100644 --- a/media/mtransport/nr_socket_prsock.h +++ b/media/mtransport/nr_socket_prsock.h @@ -188,8 +188,7 @@ private: DISALLOW_COPY_ASSIGN(nr_udp_message); }; -class NrSocketIpc : public NrSocketBase, - public nsIUDPSocketInternal { +class NrSocketIpc : public NrSocketBase { public: enum NrSocketIpcState { @@ -200,8 +199,17 @@ public: NR_CLOSED, }; - NS_DECL_THREADSAFE_ISUPPORTS - NS_DECL_NSIUDPSOCKETINTERNAL + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrSocketIpc) + + NS_IMETHODIMP CallListenerError(const nsACString &message, + const nsACString &filename, + uint32_t line_number); + NS_IMETHODIMP CallListenerReceivedData(const nsACString &host, + uint16_t port, + const uint8_t *data, + uint32_t data_length); + NS_IMETHODIMP CallListenerOpened(); + NS_IMETHODIMP CallListenerClosed(); explicit NrSocketIpc(const nsCOMPtr &main_thread); @@ -240,6 +248,22 @@ private: ReentrantMonitor monitor_; }; +// The socket child holds onto one of these, which just passes callbacks +// through and makes sure the ref to the NrSocketIpc is released on STS. +class NrSocketIpcProxy : public nsIUDPSocketInternal { +public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIUDPSOCKETINTERNAL + + nsresult Init(const nsRefPtr& socket); + +private: + virtual ~NrSocketIpcProxy(); + + nsRefPtr socket_; + nsCOMPtr sts_thread_; +}; + int nr_netaddr_to_transport_addr(const net::NetAddr *netaddr, nr_transport_addr *addr, int protocol); diff --git a/media/mtransport/runnable_utils.h b/media/mtransport/runnable_utils.h index 52fefdab0598..ed9d3513a625 100644 --- a/media/mtransport/runnable_utils.h +++ b/media/mtransport/runnable_utils.h @@ -96,6 +96,25 @@ RUN_ON_THREAD(nsIEventTarget *thread, detail::runnable_args_base +class DispatchedRelease : public detail::runnable_args_base { +public: + explicit DispatchedRelease(already_AddRefed& ref) : ref_(ref) {} + + NS_IMETHOD Run() { + ref_ = nullptr; + return NS_OK; + } +private: + nsRefPtr ref_; +}; + +template +DispatchedRelease* WrapRelease(already_AddRefed&& ref) +{ + return new DispatchedRelease(ref); +} + } /* namespace mozilla */ #endif From 4f31d378011abdb21d2cb0ff0d826899e24a7848 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Sat, 17 Jan 2015 17:30:21 -0500 Subject: [PATCH 40/46] Bug 1119503 - Part 1: Determine whether an element is a block element based on the style, not the tag; r=bzbarsky This probably fixes a whole bunch of edge cases where content uses elements other than div. --- dom/base/nsPlainTextSerializer.cpp | 19 ++++++++++++++++--- dom/base/nsPlainTextSerializer.h | 1 + 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/dom/base/nsPlainTextSerializer.cpp b/dom/base/nsPlainTextSerializer.cpp index be3a3b26e96c..aaf5d44ee396 100644 --- a/dom/base/nsPlainTextSerializer.cpp +++ b/dom/base/nsPlainTextSerializer.cpp @@ -670,7 +670,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); } @@ -887,8 +887,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 @@ -1778,6 +1777,20 @@ nsPlainTextSerializer::IsElementPreformatted(Element* aElement) return GetIdForContent(aElement) == nsGkAtoms::pre; } +bool +nsPlainTextSerializer::IsElementBlock(Element* aElement) +{ + nsRefPtr 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. diff --git a/dom/base/nsPlainTextSerializer.h b/dom/base/nsPlainTextSerializer.h index 479272a76ad0..ea2d049ca9ab 100644 --- a/dom/base/nsPlainTextSerializer.h +++ b/dom/base/nsPlainTextSerializer.h @@ -115,6 +115,7 @@ private: bool ShouldReplaceContainerWithPlaceholder(nsIAtom* aTag); bool IsElementPreformatted(mozilla::dom::Element* aElement); + bool IsElementBlock(mozilla::dom::Element* aElement); private: nsString mCurrentLine; From 7262a9f23c1cfa4e051e712d19c6eea87c2c00b3 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Sat, 17 Jan 2015 17:31:59 -0500 Subject: [PATCH 41/46] Bug 1119503 - Part 2: Insert a line break between preformatted block boundaries when creating raw output; r=bzbarsky --- dom/base/nsCopySupport.cpp | 3 ++- dom/base/nsIDocumentEncoder.idl | 7 +++++++ dom/base/nsPlainTextSerializer.cpp | 24 ++++++++++++++++++++++++ dom/base/nsPlainTextSerializer.h | 4 +++- dom/base/test/test_bug116083.html | 8 ++++++++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/dom/base/nsCopySupport.cpp b/dom/base/nsCopySupport.cpp index 56ac20eb145e..3f6db3928da1 100644 --- a/dom/base/nsCopySupport.cpp +++ b/dom/base/nsCopySupport.cpp @@ -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 domDoc = do_QueryInterface(aDoc); NS_ASSERTION(domDoc, "Need a document"); diff --git a/dom/base/nsIDocumentEncoder.idl b/dom/base/nsIDocumentEncoder.idl index b5963bb2db89..155e5c375c6e 100644 --- a/dom/base/nsIDocumentEncoder.idl +++ b/dom/base/nsIDocumentEncoder.idl @@ -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. diff --git a/dom/base/nsPlainTextSerializer.cpp b/dom/base/nsPlainTextSerializer.cpp index aaf5d44ee396..eb7e4b1cff43 100644 --- a/dom/base/nsPlainTextSerializer.cpp +++ b/dom/base/nsPlainTextSerializer.cpp @@ -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 @@ -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 @@ -1036,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; diff --git a/dom/base/nsPlainTextSerializer.h b/dom/base/nsPlainTextSerializer.h index ea2d049ca9ab..9535a59d9d52 100644 --- a/dom/base/nsPlainTextSerializer.h +++ b/dom/base/nsPlainTextSerializer.h @@ -170,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) diff --git a/dom/base/test/test_bug116083.html b/dom/base/test/test_bug116083.html index 4244a13aef69..5ac1181536e3 100644 --- a/dom/base/test/test_bug116083.html +++ b/dom/base/test/test_bug116083.html @@ -20,6 +20,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=116083
bar baz
bar baz
bar baz
+
foo
bar

!


baz
+
foo
bar

!


baz
+
foo
bar

!


baz
+
foo
bar

!


baz
+
foo
bar

!


baz
+
foo
bar

!


baz
+
foo
bar

!


baz
+
foo
bar

!


baz
foo bar