Merge inbound to mozilla-central. a=merge
Merge inbound to mozilla-central. a=merge
--- a/accessible/tests/mochitest/actions/a11y.ini
+++ b/accessible/tests/mochitest/actions/a11y.ini
@@ -7,12 +7,11 @@ support-files =
[test_aria.html]
[test_controls.html]
[test_general.html]
[test_general.xul]
[test_keys.html]
[test_keys_menu.xul]
[test_link.html]
[test_media.html]
-skip-if = buildapp == 'mulet'
[test_select.html]
[test_tree.xul]
[test_treegrid.xul]
--- a/accessible/tests/mochitest/elm/a11y.ini
+++ b/accessible/tests/mochitest/elm/a11y.ini
@@ -1,17 +1,15 @@
[DEFAULT]
support-files =
!/accessible/tests/mochitest/*.js
!/accessible/tests/mochitest/moz.png
!/dom/media/test/bug461281.ogg
[test_HTMLSpec.html]
-skip-if = buildapp == 'mulet'
[test_figure.html]
[test_listbox.xul]
[test_MathMLSpec.html]
[test_nsApplicationAcc.html]
[test_plugin.html]
-skip-if = buildapp == 'mulet'
[test_canvas.html]
[test_shadowroot.html]
support-files = test_shadowroot_subframe.html
--- a/accessible/tests/mochitest/events/a11y.ini
+++ b/accessible/tests/mochitest/events/a11y.ini
@@ -42,17 +42,17 @@ skip-if = webrender
[test_menu.xul]
[test_mutation.html]
[test_mutation.xhtml]
[test_namechange.xul]
[test_namechange.html]
[test_scroll.xul]
[test_scroll_caret.xul]
[test_selection.html]
-skip-if = buildapp == 'mulet' || os == 'mac'
+skip-if = os == 'mac'
[test_selection.xul]
skip-if = os == 'mac'
[test_selection_aria.html]
[test_statechange.html]
[test_text.html]
[test_text_alg.html]
[test_textattrchange.html]
[test_textselchange.html]
--- a/accessible/tests/mochitest/focus/a11y.ini
+++ b/accessible/tests/mochitest/focus/a11y.ini
@@ -1,9 +1,8 @@
[DEFAULT]
support-files =
!/accessible/tests/mochitest/*.js
[test_focusedChild.html]
skip-if = (os == 'win' && os_version != '6.1') # bug 845134
[test_takeFocus.html]
-skip-if = buildapp == 'mulet'
[test_takeFocus.xul]
--- a/accessible/tests/mochitest/tree/a11y.ini
+++ b/accessible/tests/mochitest/tree/a11y.ini
@@ -25,29 +25,27 @@ skip-if = true # Bug 561508
[test_combobox.xul]
[test_cssflexbox.html]
[test_cssoverflow.html]
[test_display_contents.html]
[test_dochierarchy.html]
[test_dockids.html]
[test_filectrl.html]
[test_formctrl.html]
-skip-if = buildapp == "mulet"
[test_formctrl.xul]
[test_gencontent.html]
[test_groupbox.xul]
[test_iframe.html]
[test_image.xul]
[test_img.html]
[test_invalid_img.xhtml]
[test_invalidationlist.html]
[test_list.html]
[test_map.html]
[test_media.html]
-skip-if = buildapp == "mulet"
[test_select.html]
[test_tabbox.xul]
[test_tabbrowser.xul]
skip-if = (os == 'linux' && debug) || (os == 'win' && ccov) # Bug 1389365 || bug 1423218
[test_table.html]
[test_table_2.html]
[test_table_3.html]
[test_tree.xul]
--- a/accessible/tests/mochitest/treeupdate/a11y.ini
+++ b/accessible/tests/mochitest/treeupdate/a11y.ini
@@ -21,17 +21,16 @@ support-files = test_bug1276857_subframe
[test_contextmenu.xul]
[test_cssoverflow.html]
[test_deck.xul]
[test_doc.html]
[test_gencontent.html]
[test_general.html]
[test_hidden.html]
[test_imagemap.html]
-skip-if = buildapp == "mulet"
[test_list.html]
[test_list_editabledoc.html]
[test_listbox.xul]
[test_menu.xul]
[test_menubutton.xul]
[test_optgroup.html]
[test_recreation.html]
[test_select.html]
--- a/devtools/shared/heapsnapshot/tests/gtest/DevTools.h
+++ b/devtools/shared/heapsnapshot/tests/gtest/DevTools.h
@@ -93,17 +93,17 @@ struct DevTools : public ::testing::Test
JS::FireOnNewGlobalHook, options);
if (!newGlobal)
return nullptr;
JSAutoRealm ar(cx, newGlobal);
/* Populate the global object with the standard globals, like Object and
Array. */
- if (!JS_InitStandardClasses(cx, newGlobal))
+ if (!JS::InitRealmStandardClasses(cx))
return nullptr;
return newGlobal;
}
virtual void TearDown() {
_initialized = false;
--- a/devtools/shared/heapsnapshot/tests/gtest/DoesCrossCompartmentBoundaries.cpp
+++ b/devtools/shared/heapsnapshot/tests/gtest/DoesCrossCompartmentBoundaries.cpp
@@ -14,17 +14,17 @@ DEF_TEST(DoesCrossCompartmentBoundaries,
getGlobalClass(),
nullptr,
JS::FireOnNewGlobalHook,
options));
ASSERT_TRUE(newGlobal);
JS::Compartment* newCompartment = nullptr;
{
JSAutoRealm ar(cx, newGlobal);
- ASSERT_TRUE(JS_InitStandardClasses(cx, newGlobal));
+ ASSERT_TRUE(JS::InitRealmStandardClasses(cx));
newCompartment = js::GetContextCompartment(cx);
}
ASSERT_TRUE(newCompartment);
ASSERT_NE(newCompartment, compartment);
// Our set of target compartments is both the old and new compartments.
JS::CompartmentSet targetCompartments;
ASSERT_TRUE(targetCompartments.init());
--- a/devtools/shared/heapsnapshot/tests/gtest/DoesntCrossCompartmentBoundaries.cpp
+++ b/devtools/shared/heapsnapshot/tests/gtest/DoesntCrossCompartmentBoundaries.cpp
@@ -14,17 +14,17 @@ DEF_TEST(DoesntCrossCompartmentBoundarie
getGlobalClass(),
nullptr,
JS::FireOnNewGlobalHook,
options));
ASSERT_TRUE(newGlobal);
JS::Compartment* newCompartment = nullptr;
{
JSAutoRealm ar(cx, newGlobal);
- ASSERT_TRUE(JS_InitStandardClasses(cx, newGlobal));
+ ASSERT_TRUE(JS::InitRealmStandardClasses(cx));
newCompartment = js::GetContextCompartment(cx);
}
ASSERT_TRUE(newCompartment);
ASSERT_NE(newCompartment, compartment);
// Our set of target compartments is only the pre-existing compartment and
// does not include the new compartment.
JS::CompartmentSet targetCompartments;
--- a/dom/animation/ComputedTimingFunction.h
+++ b/dom/animation/ComputedTimingFunction.h
@@ -39,16 +39,17 @@ public:
Frames(uint32_t aFrames)
{
MOZ_ASSERT(aFrames > 1, "The number of frames should be 2 or more");
return ComputedTimingFunction(nsTimingFunction::Type::Frames, aFrames);
}
ComputedTimingFunction() = default;
explicit ComputedTimingFunction(const nsTimingFunction& aFunction)
+ : mStepsOrFrames(0)
{
Init(aFunction);
}
void Init(const nsTimingFunction& aFunction);
// BeforeFlag is used in step timing function.
// https://drafts.csswg.org/css-timing/#before-flag
enum class BeforeFlag {
@@ -109,17 +110,20 @@ public:
return aFunction ? aFunction->GetValue(aPortion, aBeforeFlag) : aPortion;
}
static int32_t Compare(const Maybe<ComputedTimingFunction>& aLhs,
const Maybe<ComputedTimingFunction>& aRhs);
private:
ComputedTimingFunction(double x1, double y1, double x2, double y2)
: mType(nsTimingFunction::Type::CubicBezier)
- , mTimingFunction(x1, y1, x2, y2) { }
+ , mTimingFunction(x1, y1, x2, y2)
+ , mStepsOrFrames(0)
+ {
+ }
ComputedTimingFunction(nsTimingFunction::Type aType, uint32_t aStepsOrFrames)
: mType(aType)
, mStepsOrFrames(aStepsOrFrames) { }
nsTimingFunction::Type mType = nsTimingFunction::Type::Linear;
nsSMILKeySpline mTimingFunction;
uint32_t mStepsOrFrames;
};
--- a/dom/base/test/chrome.ini
+++ b/dom/base/test/chrome.ini
@@ -23,15 +23,14 @@ support-files =
[test_bug1008126.html]
[test_bug1016960.html]
[test_copypaste.xul]
subsuite = clipboard
[test_domrequesthelper.xul]
[test_fragment_sanitization.xul]
[test_messagemanager_principal.html]
[test_messagemanager_send_principal.html]
-skip-if = buildapp == 'mulet'
[test_mozbrowser_apis_allowed.html]
[test_navigator_resolve_identity_xrays.xul]
support-files = file_navigator_resolve_identity_xrays.xul
[test_sandboxed_blob_uri.html]
[test_sendQueryContentAndSelectionSetEvent.html]
[test_urgent_start.html]
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -3057,18 +3057,17 @@ CreateGlobal(JSContext* aCx, T* aNative,
dom::AllocateProtoAndIfaceCache(aGlobal,
CreateGlobalOptions<T>::ProtoAndIfaceCacheKind);
if (!CreateGlobalOptions<T>::PostCreateGlobal(aCx, aGlobal)) {
return false;
}
}
- if (aInitStandardClasses &&
- !JS_InitStandardClasses(aCx, aGlobal)) {
+ if (aInitStandardClasses && !JS::InitRealmStandardClasses(aCx)) {
NS_WARNING("Failed to init standard classes");
return false;
}
JS::Handle<JSObject*> proto = GetProto(aCx);
if (!proto || !JS_SplicePrototype(aCx, aGlobal, proto)) {
NS_WARNING("Failed to set proto");
return false;
--- a/dom/canvas/test/webgl-conf/generated-mochitest.ini
+++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini
@@ -1,15 +1,15 @@
# This is a GENERATED FILE. Do not edit it directly.
# Regenerated it by using `python generate-wrappers-and-manifest.py`.
# Mark failing (fail-if) and crashing (skip-if) tests in mochitest-errata.ini.
[DEFAULT]
subsuite = webgl
-skip-if = (os == 'linux') && (buildapp == 'mulet')
+skip-if = os == 'linux'
support-files = always-fail.html
checkout/00_test_list.txt
checkout/CONFORMANCE_RULES.txt
checkout/README.md
checkout/closure-library/AUTHORS
checkout/closure-library/CONTRIBUTING
checkout/closure-library/LICENSE
--- a/dom/canvas/test/webgl-conf/mochitest-errata.ini
+++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini
@@ -18,18 +18,17 @@
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832%28v=vs.85%29.aspx
# * Windows 7: 6.1
# * Windows 8: 6.2
# * Windows 8.1: 6.3
# * Windows 10: 10.0
[DEFAULT]
subsuite = webgl
-# Bug 1136181 disabled on Mulet for intermittent failures
-skip-if = (os == 'linux') && (buildapp == 'mulet')
+skip-if = os == 'linux'
[generated/test_..__always-fail.html]
fail-if = 1
####################
# Tests requesting non-local network connections.
[generated/test_conformance__more__functions__readPixelsBadArgs.html]
@@ -194,17 +193,17 @@ skip-if = ((os == 'linux') && asan)
[generated/test_conformance__glsl__bugs__sampler-array-using-loop-index.html]
# Testfail on Linux after removing SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX.
# Only happen on tryserver
fail-if = (os == 'linux')
[generated/test_conformance__misc__type-conversion-test.html]
fail-if = (os == 'linux')
# Resets device on Android 2.3.
-# Crashes on desktop Linux, and Mulet Linux x64.
+# Crashes on desktop Linux.
skip-if = (os == 'android') || (os == 'linux')
[generated/test_conformance__misc__object-deletion-behaviour.html]
fail-if = (os == 'android')
# void mozilla::gl::GLContext::fDetachShader(GLuint, GLuint): Generated unexpected GL_INVALID_VALUE error. (0x0501)
skip-if = (os == 'android' && debug)
[generated/test_conformance__textures__misc__texture-size.html]
@@ -357,20 +356,19 @@ skip-if = (os == 'win')
[generated/test_2_conformance__rendering__rendering-stencil-large-viewport.html]
# same as webgl1 test
fail-if = (os == 'mac')
skip-if = (os == 'win')
########################################################################
# "tst-linux{32,64}-spot-NNN" Slaves:
-# Android 2.3, Linux, and Mulet.
+# Android 2.3 and Linux.
# Android: os == 'android'. (Not enough info to separate out 2.3)
# Linux: os == 'linux'.
-# Mulet: buildapp == 'mulet'.
[generated/test_conformance__glsl__bugs__temp-expressions-should-not-crash.html]
# Coincidentally enough, crashes on Linux and Android 4.0.
skip-if = (os == 'android') || (os == 'linux')
[generated/test_conformance__misc__invalid-passed-params.html]
# Causes consistent *blues*: "DMError: Remote Device Error: unable to
# connect to 127.0.0.1 after 5 attempts" on 'Android 2.3 Opt'.
skip-if = (os == 'android') || (os == 'linux')
[generated/test_conformance__ogles__GL__functions__functions_001_to_008.html]
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -1063,16 +1063,34 @@ nsHTMLDocument::CreateDummyChannelForCoo
nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel =
do_QueryInterface(channel);
nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
if (!pbChannel || !loadContext) {
return nullptr;
}
pbChannel->SetPrivate(loadContext->UsePrivateBrowsing());
+
+ nsCOMPtr<nsIHttpChannel> docHTTPChannel =
+ do_QueryInterface(GetChannel());
+ if (docHTTPChannel) {
+ bool isTracking = docHTTPChannel->GetIsTrackingResource();
+ if (isTracking) {
+ // If our document channel is from a tracking resource, we must
+ // override our channel's tracking status.
+ nsCOMPtr<nsIHttpChannel> httpChannel =
+ do_QueryInterface(channel);
+ MOZ_ASSERT(httpChannel, "How come we're coming from an HTTP doc but "
+ "we don't have an HTTP channel here?");
+ if (httpChannel) {
+ httpChannel->OverrideTrackingResource(isTracking);
+ }
+ }
+ }
+
return channel.forget();
}
void
nsHTMLDocument::GetCookie(nsAString& aCookie, ErrorResult& rv)
{
aCookie.Truncate(); // clear current cookie in case service fails;
// no cookie isn't an error condition.
--- a/dom/html/reftests/reftest.list
+++ b/dom/html/reftests/reftest.list
@@ -57,16 +57,16 @@ fuzzy(3,640) fuzzy-if(skiaContent,3,7544
== table-border-2.html table-border-2-ref.html
!= table-border-2.html table-border-2-notref.html
# Test imageset is using permissions.default.image
pref(permissions.default.image,1) HTTP == bug1196784-with-srcset.html bug1196784-no-srcset.html
pref(permissions.default.image,2) HTTP == bug1196784-with-srcset.html bug1196784-no-srcset.html
# Test video with rotation information can be rotated.
-fails-if(webrender) == bug1228601-video-rotation-90.html bug1228601-video-rotated-ref.html
+== bug1228601-video-rotation-90.html bug1228601-video-rotated-ref.html
# Test that dynamically setting body margin attributes updates style appropriately
== body-topmargin-dynamic.html body-topmargin-ref.html
# Test that dynamically removing a nonmargin mapped attribute does not
# destroy margins inherited from the frame.
== body-frame-margin-remove-other-pres-hint.html body-frame-margin-remove-other-pres-hint-ref.html
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -1776,19 +1776,24 @@ nsPluginHost::ClearSiteData(nsIPluginTag
#define GetSitesClosure_CID {0x4c9268ac, 0x2fd1, 0x4f2a, {0x9a, 0x10, 0x7a, 0x09, 0xf1, 0xb7, 0x60, 0x3a}}
// Closure to contain the data needed to handle the callback from NPP_GetSitesWithData
class GetSitesClosure : public nsIGetSitesWithDataCallback {
public:
NS_DECL_ISUPPORTS
GetSitesClosure(const nsACString& domain, nsPluginHost* host)
- : domain(domain), host(host), keepWaiting(true)
+ : domain(domain)
+ , host(host)
+ , result{ false }
+ , keepWaiting(true)
+ , retVal(NS_ERROR_NOT_INITIALIZED)
{
}
+
NS_IMETHOD SitesWithData(InfallibleTArray<nsCString>& sites) override {
retVal = HandleGetSites(sites);
keepWaiting = false;
return NS_OK;
}
nsresult HandleGetSites(InfallibleTArray<nsCString>& sites) {
// If there's no data, we're done.
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -253,16 +253,17 @@ nsPluginInstanceOwner::GetCurrentImageSi
if (mInstance) {
mInstance->GetImageSize(&size);
}
return size;
}
nsPluginInstanceOwner::nsPluginInstanceOwner()
: mPluginWindow(nullptr)
+ , mLastEventloopNestingLevel(0)
{
// create nsPluginNativeWindow object, it is derived from NPWindow
// struct and allows to manipulate native window procedure
nsCOMPtr<nsIPluginHost> pluginHostCOM = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
mPluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
if (mPluginHost)
mPluginHost->NewPluginNativeWindow(&mPluginWindow);
--- a/dom/plugins/base/nsPluginManifestLineReader.h
+++ b/dom/plugins/base/nsPluginManifestLineReader.h
@@ -15,17 +15,21 @@
#define PLUGIN_REGISTRY_FIELD_DELIMITER ':'
#endif
#define PLUGIN_REGISTRY_END_OF_LINE_MARKER '$'
class nsPluginManifestLineReader
{
public:
- nsPluginManifestLineReader() {mBase = mCur = mNext = mLimit = 0;}
+ nsPluginManifestLineReader()
+ : mLength(0)
+ {
+ mBase = mCur = mNext = mLimit = 0;
+ }
~nsPluginManifestLineReader() { if (mBase) delete[] mBase; mBase=0;}
char* Init(uint32_t flen)
{
mBase = mCur = mNext = new char[flen + 1];
if (mBase) {
mLimit = mBase + flen;
*mLimit = 0;
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
@@ -39,16 +39,17 @@ NS_IMPL_ISUPPORTS(nsPluginStreamListener
nsIStreamListener,
nsIRequestObserver,
nsIHttpHeaderVisitor,
nsISupportsWeakReference,
nsIInterfaceRequestor,
nsIChannelEventSink)
nsPluginStreamListenerPeer::nsPluginStreamListenerPeer()
+ : mLength(0)
{
mStreamType = NP_NORMAL;
mStartBinding = false;
mRequestFailed = false;
mPendingRequests = 0;
mHaveFiredOnStartRequest = false;
--- a/dom/plugins/base/nsPluginTags.cpp
+++ b/dom/plugins/base/nsPluginTags.cpp
@@ -298,29 +298,35 @@ nsPluginTag::nsPluginTag(uint32_t aId,
nsTArray<nsCString> aMimeDescriptions,
nsTArray<nsCString> aExtensions,
bool aIsFlashPlugin,
bool aSupportsAsyncRender,
int64_t aLastModifiedTime,
bool aFromExtension,
int32_t aSandboxLevel,
uint32_t aBlocklistState)
- : nsIInternalPluginTag(aName, aDescription, aFileName, aVersion, aMimeTypes,
- aMimeDescriptions, aExtensions),
- mId(aId),
- mContentProcessRunningCount(0),
- mLibrary(nullptr),
- mIsFlashPlugin(aIsFlashPlugin),
- mSupportsAsyncRender(aSupportsAsyncRender),
- mLastModifiedTime(aLastModifiedTime),
- mSandboxLevel(aSandboxLevel),
- mIsSandboxLoggingEnabled(false),
- mNiceFileName(),
- mIsFromExtension(aFromExtension),
- mBlocklistState(aBlocklistState)
+ : nsIInternalPluginTag(aName,
+ aDescription,
+ aFileName,
+ aVersion,
+ aMimeTypes,
+ aMimeDescriptions,
+ aExtensions)
+ , mId(aId)
+ , mContentProcessRunningCount(0)
+ , mHadLocalInstance(false)
+ , mLibrary(nullptr)
+ , mIsFlashPlugin(aIsFlashPlugin)
+ , mSupportsAsyncRender(aSupportsAsyncRender)
+ , mLastModifiedTime(aLastModifiedTime)
+ , mSandboxLevel(aSandboxLevel)
+ , mIsSandboxLoggingEnabled(false)
+ , mNiceFileName()
+ , mIsFromExtension(aFromExtension)
+ , mBlocklistState(aBlocklistState)
{
}
nsPluginTag::~nsPluginTag()
{
NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
}
--- a/dom/plugins/base/nsPluginsDirDarwin.cpp
+++ b/dom/plugins/base/nsPluginsDirDarwin.cpp
@@ -262,18 +262,19 @@ static void ParsePlistPluginInfo(nsPlugi
CFTypeRef description = ::CFDictionaryGetValue(static_cast<CFDictionaryRef>(mimeDict), CFSTR("WebPluginTypeDescription"));
if (description && ::CFGetTypeID(description) == ::CFStringGetTypeID())
info.fMimeDescriptionArray[info.fVariantCount] = CFStringRefToUTF8Buffer(static_cast<CFStringRef>(description));
}
info.fVariantCount++;
}
}
-nsPluginFile::nsPluginFile(nsIFile *spec)
- : mPlugin(spec)
+nsPluginFile::nsPluginFile(nsIFile* spec)
+ : pLibrary(nullptr)
+ , mPlugin(spec)
{
}
nsPluginFile::~nsPluginFile() {}
nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary)
{
if (!mPlugin)
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -131,16 +131,17 @@ PluginInstanceChild::PluginInstanceChild
const InfallibleTArray<nsCString>& aValues)
: mPluginIface(aPluginIface)
, mMimeType(aMimeType)
, mNames(aNames)
, mValues(aValues)
#if defined(XP_DARWIN) || defined (XP_WIN)
, mContentsScaleFactor(1.0)
#endif
+ , mCSSZoomFactor(0.0)
, mPostingKeyEvents(0)
, mPostingKeyEventsOutdated(0)
, mDrawingModel(kDefaultDrawingModel)
, mCurrentDirectSurface(nullptr)
, mAsyncInvalidateMutex("PluginInstanceChild::mAsyncInvalidateMutex")
, mAsyncInvalidateTask(0)
, mCachedWindowActor(nullptr)
, mCachedElementActor(nullptr)
@@ -155,16 +156,17 @@ PluginInstanceChild::PluginInstanceChild
#endif // OS_WIN
#if defined(MOZ_WIDGET_COCOA)
#if defined(__i386__)
, mEventModel(NPEventModelCarbon)
#endif
, mShColorSpace(nullptr)
, mShContext(nullptr)
, mCGLayer(nullptr)
+ , mCARefreshTimer(0)
, mCurrentEvent(nullptr)
#endif
, mLayersRendering(false)
#ifdef XP_WIN
, mCurrentSurfaceActor(nullptr)
, mBackSurfaceActor(nullptr)
#endif
, mAccumulatedInvalidRect(0,0,0,0)
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -193,26 +193,27 @@ namespace {
/**
* Objects of this class remain linked until an error occurs in the
* plugin initialization sequence.
*/
class PluginModuleMapping : public PRCList
{
public:
- explicit PluginModuleMapping(uint32_t aPluginId)
- : mPluginId(aPluginId)
- , mProcessIdValid(false)
- , mModule(nullptr)
- , mChannelOpened(false)
- {
- MOZ_COUNT_CTOR(PluginModuleMapping);
- PR_INIT_CLIST(this);
- PR_APPEND_LINK(this, &sModuleListHead);
- }
+ explicit PluginModuleMapping(uint32_t aPluginId)
+ : mPluginId(aPluginId)
+ , mProcessIdValid(false)
+ , mProcessId(0)
+ , mModule(nullptr)
+ , mChannelOpened(false)
+ {
+ MOZ_COUNT_CTOR(PluginModuleMapping);
+ PR_INIT_CLIST(this);
+ PR_APPEND_LINK(this, &sModuleListHead);
+ }
~PluginModuleMapping()
{
PR_REMOVE_LINK(this);
MOZ_COUNT_DTOR(PluginModuleMapping);
}
bool
@@ -585,29 +586,30 @@ PluginModuleChromeParent::InitCrashRepor
shmem,
threadId);
}
return true;
}
PluginModuleParent::PluginModuleParent(bool aIsChrome)
- : mQuirks(QUIRKS_NOT_INITIALIZED)
- , mIsChrome(aIsChrome)
- , mShutdown(false)
- , mHadLocalInstance(false)
- , mClearSiteDataSupported(false)
- , mGetSitesWithDataSupported(false)
- , mNPNIface(nullptr)
- , mNPPIface(nullptr)
- , mPlugin(nullptr)
- , mTaskFactory(this)
- , mSandboxLevel(0)
- , mIsFlashPlugin(false)
- , mCrashReporterMutex("PluginModuleChromeParent::mCrashReporterMutex")
+ : mQuirks(QUIRKS_NOT_INITIALIZED)
+ , mIsChrome(aIsChrome)
+ , mShutdown(false)
+ , mHadLocalInstance(false)
+ , mClearSiteDataSupported(false)
+ , mGetSitesWithDataSupported(false)
+ , mNPNIface(nullptr)
+ , mNPPIface(nullptr)
+ , mPlugin(nullptr)
+ , mTaskFactory(this)
+ , mSandboxLevel(0)
+ , mIsFlashPlugin(false)
+ , mRunID(0)
+ , mCrashReporterMutex("PluginModuleChromeParent::mCrashReporterMutex")
{
}
PluginModuleParent::~PluginModuleParent()
{
if (!OkToCleanup()) {
MOZ_CRASH("unsafe destruction");
}
@@ -615,47 +617,49 @@ PluginModuleParent::~PluginModuleParent(
if (!mShutdown) {
NS_WARNING("Plugin host deleted the module without shutting down.");
NPError err;
NP_Shutdown(&err);
}
}
PluginModuleContentParent::PluginModuleContentParent()
- : PluginModuleParent(false)
+ : PluginModuleParent(false)
+ , mPluginId(0)
{
- Preferences::RegisterCallback(TimeoutChanged, kContentTimeoutPref, this);
+ Preferences::RegisterCallback(TimeoutChanged, kContentTimeoutPref, this);
}
PluginModuleContentParent::~PluginModuleContentParent()
{
Preferences::UnregisterCallback(TimeoutChanged, kContentTimeoutPref, this);
}
PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath,
uint32_t aPluginId,
int32_t aSandboxLevel)
- : PluginModuleParent(true)
- , mSubprocess(new PluginProcessParent(aFilePath))
- , mPluginId(aPluginId)
- , mChromeTaskFactory(this)
- , mHangAnnotationFlags(0)
+ : PluginModuleParent(true)
+ , mSubprocess(new PluginProcessParent(aFilePath))
+ , mPluginId(aPluginId)
+ , mChromeTaskFactory(this)
+ , mHangAnnotationFlags(0)
#ifdef XP_WIN
- , mPluginCpuUsageOnHang()
- , mHangUIParent(nullptr)
- , mHangUIEnabled(true)
- , mIsTimerReset(true)
- , mBrokerParent(nullptr)
+ , mPluginCpuUsageOnHang()
+ , mHangUIParent(nullptr)
+ , mHangUIEnabled(true)
+ , mIsTimerReset(true)
+ , mBrokerParent(nullptr)
#endif
#ifdef MOZ_CRASHREPORTER_INJECTOR
- , mFlashProcess1(0)
- , mFlashProcess2(0)
- , mFinishInitTask(nullptr)
+ , mFlashProcess1(0)
+ , mFlashProcess2(0)
+ , mFinishInitTask(nullptr)
#endif
- , mIsCleaningFromTimeout(false)
+ , mIsBlocklisted(false)
+ , mIsCleaningFromTimeout(false)
{
NS_ASSERTION(mSubprocess, "Out of memory!");
mSandboxLevel = aSandboxLevel;
mRunID = GeckoChildProcessHost::GetUniqueID();
mozilla::HangMonitor::RegisterAnnotator(*this);
}
--- a/dom/security/SRICheck.cpp
+++ b/dom/security/SRICheck.cpp
@@ -180,20 +180,22 @@ SRICheck::IntegrityMetadata(const nsAStr
}
//////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////
SRICheckDataVerifier::SRICheckDataVerifier(const SRIMetadata& aMetadata,
const nsACString& aSourceFileURI,
nsIConsoleReportCollector* aReporter)
- : mCryptoHash(nullptr),
- mBytesHashed(0),
- mInvalidMetadata(false),
- mComplete(false)
+ : mCryptoHash(nullptr)
+ , mBytesHashed(0)
+ , mHashLength(0)
+ , mHashType('\0')
+ , mInvalidMetadata(false)
+ , mComplete(false)
{
MOZ_ASSERT(!aMetadata.IsEmpty()); // should be checked by caller
// IntegrityMetadata() checks this and returns "no metadata" if
// it's disabled so we should never make it this far
MOZ_ASSERT(Preferences::GetBool("security.sri.enable", false));
MOZ_ASSERT(aReporter);
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -2557,17 +2557,17 @@ RuntimeService::ClampedHardwareConcurren
// other worker has initialized numberOfProcessors, so we're good to go.
if (!clampedHardwareConcurrency) {
int32_t numberOfProcessors = PR_GetNumberOfProcessors();
if (numberOfProcessors <= 0) {
numberOfProcessors = 1; // Must be one there somewhere
}
uint32_t clampedValue = std::min(uint32_t(numberOfProcessors),
gMaxHardwareConcurrency);
- clampedHardwareConcurrency.compareExchange(0, clampedValue);
+ Unused << clampedHardwareConcurrency.compareExchange(0, clampedValue);
}
return clampedHardwareConcurrency;
}
// nsISupports
NS_IMPL_ISUPPORTS(RuntimeService, nsIObserver)
--- a/editor/libeditor/SelectionState.cpp
+++ b/editor/libeditor/SelectionState.cpp
@@ -634,16 +634,18 @@ RangeUpdater::DidMoveNode(nsINode* aOldP
/******************************************************************************
* mozilla::RangeItem
*
* Helper struct for SelectionState. This stores range endpoints.
******************************************************************************/
RangeItem::RangeItem()
+ : mStartOffset{0}
+ , mEndOffset{0}
{
}
RangeItem::~RangeItem()
{
}
NS_IMPL_CYCLE_COLLECTION(RangeItem, mStartContainer, mEndContainer)
--- a/editor/spellchecker/nsFilteredContentIterator.h
+++ b/editor/spellchecker/nsFilteredContentIterator.h
@@ -42,17 +42,22 @@ public:
virtual bool IsDone() override;
virtual nsresult PositionAt(nsINode* aCurNode) override;
/* Helpers */
bool DidSkip() { return mDidSkip; }
void ClearDidSkip() { mDidSkip = false; }
protected:
- nsFilteredContentIterator() : mDidSkip(false), mIsOutOfRange(false) { }
+ nsFilteredContentIterator()
+ : mDidSkip(false)
+ , mIsOutOfRange(false)
+ , mDirection{eDirNotSet}
+ {
+ }
virtual ~nsFilteredContentIterator();
/**
* Callers must guarantee that mRange isn't nullptr and it's positioned.
*/
nsresult InitWithRange();
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -554,16 +554,20 @@ public:
* Default implementation in this class is to ignore the hint.
* Can be called on any thread. This method takes mRecursiveMutex
* when accessing thread-shared state.
*/
void SetScaleHint(const gfx::IntSize& aScaleHint) { mScaleHint = aScaleHint; }
const gfx::IntSize& GetScaleHint() const { return mScaleHint; }
+ void SetTransformHint(const gfx::Matrix& aTransformHint) { mTransformHint = aTransformHint; }
+
+ const gfx::Matrix& GetTransformHint() const { return mTransformHint; }
+
void SetImageFactory(ImageFactory *aFactory)
{
RecursiveMutexAutoLock lock(mRecursiveMutex);
mImageFactory = aFactory ? aFactory : new ImageFactory();
}
ImageFactory* GetImageFactory() const
{
@@ -676,16 +680,18 @@ private:
// This is the image factory used by this container, layer managers using
// this container can set an alternative image factory that will be used to
// create images for this container.
RefPtr<ImageFactory> mImageFactory;
gfx::IntSize mScaleHint;
+ gfx::Matrix mTransformHint;
+
RefPtr<BufferRecycleBin> mRecycleBin;
// This member points to an ImageClient if this ImageContainer was
// sucessfully created with ENABLE_ASYNC, or points to null otherwise.
// 'unsuccessful' in this case only means that the ImageClient could not
// be created, most likely because off-main-thread compositing is not enabled.
// In this case the ImageContainer is perfectly usable, but it will forward
// frames to the compositor through transactions in the main thread rather than
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -1402,25 +1402,26 @@ WebRenderCommandBuilder::CreateImageKey(
MOZ_ASSERT(aAsyncImageBounds);
LayoutDeviceRect rect = aAsyncImageBounds.value();
LayoutDeviceRect scBounds(LayoutDevicePoint(0, 0), rect.Size());
gfx::MaybeIntSize scaleToSize;
if (!aContainer->GetScaleHint().IsEmpty()) {
scaleToSize = Some(aContainer->GetScaleHint());
}
+ gfx::Matrix4x4 transform = gfx::Matrix4x4::From2D(aContainer->GetTransformHint());
// TODO!
// We appear to be using the image bridge for a lot (most/all?) of
// layers-free image handling and that breaks frame consistency.
imageData->CreateAsyncImageWebRenderCommands(aBuilder,
aContainer,
aSc,
rect,
scBounds,
- gfx::Matrix4x4(),
+ transform,
scaleToSize,
wr::ImageRendering::Auto,
wr::MixBlendMode::Normal,
!aItem->BackfaceIsHidden());
return Nothing();
}
AutoLockImage autoLock(aContainer);
--- a/gfx/webrender_bindings/src/program_cache.rs
+++ b/gfx/webrender_bindings/src/program_cache.rs
@@ -56,19 +56,30 @@ fn get_cache_path_from_prof_path(prof_pa
let prof_path = OsString::from_wide(prof_path.as_ref());
let mut cache_path = PathBuf::from(&prof_path);
cache_path.push("shader-cache");
Some(cache_path)
}
#[cfg(not(target_os="windows"))]
-fn get_cache_path_from_prof_path(_prof_path: &nsAString) -> Option<PathBuf> {
- // Not supported yet.
- None
+fn get_cache_path_from_prof_path(prof_path: &nsAString) -> Option<PathBuf> {
+ if prof_path.is_empty() {
+ // Empty means that we do not use disk cache.
+ return None;
+ }
+
+ use std::ffi::OsString;
+
+ let utf8 = String::from_utf16(prof_path.as_ref()).unwrap();
+ let prof_path = OsString::from(utf8);
+ let mut cache_path = PathBuf::from(&prof_path);
+ cache_path.push("shader-cache");
+
+ Some(cache_path)
}
struct WrProgramBinaryDiskCache {
cache_path: Option<PathBuf>,
program_count: u32,
is_enabled: bool,
workers: Arc<ThreadPool>,
}
@@ -231,52 +242,40 @@ impl ProgramCacheObserver for WrProgramC
pub struct WrProgramCache {
program_cache: Rc<ProgramCache>,
disk_cache: Option<Rc<RefCell<WrProgramBinaryDiskCache>>>,
}
impl WrProgramCache {
- #[cfg(target_os = "windows")]
pub fn new(prof_path: &nsAString, workers: &Arc<ThreadPool>) -> Self {
let disk_cache = Rc::new(RefCell::new(WrProgramBinaryDiskCache::new(prof_path, workers)));
let program_cache_observer = Box::new(WrProgramCacheObserver::new(Rc::clone(&disk_cache)));
let program_cache = ProgramCache::new(Some(program_cache_observer));
WrProgramCache {
program_cache,
disk_cache: Some(disk_cache),
}
}
- #[cfg(not(target_os="windows"))]
- pub fn new(_prof_path: &nsAString, _: &Arc<ThreadPool>) -> Self {
- let program_cache = ProgramCache::new(None);
-
- WrProgramCache {
- program_cache,
- disk_cache: None,
- }
- }
-
pub fn rc_get(&self) -> &Rc<ProgramCache> {
&self.program_cache
}
pub fn try_load_from_disk(&self) {
if let Some(ref disk_cache) = self.disk_cache {
disk_cache.borrow_mut().try_load_from_disk(&self.program_cache);
} else {
error!("Shader disk cache is not supported");
}
}
}
-#[cfg(target_os = "windows")]
pub fn remove_disk_cache(prof_path: &nsAString) -> Result<(), Error> {
use std::fs::remove_dir_all;
use std::time::{Instant};
if let Some(cache_path) = get_cache_path_from_prof_path(prof_path) {
if cache_path.exists() {
let start = Instant::now();
@@ -284,15 +283,8 @@ pub fn remove_disk_cache(prof_path: &nsA
let elapsed = start.elapsed();
let elapsed_ms = (elapsed.as_secs() * 1_000) + (elapsed.subsec_nanos() / 1_000_000) as u64;
info!("remove_disk_cache: {} ms", elapsed_ms);
}
}
Ok(())
}
-
-#[cfg(not(target_os="windows"))]
-pub fn remove_disk_cache(_prof_path: &nsAString) -> Result<(), Error> {
- error!("Shader disk cache is not supported");
- return Err(Error::new(ErrorKind::Other, "Not supported"))
-}
-
--- a/image/CopyOnWrite.h
+++ b/image/CopyOnWrite.h
@@ -25,21 +25,46 @@ namespace image {
namespace detail {
template <typename T>
class CopyOnWriteValue final
{
public:
NS_INLINE_DECL_REFCOUNTING(CopyOnWriteValue)
- explicit CopyOnWriteValue(T* aValue) : mValue(aValue) { }
- explicit CopyOnWriteValue(already_AddRefed<T>& aValue) : mValue(aValue) { }
- explicit CopyOnWriteValue(already_AddRefed<T>&& aValue) : mValue(aValue) { }
- explicit CopyOnWriteValue(const RefPtr<T>& aValue) : mValue(aValue) { }
- explicit CopyOnWriteValue(RefPtr<T>&& aValue) : mValue(aValue) { }
+ explicit CopyOnWriteValue(T* aValue)
+ : mValue(aValue)
+ , mReaders(0)
+ , mWriter(false)
+ {
+ }
+ explicit CopyOnWriteValue(already_AddRefed<T>& aValue)
+ : mValue(aValue)
+ , mReaders(0)
+ , mWriter(false)
+ {
+ }
+ explicit CopyOnWriteValue(already_AddRefed<T>&& aValue)
+ : mValue(aValue)
+ , mReaders(0)
+ , mWriter(false)
+ {
+ }
+ explicit CopyOnWriteValue(const RefPtr<T>& aValue)
+ : mValue(aValue)
+ , mReaders(0)
+ , mWriter(false)
+ {
+ }
+ explicit CopyOnWriteValue(RefPtr<T>&& aValue)
+ : mValue(aValue)
+ , mReaders(0)
+ , mWriter(false)
+ {
+ }
T* get() { return mValue.get(); }
const T* get() const { return mValue.get(); }
bool HasReaders() const { return mReaders > 0; }
bool HasWriter() const { return mWriter; }
bool HasUsers() const { return HasReaders() || HasWriter(); }
--- a/image/Downscaler.cpp
+++ b/image/Downscaler.cpp
@@ -19,16 +19,20 @@ namespace mozilla {
using gfx::IntRect;
namespace image {
Downscaler::Downscaler(const nsIntSize& aTargetSize)
: mTargetSize(aTargetSize)
, mOutputBuffer(nullptr)
, mWindowCapacity(0)
+ , mLinesInBuffer(0)
+ , mPrevInvalidatedLine(0)
+ , mCurrentOutLine(0)
+ , mCurrentInLine(0)
, mHasAlpha(true)
, mFlipVertically(false)
{
MOZ_ASSERT(mTargetSize.width > 0 && mTargetSize.height > 0,
"Invalid target size");
}
Downscaler::~Downscaler()
--- a/image/RasterImage.cpp
+++ b/image/RasterImage.cpp
@@ -69,16 +69,17 @@ NS_IMPL_ISUPPORTS(RasterImage, imgIConta
imgIContainerDebug)
#endif
//******************************************************************************
RasterImage::RasterImage(nsIURI* aURI /* = nullptr */) :
ImageResource(aURI), // invoke superclass's constructor
mSize(0,0),
mLockCount(0),
+ mDecoderType(DecoderType::UNKNOWN),
mDecodeCount(0),
#ifdef DEBUG
mFramesNotified(0),
#endif
mSourceBuffer(MakeNotNull<SourceBuffer*>()),
mHasSize(false),
mTransient(false),
mSyncLoad(false),
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -370,16 +370,17 @@ NS_IMPL_ISUPPORTS(VectorImage,
//------------------------------------------------------------------------------
// Constructor / Destructor
VectorImage::VectorImage(nsIURI* aURI /* = nullptr */) :
ImageResource(aURI), // invoke superclass's constructor
mLockCount(0),
mIsInitialized(false),
+ mDiscardable(false),
mIsFullyLoaded(false),
mIsDrawing(false),
mHaveAnimations(false),
mHasPendingInvalidation(false)
{ }
VectorImage::~VectorImage()
{
--- a/image/decoders/nsGIFDecoder2.cpp
+++ b/image/decoders/nsGIFDecoder2.cpp
@@ -81,16 +81,17 @@ static const uint8_t PACKED_FIELDS_TABLE
nsGIFDecoder2::nsGIFDecoder2(RasterImage* aImage)
: Decoder(aImage)
, mLexer(Transition::To(State::GIF_HEADER, GIF_HEADER_LEN),
Transition::TerminateSuccess())
, mOldColor(0)
, mCurrentFrameIndex(-1)
, mColorTablePos(0)
+ , mColorMask('\0')
, mGIFOpen(false)
, mSawTransparency(false)
{
// Clear out the structure, excluding the arrays.
memset(&mGIFStruct, 0, sizeof(mGIFStruct));
}
nsGIFDecoder2::~nsGIFDecoder2()
--- a/image/decoders/nsJPEGDecoder.cpp
+++ b/image/decoders/nsJPEGDecoder.cpp
@@ -69,23 +69,38 @@ METHODDEF(void) skip_input_data (j_decom
METHODDEF(void) term_source (j_decompress_ptr jd);
METHODDEF(void) my_error_exit (j_common_ptr cinfo);
// Normal JFIF markers can't have more bytes than this.
#define MAX_JPEG_MARKER_LENGTH (((uint32_t)1 << 16) - 1)
nsJPEGDecoder::nsJPEGDecoder(RasterImage* aImage,
Decoder::DecodeStyle aDecodeStyle)
- : Decoder(aImage)
- , mLexer(Transition::ToUnbuffered(State::FINISHED_JPEG_DATA,
- State::JPEG_DATA,
- SIZE_MAX),
- Transition::TerminateSuccess())
- , mDecodeStyle(aDecodeStyle)
+ : Decoder(aImage)
+ , mLexer(Transition::ToUnbuffered(State::FINISHED_JPEG_DATA,
+ State::JPEG_DATA,
+ SIZE_MAX),
+ Transition::TerminateSuccess())
+ , mProfile(nullptr)
+ , mProfileLength(0)
+ , mDecodeStyle(aDecodeStyle)
{
+ this->mErr.pub.error_exit = nullptr;
+ this->mErr.pub.emit_message = nullptr;
+ this->mErr.pub.output_message = nullptr;
+ this->mErr.pub.format_message = nullptr;
+ this->mErr.pub.reset_error_mgr = nullptr;
+ this->mErr.pub.msg_code = 0;
+ this->mErr.pub.trace_level = 0;
+ this->mErr.pub.num_warnings = 0;
+ this->mErr.pub.jpeg_message_table = nullptr;
+ this->mErr.pub.last_jpeg_message = 0;
+ this->mErr.pub.addon_message_table = nullptr;
+ this->mErr.pub.first_addon_message = 0;
+ this->mErr.pub.last_addon_message = 0;
mState = JPEG_HEADER;
mReading = true;
mImageData = nullptr;
mBytesToSkip = 0;
memset(&mInfo, 0, sizeof(jpeg_decompress_struct));
memset(&mSourceMgr, 0, sizeof(mSourceMgr));
mInfo.client_data = (void*)this;
--- a/image/encoders/bmp/nsBMPEncoder.cpp
+++ b/image/encoders/bmp/nsBMPEncoder.cpp
@@ -14,25 +14,30 @@
using namespace mozilla;
using namespace mozilla::image;
using namespace mozilla::image::bmp;
NS_IMPL_ISUPPORTS(nsBMPEncoder, imgIEncoder, nsIInputStream,
nsIAsyncInputStream)
-nsBMPEncoder::nsBMPEncoder() : mImageBufferStart(nullptr),
- mImageBufferCurr(0),
- mImageBufferSize(0),
- mImageBufferReadPoint(0),
- mFinished(false),
- mCallback(nullptr),
- mCallbackTarget(nullptr),
- mNotifyThreshold(0)
+nsBMPEncoder::nsBMPEncoder()
+ : mBMPInfoHeader{}
+ , mImageBufferStart(nullptr)
+ , mImageBufferCurr(0)
+ , mImageBufferSize(0)
+ , mImageBufferReadPoint(0)
+ , mFinished(false)
+ , mCallback(nullptr)
+ , mCallbackTarget(nullptr)
+ , mNotifyThreshold(0)
{
+ this->mBMPFileHeader.filesize = 0;
+ this->mBMPFileHeader.reserved = 0;
+ this->mBMPFileHeader.dataoffset = 0;
}
nsBMPEncoder::~nsBMPEncoder()
{
if (mImageBufferStart) {
free(mImageBufferStart);
mImageBufferStart = nullptr;
mImageBufferCurr = nullptr;
--- a/image/encoders/ico/nsICOEncoder.cpp
+++ b/image/encoders/ico/nsICOEncoder.cpp
@@ -12,23 +12,26 @@
#include "nsTArray.h"
using namespace mozilla;
using namespace mozilla::image;
NS_IMPL_ISUPPORTS(nsICOEncoder, imgIEncoder, nsIInputStream,
nsIAsyncInputStream)
-nsICOEncoder::nsICOEncoder() : mImageBufferStart(nullptr),
- mImageBufferCurr(0),
- mImageBufferSize(0),
- mImageBufferReadPoint(0),
- mFinished(false),
- mUsePNG(true),
- mNotifyThreshold(0)
+nsICOEncoder::nsICOEncoder()
+ : mICOFileHeader{}
+ , mICODirEntry{}
+ , mImageBufferStart(nullptr)
+ , mImageBufferCurr(0)
+ , mImageBufferSize(0)
+ , mImageBufferReadPoint(0)
+ , mFinished(false)
+ , mUsePNG(true)
+ , mNotifyThreshold(0)
{
}
nsICOEncoder::~nsICOEncoder()
{
if (mImageBufferStart) {
free(mImageBufferStart);
mImageBufferStart = nullptr;
--- a/image/imgFrame.cpp
+++ b/image/imgFrame.cpp
@@ -204,16 +204,17 @@ imgFrame::imgFrame()
, mDecoded(0, 0, 0, 0)
, mLockCount(0)
, mAborted(false)
, mFinished(false)
, mOptimizable(false)
, mTimeout(FrameTimeout::FromRawMilliseconds(100))
, mDisposalMethod(DisposalMethod::NOT_SPECIFIED)
, mBlendMethod(BlendMethod::OVER)
+ , mFormat(SurfaceFormat::UNKNOWN)
, mPalettedImageData(nullptr)
, mPaletteDepth(0)
, mNonPremult(false)
, mCompositingFailed(false)
{
}
imgFrame::~imgFrame()
--- a/image/imgFrame.h
+++ b/image/imgFrame.h
@@ -230,17 +230,20 @@ private: // methods
{
return mPaletteDepth ? (size_t(1) << mPaletteDepth) * sizeof(uint32_t)
: 0;
}
struct SurfaceWithFormat {
RefPtr<gfxDrawable> mDrawable;
SurfaceFormat mFormat;
- SurfaceWithFormat() { }
+ SurfaceWithFormat()
+ : mFormat(SurfaceFormat::UNKNOWN)
+ {
+ }
SurfaceWithFormat(gfxDrawable* aDrawable, SurfaceFormat aFormat)
: mDrawable(aDrawable), mFormat(aFormat)
{ }
bool IsValid() { return !!mDrawable; }
};
SurfaceWithFormat SurfaceForDrawing(bool aDoPartialDecode,
bool aDoTile,
--- a/ipc/glue/ProtocolUtils.cpp
+++ b/ipc/glue/ProtocolUtils.cpp
@@ -666,22 +666,25 @@ IProtocol::ManagedState::ReplaceEventTar
}
already_AddRefed<nsIEventTarget>
IProtocol::ManagedState::GetActorEventTarget(IProtocol* aActor)
{
return mProtocol->Manager()->GetActorEventTarget(aActor);
}
-IToplevelProtocol::IToplevelProtocol(const char* aName, ProtocolId aProtoId, Side aSide)
- : IProtocol(aSide, MakeUnique<ToplevelState>(aName, this, aSide)),
- mMonitor("mozilla.ipc.IToplevelProtocol.mMonitor"),
- mProtocolId(aProtoId),
- mOtherPid(mozilla::ipc::kInvalidProcessId),
- mOtherPidState(ProcessIdState::eUnstarted)
+IToplevelProtocol::IToplevelProtocol(const char* aName,
+ ProtocolId aProtoId,
+ Side aSide)
+ : IProtocol(aSide, MakeUnique<ToplevelState>(aName, this, aSide))
+ , mMonitor("mozilla.ipc.IToplevelProtocol.mMonitor")
+ , mProtocolId(aProtoId)
+ , mOtherPid(mozilla::ipc::kInvalidProcessId)
+ , mOtherPidState(ProcessIdState::eUnstarted)
+ , mIsMainThreadProtocol(false)
{
}
IToplevelProtocol::~IToplevelProtocol()
{
if (mTrans) {
RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(mTrans.release());
XRE_GetIOMessageLoop()->PostTask(task.forget());
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -800,17 +800,21 @@ ReEntrantDeleteStateTransition(bool aIsD
template<class PFooSide>
class Endpoint
{
public:
typedef base::ProcessId ProcessId;
Endpoint()
: mValid(false)
- {}
+ , mMode(static_cast<mozilla::ipc::Transport::Mode>(0))
+ , mMyPid(0)
+ , mOtherPid(0)
+ {
+ }
Endpoint(const PrivateIPDLInterface&,
mozilla::ipc::Transport::Mode aMode,
TransportDescriptor aTransport,
ProcessId aMyPid,
ProcessId aOtherPid)
: mValid(true)
, mMode(aMode)
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -127,26 +127,34 @@ class ObjectOpResult
uintptr_t code_;
public:
enum SpecialCodes : uintptr_t {
OkCode = 0,
Uninitialized = uintptr_t(-1)
};
+ static const uintptr_t SoftFailBit = uintptr_t(1) << (sizeof(uintptr_t) * 8 - 1);
+
ObjectOpResult() : code_(Uninitialized) {}
+ /* Return true if succeed() or failSoft() was called. */
+ bool ok() const {
+ MOZ_ASSERT(code_ != Uninitialized);
+ return code_ == OkCode || (code_ & SoftFailBit);
+ }
+
+ explicit operator bool() const { return ok(); }
+
/* Return true if succeed() was called. */
- bool ok() const {
+ bool reallyOk() const {
MOZ_ASSERT(code_ != Uninitialized);
return code_ == OkCode;
}
- explicit operator bool() const { return ok(); }
-
/* Set this ObjectOpResult to true and return true. */
bool succeed() {
code_ = OkCode;
return true;
}
/*
* Set this ObjectOpResult to false with an error code.
@@ -156,20 +164,36 @@ class ObjectOpResult
* if (funny condition)
* return result.fail(JSMSG_CANT_DO_THE_THINGS);
*
* The true return value indicates that no exception is pending, and it
* would be OK to ignore the failure and continue.
*/
bool fail(uint32_t msg) {
MOZ_ASSERT(msg != OkCode);
+ MOZ_ASSERT((msg & SoftFailBit) == 0);
code_ = msg;
return true;
}
+ /*
+ * DEPRECATED: This is a non-standard compatibility hack.
+ *
+ * Set this ObjectOpResult to true, but remembers an error code.
+ * This is used for situations where we really want to fail,
+ * but can't for legacy reasons.
+ *
+ * Always returns true, as a convenience.
+ */
+ bool failSoft(uint32_t msg) {
+ // The msg code is currently never extracted again.
+ code_ = msg | SoftFailBit;
+ return true;
+ }
+
JS_PUBLIC_API(bool) failCantRedefineProp();
JS_PUBLIC_API(bool) failReadOnly();
JS_PUBLIC_API(bool) failGetterOnly();
JS_PUBLIC_API(bool) failCantDelete();
JS_PUBLIC_API(bool) failCantSetInterposed();
JS_PUBLIC_API(bool) failCantDefineWindowElement();
JS_PUBLIC_API(bool) failCantDeleteWindowElement();
--- a/js/public/Realm.h
+++ b/js/public/Realm.h
@@ -1,20 +1,14 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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/. */
-/*
- * Ways to get various per-Realm objects. All the getters declared in this
- * header operate on the Realm corresponding to the current compartment on the
- * JSContext.
- */
-
#ifndef js_Realm_h
#define js_Realm_h
#include "jspubtd.h"
#include "js/GCPolicyAPI.h"
#include "js/TypeDecls.h" // forward-declaration of JS::Realm
namespace js {
@@ -109,16 +103,27 @@ typedef void
extern JS_PUBLIC_API(void)
SetRealmNameCallback(JSContext* cx, RealmNameCallback callback);
// Get the global object for the given realm. This only returns nullptr during
// GC, between collecting the global object and destroying the Realm.
extern JS_PUBLIC_API(JSObject*)
GetRealmGlobalOrNull(Handle<Realm*> realm);
+// Initialize standard JS class constructors, prototypes, and any top-level
+// functions and constants associated with the standard classes (e.g. isNaN
+// for Number).
+extern JS_PUBLIC_API(bool)
+InitRealmStandardClasses(JSContext* cx);
+
+/*
+ * Ways to get various per-Realm objects. All the getters declared below operate
+ * on the JSContext's current Realm.
+ */
+
extern JS_PUBLIC_API(JSObject*)
GetRealmObjectPrototype(JSContext* cx);
extern JS_PUBLIC_API(JSObject*)
GetRealmFunctionPrototype(JSContext* cx);
extern JS_PUBLIC_API(JSObject*)
GetRealmArrayPrototype(JSContext* cx);
--- a/js/rust/build.rs
+++ b/js/rust/build.rs
@@ -281,23 +281,19 @@ const WHITELIST_FUNCTIONS: &'static [&'s
"JS_DeletePropertyById",
"js::detail::IsWindowSlow",
"JS::Evaluate",
"JS_ForwardGetPropertyTo",
"JS_ForwardSetPropertyTo",
"JS::GCTraceKindToAscii",
"js::GetArrayBufferLengthAndData",
"js::GetArrayBufferViewLengthAndData",
- "JS_GetErrorPrototype",
"js::GetFunctionNativeReserved",
- "JS_GetFunctionPrototype",
"js::GetGlobalForObjectCrossCompartment",
- "JS_GetIteratorPrototype",
"js::GetObjectProto",
- "JS_GetObjectPrototype",
"JS_GetObjectRuntime",
"JS_GetOwnPropertyDescriptorById",
"JS::GetPromiseResult",
"JS::GetPromiseState",
"JS_GetPropertyDescriptorById",
"js::GetPropertyKeys",
"JS_GetPrototype",
"JS_GetRuntime",
@@ -344,26 +340,30 @@ const WHITELIST_FUNCTIONS: &'static [&'s
"JS_GetLatin1StringCharsAndLength",
"JS_GetParentRuntime",
"JS_GetPendingException",
"JS_GetProperty",
"JS_GetPropertyById",
"js::GetPropertyKeys",
"JS_GetPrototype",
"JS_GetReservedSlot",
+ "JS::GetRealmErrorPrototype",
+ "JS::GetRealmFunctionPrototype",
+ "JS::GetRealmIteratorPrototype",
+ "JS::GetRealmObjectPrototype",
"JS::GetScriptedCallerGlobal",
"JS_GetTwoByteStringCharsAndLength",
"JS_GetUint16ArrayData",
"JS_GetUint32ArrayData",
"JS_GetUint8ArrayData",
"JS_GetUint8ClampedArrayData",
"JS::GetWellKnownSymbol",
"JS_GlobalObjectTraceHook",
"JS::HideScriptedCaller",
- "JS_InitStandardClasses",
+ "JS::InitRealmStandardClasses",
"JS_IsArrayObject",
"JS_IsExceptionPending",
"JS_IsGlobalObject",
"JS::IsCallable",
"JS::LeaveRealm",
"JS_LinkConstructorAndPrototype",
"JS_MayResolveStandardClass",
"JS_NewArrayBuffer",
--- a/js/rust/tests/rooting.rs
+++ b/js/rust/tests/rooting.rs
@@ -25,17 +25,17 @@ fn rooting() {
let c_option = JS::RealmOptions::default();
rooted!(in(cx) let global = JS_NewGlobalObject(cx,
&SIMPLE_GLOBAL_CLASS,
ptr::null_mut(),
h_option,
&c_option));
let _ac = js::ac::AutoCompartment::with_obj(cx, global.get());
- rooted!(in(cx) let prototype_proto = JS_GetObjectPrototype(cx, global.handle()));
+ rooted!(in(cx) let prototype_proto = JS::GetRealmObjectPrototype(cx));
rooted!(in(cx) let proto = JS_NewObjectWithUniqueType(cx,
&CLASS as *const _,
prototype_proto.handle()));
define_methods(cx, proto.handle(), &METHODS[..]).unwrap();
}
}
unsafe extern "C" fn generic_method(_: *mut JSContext, _: u32, _: *mut JS::Value) -> bool {
--- a/js/rust/tests/vec_conversion.rs
+++ b/js/rust/tests/vec_conversion.rs
@@ -6,17 +6,17 @@
extern crate js;
use js::ac::AutoCompartment;
use js::conversions::ConversionBehavior;
use js::conversions::ConversionResult;
use js::conversions::FromJSValConvertible;
use js::conversions::ToJSValConvertible;
use js::jsapi::root::JS::RealmOptions;
-use js::jsapi::root::JS_InitStandardClasses;
+use js::jsapi::root::JS::InitRealmStandardClasses;
use js::jsapi::root::JS_NewGlobalObject;
use js::jsapi::root::JS::OnNewGlobalHookOption;
use js::jsval::UndefinedValue;
use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS};
use std::ptr;
fn assert_is_array(cx: *mut js::jsapi::root::JSContext,
@@ -38,17 +38,17 @@ fn vec_conversion() {
unsafe {
let global = JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS,
ptr::null_mut(), h_option, &c_option);
rooted!(in(cx) let global_root = global);
let global = global_root.handle();
let _ac = AutoCompartment::with_obj(cx, global.get());
- assert!(JS_InitStandardClasses(cx, global));
+ assert!(InitRealmStandardClasses(cx));
rooted!(in(cx) let mut rval = UndefinedValue());
let orig_vec: Vec<f32> = vec![1.0, 2.9, 3.0];
orig_vec.to_jsval(cx, rval.handle_mut());
assert_is_array(cx, rval.handle());
let converted = Vec::<f32>::from_jsval(cx, rval.handle(), ()).unwrap();
assert_eq!(&orig_vec, converted.get_success_value().unwrap());
--- a/js/src/builtin/Array.cpp
+++ b/js/src/builtin/Array.cpp
@@ -3548,20 +3548,19 @@ static const JSFunctionSpec array_method
JS_SELF_HOSTED_SYM_FN(iterator, "ArrayValues", 0,0),
JS_SELF_HOSTED_FN("entries", "ArrayEntries", 0,0),
JS_SELF_HOSTED_FN("keys", "ArrayKeys", 0,0),
JS_SELF_HOSTED_FN("values", "ArrayValues", 0,0),
/* ES7 additions */
JS_SELF_HOSTED_FN("includes", "ArrayIncludes", 2,0),
-#ifdef NIGHTLY_BUILD
+ /* Future additions */
JS_SELF_HOSTED_FN("flatMap", "ArrayFlatMap", 1,0),
JS_SELF_HOSTED_FN("flat", "ArrayFlat", 0,0),
-#endif
JS_FS_END
};
static const JSFunctionSpec array_static_methods[] = {
JS_INLINABLE_FN("isArray", array_isArray, 1,0, ArrayIsArray),
JS_SELF_HOSTED_FN("concat", "ArrayStaticConcat", 2,0),
JS_SELF_HOSTED_FN("lastIndexOf", "ArrayStaticLastIndexOf", 2,0),
--- a/js/src/builtin/Reflect.cpp
+++ b/js/src/builtin/Reflect.cpp
@@ -37,17 +37,17 @@ Reflect_deleteProperty(JSContext* cx, un
RootedId key(cx);
if (!ToPropertyKey(cx, propertyKey, &key))
return false;
// Step 4.
ObjectOpResult result;
if (!DeleteProperty(cx, target, key, result))
return false;
- args.rval().setBoolean(bool(result));
+ args.rval().setBoolean(result.reallyOk());
return true;
}
/* ES6 26.1.8 Reflect.getPrototypeOf(target) */
bool
js::Reflect_getPrototypeOf(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
@@ -113,17 +113,17 @@ Reflect_preventExtensions(JSContext* cx,
args.get(0)));
if (!target)
return false;
// Step 2.
ObjectOpResult result;
if (!PreventExtensions(cx, target, result))
return false;
- args.rval().setBoolean(bool(result));
+ args.rval().setBoolean(result.reallyOk());
return true;
}
/* ES6 26.1.13 Reflect.set(target, propertyKey, V [, receiver]) */
static bool
Reflect_set(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
@@ -142,17 +142,17 @@ Reflect_set(JSContext* cx, unsigned argc
// Step 4.
RootedValue receiver(cx, args.length() > 3 ? args[3] : args.get(0));
// Step 5.
ObjectOpResult result;
RootedValue value(cx, args.get(2));
if (!SetProperty(cx, target, key, value, receiver, result))
return false;
- args.rval().setBoolean(bool(result));
+ args.rval().setBoolean(result.reallyOk());
return true;
}
/*
* ES6 26.1.3 Reflect.setPrototypeOf(target, proto)
*
* The specification is not quite similar enough to Object.setPrototypeOf to
* share code.
@@ -175,17 +175,17 @@ Reflect_setPrototypeOf(JSContext* cx, un
return false;
}
RootedObject proto(cx, args.get(1).toObjectOrNull());
// Step 4.
ObjectOpResult result;
if (!SetPrototype(cx, obj, proto, result))
return false;
- args.rval().setBoolean(bool(result));
+ args.rval().setBoolean(result.reallyOk());
return true;
}
static const JSFunctionSpec methods[] = {
JS_SELF_HOSTED_FN("apply", "Reflect_apply", 3, 0),
JS_SELF_HOSTED_FN("construct", "Reflect_construct", 2, 0),
JS_SELF_HOSTED_FN("defineProperty", "Reflect_defineProperty", 3, 0),
JS_FN("deleteProperty", Reflect_deleteProperty, 2, 0),
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -18,16 +18,17 @@
*/
#include "frontend/Parser.h"
#include "mozilla/Range.h"
#include "mozilla/Sprintf.h"
#include "mozilla/TypeTraits.h"
+#include <memory>
#include <new>
#include "jsapi.h"
#include "jstypes.h"
#include "builtin/ModuleObject.h"
#include "builtin/SelfHostingDefines.h"
#include "frontend/BytecodeCompiler.h"
@@ -1761,33 +1762,31 @@ Parser<FullParseHandler, CharT>::checkSt
return true;
}
template <typename Scope>
typename Scope::Data*
NewEmptyBindingData(JSContext* cx, LifoAlloc& alloc, uint32_t numBindings)
{
using Data = typename Scope::Data;
- size_t allocSize = Scope::sizeOfData(numBindings);
+ size_t allocSize = SizeOfData<typename Scope::Data>(numBindings);
auto* bindings = alloc.allocInSize<Data>(allocSize, numBindings);
if (!bindings)
ReportOutOfMemory(cx);
return bindings;
}
/**
* Copy-construct |BindingName|s from |bindings| into |cursor|, then return
* the location one past the newly-constructed |BindingName|s.
*/
static MOZ_MUST_USE BindingName*
FreshlyInitializeBindings(BindingName* cursor, const Vector<BindingName>& bindings)
{
- for (const BindingName& binding : bindings)
- new (cursor++) BindingName(binding);
- return cursor;
+ return std::uninitialized_copy(bindings.begin(), bindings.end(), cursor);
}
Maybe<GlobalScope::Data*>
NewGlobalScopeData(JSContext* context, ParseContext::Scope& scope, LifoAlloc& alloc, ParseContext* pc)
{
Vector<BindingName> vars(context);
Vector<BindingName> lets(context);
Vector<BindingName> consts(context);
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -4,17 +4,19 @@
* 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/. */
// JS lexical scanner.
#include "frontend/TokenStream.h"
#include "mozilla/ArrayUtils.h"
+#include "mozilla/Attributes.h"
#include "mozilla/IntegerTypeTraits.h"
+#include "mozilla/Likely.h"
#include "mozilla/MemoryChecking.h"
#include "mozilla/PodOperations.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/TextUtils.h"
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
@@ -32,16 +34,17 @@
#include "util/StringBuffer.h"
#include "util/Unicode.h"
#include "vm/HelperThreads.h"
#include "vm/JSAtom.h"
#include "vm/JSContext.h"
#include "vm/Realm.h"
using mozilla::ArrayLength;
+using mozilla::AssertedCast;
using mozilla::IsAscii;
using mozilla::IsAsciiAlpha;
using mozilla::IsAsciiDigit;
using mozilla::MakeScopeExit;
using mozilla::PodCopy;
struct ReservedWordInfo
{
@@ -493,32 +496,32 @@ TokenStreamAnyChars::updateFlagsForEOL()
// unit, normalizing EOL sequences to '\n', also updating line/column info as
// needed.
template<class AnyCharsAccess>
bool
TokenStreamChars<char16_t, AnyCharsAccess>::getCodePoint(int32_t* cp)
{
TokenStreamAnyChars& anyChars = anyCharsAccess();
- if (MOZ_UNLIKELY(!sourceUnits.hasRawChars())) {
+ if (MOZ_UNLIKELY(sourceUnits.atEnd())) {
anyChars.flags.isEOF = true;
*cp = EOF;
return true;
}
int32_t c = sourceUnits.getCodeUnit();
do {
// Normalize the char16_t if it was a newline.
if (MOZ_UNLIKELY(c == '\n'))
break;
if (MOZ_UNLIKELY(c == '\r')) {
// If it's a \r\n sequence: treat as a single EOL, skip over the \n.
- if (MOZ_LIKELY(sourceUnits.hasRawChars()))
+ if (MOZ_LIKELY(!sourceUnits.atEnd()))
sourceUnits.matchCodeUnit('\n');
break;
}
if (MOZ_UNLIKELY(c == unicode::LINE_SEPARATOR || c == unicode::PARA_SEPARATOR))
break;
@@ -540,18 +543,23 @@ TokenStreamChars<char16_t, AnyCharsAcces
MOZ_ASSERT(!isAsciiCodePoint(lead),
"ASCII code unit/point must be handled separately");
MOZ_ASSERT(lead == sourceUnits.previousCodeUnit(),
"getNonAsciiCodePoint called incorrectly");
// The code point is usually |lead|: overwrite later if needed.
*codePoint = lead;
- // Dispense with single-unit code points ("code points", when a lone
- // trailing surrogate is encountered).
+ // ECMAScript specifically requires that unpaired UTF-16 surrogates be
+ // treated as the corresponding code point and not as an error. See
+ // <https://tc39.github.io/ecma262/#sec-ecmascript-language-types-string-type>.
+ // Thus this function does not consider any sequence of 16-bit numbers to
+ // be intrinsically in error.
+
+ // Dispense with single-unit code points and lone trailing surrogates.
if (MOZ_LIKELY(!unicode::IsLeadSurrogate(lead))) {
if (MOZ_UNLIKELY(lead == unicode::LINE_SEPARATOR ||
lead == unicode::PARA_SEPARATOR))
{
if (!updateLineInfoForEOL()) {
#ifdef DEBUG
*codePoint = EOF; // sentinel value to hopefully cause errors
#endif
@@ -562,51 +570,30 @@ TokenStreamChars<char16_t, AnyCharsAcces
*codePoint = '\n';
} else {
MOZ_ASSERT(!SourceUnits::isRawEOLChar(*codePoint));
}
return true;
}
- // If there are no more units, or the next unit isn't a trailing surrogate,
- // it's also a "code point".
- if (MOZ_UNLIKELY(!sourceUnits.hasRawChars() ||
+ // Also handle a lead surrogate not paired with a trailing surrogate.
+ if (MOZ_UNLIKELY(sourceUnits.atEnd() ||
!unicode::IsTrailSurrogate(sourceUnits.peekCodeUnit())))
{
MOZ_ASSERT(!SourceUnits::isRawEOLChar(*codePoint));
return true;
}
// Otherwise we have a multi-unit code point.
*codePoint = unicode::UTF16Decode(lead, sourceUnits.getCodeUnit());
MOZ_ASSERT(!SourceUnits::isRawEOLChar(*codePoint));
return true;
}
-// This gets the next code unit -- the next numeric sub-unit of source text,
-// possibly smaller than a full code point. It is simple and stupid, and it
-// doesn't understand EOL, update line counters, or anything like that. If you
-// use it to consume an EOL sequence, line counters *will not* be correct for
-// subsequent code.
-//
-// Only use this if (a) the resulting code unit is guaranteed to be ungotten
-// (by ungetCodeUnit()) if it's an EOL, and (b) the line-related state (lineno,
-// linebase) is not used before it's ungotten.
-template<typename CharT, class AnyCharsAccess>
-int32_t
-GeneralTokenStreamChars<CharT, AnyCharsAccess>::getCodeUnit()
-{
- if (MOZ_LIKELY(sourceUnits.hasRawChars()))
- return sourceUnits.getCodeUnit();
-
- anyCharsAccess().flags.isEOF = true;
- return EOF;
-}
-
template<typename CharT, class AnyCharsAccess>
void
GeneralTokenStreamChars<CharT, AnyCharsAccess>::ungetChar(int32_t c)
{
if (c == EOF)
return;
sourceUnits.ungetCodeUnit();
@@ -619,26 +606,16 @@ GeneralTokenStreamChars<CharT, AnyCharsA
sourceUnits.ungetOptionalCRBeforeLF();
anyCharsAccess().undoInternalUpdateLineInfoForEOL();
} else {
MOZ_ASSERT(sourceUnits.peekCodeUnit() == c);
}
}
-template<typename CharT>
-void
-TokenStreamCharsBase<CharT>::ungetCodeUnit(int32_t c)
-{
- if (c == EOF)
- return;
-
- sourceUnits.ungetCodeUnit();
-}
-
template<class AnyCharsAccess>
void
TokenStreamChars<char16_t, AnyCharsAccess>::ungetCodePointIgnoreEOL(uint32_t codePoint)
{
MOZ_ASSERT(!sourceUnits.atStart());
unsigned numUnits = 0;
char16_t units[2];
@@ -660,39 +637,16 @@ TokenStreamChars<char16_t, AnyCharsAcces
MOZ_ASSERT(SourceUnits::isRawEOLChar(last));
if (last == '\n')
sourceUnits.ungetOptionalCRBeforeLF();
anyCharsAccess().undoInternalUpdateLineInfoForEOL();
}
-// Return true iff |n| raw characters can be read from this without reading past
-// EOF, and copy those characters into |cp| if so. The characters are not
-// consumed: use skipChars(n) to do so after checking that the consumed
-// characters had appropriate values.
-template<typename CharT, class AnyCharsAccess>
-bool
-TokenStreamSpecific<CharT, AnyCharsAccess>::peekChars(int n, CharT* cp)
-{
- int i;
- for (i = 0; i < n; i++) {
- int32_t c = getCodeUnit();
- if (c == EOF)
- break;
-
- cp[i] = char16_t(c);
- }
-
- for (int j = i - 1; j >= 0; j--)
- ungetCodeUnit(cp[j]);
-
- return i == n;
-}
-
template<typename CharT>
size_t
SourceUnits<CharT>::findEOLMax(size_t start, size_t max)
{
const CharT* p = codeUnitPtrAt(start);
size_t n = 0;
while (true) {
@@ -1065,107 +1019,120 @@ TokenStreamSpecific<CharT, AnyCharsAcces
}
// We have encountered a '\': check for a Unicode escape sequence after it.
// Return the length of the escape sequence and the character code point (by
// value) if we found a Unicode escape sequence. Otherwise, return 0. In both
// cases, do not advance along the buffer.
template<typename CharT, class AnyCharsAccess>
uint32_t
-TokenStreamSpecific<CharT, AnyCharsAccess>::peekUnicodeEscape(uint32_t* codePoint)
+GeneralTokenStreamChars<CharT, AnyCharsAccess>::matchUnicodeEscape(uint32_t* codePoint)
{
- int32_t c = getCodeUnit();
- if (c != 'u') {
- ungetCodeUnit(c);
+ MOZ_ASSERT(sourceUnits.previousCodeUnit() == '\\');
+
+ int32_t unit = getCodeUnit();
+ if (unit != 'u') {
+ // NOTE: |unit| may be EOF here.
+ ungetCodeUnit(unit);
+ MOZ_ASSERT(sourceUnits.previousCodeUnit() == '\\');
return 0;
}
CharT cp[3];
- uint32_t length;
- c = getCodeUnit();
- if (JS7_ISHEX(c) && peekChars(3, cp) &&
+ unit = getCodeUnit();
+ if (JS7_ISHEX(unit) &&
+ sourceUnits.peekCodeUnits(3, cp) &&
JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1]) && JS7_ISHEX(cp[2]))
{
- *codePoint = (JS7_UNHEX(c) << 12) |
+ *codePoint = (JS7_UNHEX(unit) << 12) |
(JS7_UNHEX(cp[0]) << 8) |
(JS7_UNHEX(cp[1]) << 4) |
JS7_UNHEX(cp[2]);
- length = 5;
- } else if (c == '{') {
- length = peekExtendedUnicodeEscape(codePoint);
- } else {
- length = 0;
+ sourceUnits.skipCodeUnits(3);
+ return 5;
}
- ungetCodeUnit(c);
+ if (unit == '{')
+ return matchExtendedUnicodeEscape(codePoint);
+
+ // NOTE: |unit| may be EOF here, so this ungets either one or two units.
+ ungetCodeUnit(unit);
ungetCodeUnit('u');
- return length;
+ MOZ_ASSERT(sourceUnits.previousCodeUnit() == '\\');
+ return 0;
}
template<typename CharT, class AnyCharsAccess>
uint32_t
-TokenStreamSpecific<CharT, AnyCharsAccess>::peekExtendedUnicodeEscape(uint32_t* codePoint)
+GeneralTokenStreamChars<CharT, AnyCharsAccess>::matchExtendedUnicodeEscape(uint32_t* codePoint)
{
- // The opening brace character was already read.
- int32_t c = getCodeUnit();
-
- // Skip leading zeros.
- uint32_t leadingZeros = 0;
- while (c == '0') {
- leadingZeros++;
- c = getCodeUnit();
+ MOZ_ASSERT(sourceUnits.previousCodeUnit() == '{');
+
+ int32_t unit = getCodeUnit();
+
+ // Skip leading zeroes.
+ uint32_t leadingZeroes = 0;
+ while (unit == '0') {
+ leadingZeroes++;
+ unit = getCodeUnit();
}
- CharT cp[6];
size_t i = 0;
uint32_t code = 0;
- while (JS7_ISHEX(c) && i < 6) {
- cp[i++] = c;
- code = code << 4 | JS7_UNHEX(c);
- c = getCodeUnit();
+ while (JS7_ISHEX(unit) && i < 6) {
+ code = (code << 4) | JS7_UNHEX(unit);
+ unit = getCodeUnit();
+ i++;
}
- uint32_t length;
- if (c == '}' && (leadingZeros > 0 || i > 0) && code <= unicode::NonBMPMax) {
+ uint32_t gotten =
+ 2 + // 'u{'
+ leadingZeroes +
+ i + // significant hexdigits
+ (unit != EOF); // subtract a get if it didn't contribute to length
+
+ if (unit == '}' && (leadingZeroes > 0 || i > 0) && code <= unicode::NonBMPMax) {
*codePoint = code;
- length = leadingZeros + i + 3;
- } else {
- length = 0;
+ return gotten;
}
- ungetCodeUnit(c);
- while (i--)
- ungetCodeUnit(cp[i]);
- while (leadingZeros--)
- ungetCodeUnit('0');
-
- return length;
+ sourceUnits.unskipCodeUnits(gotten);
+ MOZ_ASSERT(sourceUnits.previousCodeUnit() == '\\');
+ return 0;
}
template<typename CharT, class AnyCharsAccess>
uint32_t
-TokenStreamSpecific<CharT, AnyCharsAccess>::matchUnicodeEscapeIdStart(uint32_t* codePoint)
+GeneralTokenStreamChars<CharT, AnyCharsAccess>::matchUnicodeEscapeIdStart(uint32_t* codePoint)
{
- uint32_t length = peekUnicodeEscape(codePoint);
- if (length > 0 && unicode::IsIdentifierStart(*codePoint)) {
- skipChars(length);
- return length;
+ uint32_t length = matchUnicodeEscape(codePoint);
+ if (MOZ_LIKELY(length > 0)) {
+ if (MOZ_LIKELY(unicode::IsIdentifierStart(*codePoint)))
+ return length;
+
+ sourceUnits.unskipCodeUnits(length);
}
+
+ MOZ_ASSERT(sourceUnits.previousCodeUnit() == '\\');
return 0;
}
template<typename CharT, class AnyCharsAccess>
bool
-TokenStreamSpecific<CharT, AnyCharsAccess>::matchUnicodeEscapeIdent(uint32_t* codePoint)
+GeneralTokenStreamChars<CharT, AnyCharsAccess>::matchUnicodeEscapeIdent(uint32_t* codePoint)
{
- uint32_t length = peekUnicodeEscape(codePoint);
- if (length > 0 && unicode::IsIdentifierPart(*codePoint)) {
- skipChars(length);
- return true;
+ uint32_t length = matchUnicodeEscape(codePoint);
+ if (MOZ_LIKELY(length > 0)) {
+ if (MOZ_LIKELY(unicode::IsIdentifierPart(*codePoint)))
+ return true;
+
+ sourceUnits.unskipCodeUnits(length);
}
+
+ MOZ_ASSERT(sourceUnits.previousCodeUnit() == '\\');
return false;
}
// Helper function which returns true if the first length(q) characters in p are
// the same as the characters in q.
template<typename CharT>
static bool
CharsMatch(const CharT* p, const char* q)
@@ -1224,57 +1191,72 @@ TokenStreamSpecific<CharT, AnyCharsAcces
const char* errorMsgPragma,
UniquePtr<char16_t[], JS::FreePolicy>* destination)
{
MOZ_ASSERT(directiveLength <= 18);
char16_t peeked[18];
// If there aren't enough characters left, it can't be the desired
// directive.
- if (!peekChars(directiveLength, peeked))
+ if (!sourceUnits.peekCodeUnits(directiveLength, peeked))
return true;
// It's also not the desired directive if the characters don't match.
if (!CharsMatch(peeked, directive))
return true;
if (shouldWarnDeprecated) {
if (!warning(JSMSG_DEPRECATED_PRAGMA, errorMsgPragma))
return false;
}
- skipChars(directiveLength);
+ sourceUnits.skipCodeUnits(directiveLength);
tokenbuf.clear();
do {
- int32_t c;
- if (!peekChar(&c))
- return false;
-
- if (c == EOF || unicode::IsSpaceOrBOM2(c))
+ int32_t unit = peekCodeUnit();
+ if (unit == EOF)
break;
- consumeKnownChar(c);
-
- // Debugging directives can occur in both single- and multi-line
- // comments. If we're currently inside a multi-line comment, we also
- // need to recognize multi-line comment terminators.
- if (isMultiline && c == '*' && matchCodeUnit('/')) {
- ungetCodeUnit('/');
- ungetCodeUnit('*');
+ if (MOZ_LIKELY(isAsciiCodePoint(unit))) {
+ if (unicode::IsSpaceOrBOM2(unit))
+ break;
+
+ consumeKnownCodeUnit(unit);
+
+ // Debugging directives can occur in both single- and multi-line
+ // comments. If we're currently inside a multi-line comment, we
+ // also must recognize multi-line comment terminators.
+ if (isMultiline && unit == '*' && peekCodeUnit() == '/') {
+ ungetCodeUnit('*');
+ break;
+ }
+
+ if (!tokenbuf.append(unit))
+ return false;
+
+ continue;
+ }
+
+ int32_t codePoint;
+ if (!getCodePoint(&codePoint))
+ return false;
+
+ if (unicode::IsSpaceOrBOM2(codePoint)) {
+ ungetNonAsciiNormalizedCodePoint(codePoint);
break;
}
- if (!tokenbuf.append(c))
+ if (!appendCodePointToTokenbuf(codePoint))
return false;
} while (true);
if (tokenbuf.empty()) {
- // The directive's URL was missing, but this is not quite an
- // exception that we should stop and drop everything for.
+ // The directive's URL was missing, but comments can contain anything,
+ // so it isn't an error.
return true;
}
return copyTokenbufTo(anyCharsAccess().cx, destination);
}
template<typename CharT, class AnyCharsAccess>
bool
@@ -1368,68 +1350,69 @@ TokenStreamCharsBase<char16_t>::appendCo
return false;
if (numUnits == 1)
return true;
return tokenbuf.append(units[1]);
}
-template<class AnyCharsAccess>
-void
-TokenStreamChars<char16_t, AnyCharsAccess>::matchMultiUnitCodePointSlow(char16_t lead,
- uint32_t* codePoint)
-{
- MOZ_ASSERT(unicode::IsLeadSurrogate(lead),
- "matchMultiUnitCodepoint should have ensured |lead| is a lead "
- "surrogate");
-
- int32_t maybeTrail = getCodeUnit();
- if (MOZ_LIKELY(unicode::IsTrailSurrogate(maybeTrail))) {
- *codePoint = unicode::UTF16Decode(lead, maybeTrail);
- } else {
- ungetCodeUnit(maybeTrail);
- *codePoint = 0;
- }
-}
-
template<typename CharT, class AnyCharsAccess>
bool
TokenStreamSpecific<CharT, AnyCharsAccess>::putIdentInTokenbuf(const CharT* identStart)
{
const CharT* const originalAddress = sourceUnits.addressOfNextCodeUnit();
sourceUnits.setAddressOfNextCodeUnit(identStart);
auto restoreNextRawCharAddress =
MakeScopeExit([this, originalAddress]() {
this->sourceUnits.setAddressOfNextCodeUnit(originalAddress);
});
tokenbuf.clear();
- for (;;) {
- int32_t c = getCodeUnit();
+ do {
+ int32_t unit = getCodeUnit();
+ if (unit == EOF)
+ break;
uint32_t codePoint;
- if (!matchMultiUnitCodePoint(c, &codePoint))
- return false;
- if (codePoint) {
- if (!unicode::IsIdentifierPart(codePoint))
+ if (MOZ_LIKELY(isAsciiCodePoint(unit))) {
+ if (MOZ_LIKELY(unicode::IsIdentifierPart(char16_t(unit)))) {
+ if (!tokenbuf.append(unit))
+ return false;
+
+ continue;
+ }
+
+ if (unit != '\\' || !matchUnicodeEscapeIdent(&codePoint))
break;
} else {
- if (unicode::IsIdentifierPart(char16_t(c))) {
- codePoint = c;
- } else {
- if (c != '\\' || !matchUnicodeEscapeIdent(&codePoint))
- break;
+ int32_t cp;
+ if (!getNonAsciiCodePoint(unit, &cp))
+ return false;
+
+ codePoint = AssertedCast<uint32_t>(cp);
+ }
+
+ if (!unicode::IsIdentifierPart(codePoint)) {
+ if (MOZ_UNLIKELY(codePoint == unicode::LINE_SEPARATOR ||
+ codePoint == unicode::PARA_SEPARATOR))
+ {
+ // |restoreNextRawCharAddress| undoes all gets, but it doesn't
+ // revert line/column updates. The ASCII code path never
+ // updates line/column state, so only Unicode separators gotten
+ // by |getNonAsciiCodePoint| require this.
+ anyCharsAccess().undoInternalUpdateLineInfoForEOL();
}
+ break;
}
if (!appendCodePointToTokenbuf(codePoint))
return false;
- }
+ } while (true);
return true;
}
template<typename CharT, class AnyCharsAccess>
MOZ_MUST_USE bool
TokenStreamSpecific<CharT, AnyCharsAccess>::identifierName(TokenStart start,
const CharT* identStart,
@@ -1437,40 +1420,48 @@ TokenStreamSpecific<CharT, AnyCharsAcces
Modifier modifier, TokenKind* out)
{
// Run the bad-token code for every path out of this function except the
// two success-cases.
auto noteBadToken = MakeScopeExit([this]() {
this->badToken();
});
- int c;
+ // We've already consumed an initial code point in the identifer, to *know*
+ // that this is an identifier. So no need to worry about not consuming any
+ // code points in the loop below.
+ int32_t unit;
while (true) {
- c = getCodeUnit();
- if (c == EOF)
+ unit = getCodeUnit();
+ if (unit == EOF)
break;
- uint32_t codePoint;
- if (!matchMultiUnitCodePoint(c, &codePoint))
- return false;
- if (codePoint) {
- if (!unicode::IsIdentifierPart(codePoint))
+ if (MOZ_LIKELY(isAsciiCodePoint(unit))) {
+ if (MOZ_UNLIKELY(!unicode::IsIdentifierPart(static_cast<char16_t>(unit)))) {
+ // Handle a Unicode escape -- otherwise it's not part of the
+ // identifier.
+ uint32_t codePoint;
+ if (unit != '\\' || !matchUnicodeEscapeIdent(&codePoint)) {
+ ungetCodeUnit(unit);
+ break;
+ }
+
+ escaping = IdentifierEscapes::SawUnicodeEscape;
+ }
+ } else {
+ int32_t codePoint;
+ if (!getNonAsciiCodePoint(unit, &codePoint))
+ return false;
+
+ if (!unicode::IsIdentifierPart(uint32_t(codePoint))) {
+ ungetNonAsciiNormalizedCodePoint(codePoint);
break;
-
- continue;
- }
-
- if (!unicode::IsIdentifierPart(char16_t(c))) {
- uint32_t qc;
- if (c != '\\' || !matchUnicodeEscapeIdent(&qc))
- break;
- escaping = IdentifierEscapes::SawUnicodeEscape;
+ }
}
}
- ungetCodeUnit(c);
const CharT* chars;
size_t length;
if (escaping == IdentifierEscapes::SawUnicodeEscape) {
// Identifiers containing Unicode escapes have to be converted into
// tokenbuf before atomizing.
if (!putIdentInTokenbuf(identStart))
return false;
@@ -1591,109 +1582,102 @@ GeneralTokenStreamChars<CharT, AnyCharsA
c = getCodeUnit();
} while (c != EOF && !SourceUnits::isRawEOLChar(c));
ungetCodeUnit(c);
}
template<typename CharT, class AnyCharsAccess>
MOZ_MUST_USE bool
-TokenStreamSpecific<CharT, AnyCharsAccess>::decimalNumber(int c, TokenStart start,
+TokenStreamSpecific<CharT, AnyCharsAccess>::decimalNumber(int32_t unit, TokenStart start,
const CharT* numStart,
Modifier modifier, TokenKind* out)
{
// Run the bad-token code for every path out of this function except the
// one success-case.
auto noteBadToken = MakeScopeExit([this]() {
this->badToken();
});
// Consume integral component digits.
- while (IsAsciiDigit(c))
- c = getCodeUnit();
+ while (IsAsciiDigit(unit))
+ unit = getCodeUnit();
// Numbers contain no escapes, so we can read directly from |sourceUnits|.
double dval;
DecimalPoint decimalPoint = NoDecimal;
- if (c != '.' && c != 'e' && c != 'E') {
- ungetCodeUnit(c);
+ if (unit != '.' && unit != 'e' && unit != 'E') {
+ // NOTE: |unit| may be EOF here.
+ ungetCodeUnit(unit);
// Most numbers are pure decimal integers without fractional component
// or exponential notation. Handle that with optimized code.
if (!GetDecimalInteger(anyCharsAccess().cx, numStart, sourceUnits.addressOfNextCodeUnit(),
&dval))
{
return false;
}
} else {
// Consume any decimal dot and fractional component.
- if (c == '.') {
+ if (unit == '.') {
decimalPoint = HasDecimal;
do {
- c = getCodeUnit();
- } while (IsAsciiDigit(c));
+ unit = getCodeUnit();
+ } while (IsAsciiDigit(unit));
}
// Consume any exponential notation.
- if (c == 'e' || c == 'E') {
- c = getCodeUnit();
- if (c == '+' || c == '-')
- c = getCodeUnit();
+ if (unit == 'e' || unit == 'E') {
+ unit = getCodeUnit();
+ if (unit == '+' || unit == '-')
+ unit = getCodeUnit();
// Exponential notation must contain at least one digit.
- if (!IsAsciiDigit(c)) {
- ungetCodeUnit(c);
+ if (!IsAsciiDigit(unit)) {
+ ungetCodeUnit(unit);
error(JSMSG_MISSING_EXPONENT);
return false;
}
// Consume exponential digits.
do {
- c = getCodeUnit();
- } while (IsAsciiDigit(c));
+ unit = getCodeUnit();
+ } while (IsAsciiDigit(unit));
}
- ungetCodeUnit(c);
+ ungetCodeUnit(unit);
const CharT* dummy;
if (!js_strtod(anyCharsAccess().cx, numStart, sourceUnits.addressOfNextCodeUnit(), &dummy,
&dval))
{
return false;
}
}
// Number followed by IdentifierStart is an error. (This is the only place
// in ECMAScript where token boundary is inadequate to properly separate
// two tokens, necessitating this unaesthetic lookahead.)
- if (c != EOF) {
- if (unicode::IsIdentifierStart(char16_t(c))) {
- error(JSMSG_IDSTART_AFTER_NUMBER);
- return false;
- }
-
- consumeKnownCharIgnoreEOL(c);
-
- uint32_t codePoint;
- if (!matchMultiUnitCodePoint(c, &codePoint))
- return false;
-
- if (codePoint) {
- // In all cases revert the get of the overall code point.
- ungetCodePointIgnoreEOL(codePoint);
-
- if (unicode::IsIdentifierStart(codePoint)) {
- // This will properly point at the start of the code point.
+ if (unit != EOF) {
+ if (MOZ_LIKELY(isAsciiCodePoint(unit))) {
+ if (unicode::IsIdentifierStart(char16_t(unit))) {
error(JSMSG_IDSTART_AFTER_NUMBER);
return false;
}
} else {
- // If not a multi-unit code point, we only need to unget the single
- // code unit consumed.
- ungetCodeUnit(c);
+ int32_t codePoint;
+ if (!getCodePoint(&codePoint))
+ return false;
+
+ ungetNonAsciiNormalizedCodePoint(codePoint);
+
+ if (unicode::IsIdentifierStart(uint32_t(codePoint))) {
+ error(JSMSG_IDSTART_AFTER_NUMBER);
+ return false;
+ }
}
}
noteBadToken.release();
newNumberToken(dval, decimalPoint, start, modifier, out);
return true;
}
@@ -1821,69 +1805,66 @@ TokenStreamSpecific<CharT, AnyCharsAcces
// Check if in the middle of a template string. Have to get this out of
// the way first.
if (MOZ_UNLIKELY(modifier == TemplateTail))
return getStringOrTemplateToken('`', modifier, ttp);
// This loop runs more than once only when whitespace or comments are
// encountered.
do {
- if (MOZ_UNLIKELY(!sourceUnits.hasRawChars())) {
+ int32_t unit = getCodeUnit();
+ if (MOZ_UNLIKELY(unit == EOF)) {
+ MOZ_ASSERT(sourceUnits.atEnd());
anyCharsAccess().flags.isEOF = true;
TokenStart start(sourceUnits, 0);
newSimpleToken(TokenKind::Eof, start, modifier, ttp);
return true;
}
- int c = sourceUnits.getCodeUnit();
- MOZ_ASSERT(c != EOF);
-
- // Chars not in the range 0..127 are rare. Getting them out of the way
- // early allows subsequent checking to be faster.
- if (MOZ_UNLIKELY(c >= 128)) {
- if (unicode::IsSpaceOrBOM2(c)) {
- if (c == unicode::LINE_SEPARATOR ||
- c == unicode::PARA_SEPARATOR)
- {
+ if (MOZ_UNLIKELY(!isAsciiCodePoint(unit))) {
+ // Non-ASCII code points can only be identifiers or whitespace.
+ // It would be nice to compute these *after* discarding whitespace,
+ // but IN A WORLD where |unicode::IsSpaceOrBOM2| requires consuming
+ // a variable number of code points, it's easier to assume it's an
+ // identifier and maybe do a little wasted work, than to unget and
+ // compute and reget if whitespace.
+ TokenStart start(sourceUnits, -1);
+ const CharT* identStart = sourceUnits.addressOfNextCodeUnit() - 1;
+
+ int32_t codePoint;
+ if (!getNonAsciiCodePoint(unit, &codePoint))
+ return badToken();
+
+ if (unicode::IsSpaceOrBOM2(codePoint)) {
+ if (codePoint == unicode::LINE_SEPARATOR || codePoint == unicode::PARA_SEPARATOR) {
if (!updateLineInfoForEOL())
return badToken();
anyCharsAccess().updateFlagsForEOL();
}
continue;
}
- // If there's an identifier here (and no error occurs), it starts
- // at the previous code unit.
- TokenStart start(sourceUnits, -1);
- const CharT* identStart = sourceUnits.addressOfNextCodeUnit() - 1;
-
- static_assert('$' < 128,
+ static_assert(isAsciiCodePoint('$'),
"IdentifierStart contains '$', but as "
"!IsUnicodeIDStart('$'), ensure that '$' is never "
"handled here");
- static_assert('_' < 128,
+ static_assert(isAsciiCodePoint('_'),
"IdentifierStart contains '_', but as "
"!IsUnicodeIDStart('_'), ensure that '_' is never "
"handled here");
- if (unicode::IsUnicodeIDStart(char16_t(c)))
- return identifierName(start, identStart, IdentifierEscapes::None, modifier, ttp);
-
- uint32_t codePoint = c;
- if (!matchMultiUnitCodePoint(c, &codePoint))
- return badToken();
-
- if (codePoint && unicode::IsUnicodeIDStart(codePoint))
+
+ if (unicode::IsUnicodeIDStart(uint32_t(codePoint)))
return identifierName(start, identStart, IdentifierEscapes::None, modifier, ttp);
ungetCodePointIgnoreEOL(codePoint);
error(JSMSG_ILLEGAL_CHARACTER);
return badToken();
- }
+ } // !isAsciiCodePoint(unit)
// Get the token kind, based on the first char. The ordering of c1kind
// comparison is based on the frequency of tokens in real code:
// Parsemark (which represents typical JS code on the web) and the
// Unreal demo (which represents asm.js code).
//
// Parsemark Unreal
// OneChar 32.9% 39.7%
@@ -1894,17 +1875,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces
// EOL 1.7% 0.0%
// ZeroDigit 0.4% 4.9%
// Other 5.7% 13.3%
//
// The ordering is based mostly only Parsemark frequencies, with Unreal
// frequencies used to break close categories (e.g. |Dec| and
// |String|). |Other| is biggish, but no other token kind is common
// enough for it to be worth adding extra values to FirstCharKind.
- FirstCharKind c1kind = FirstCharKind(firstCharKinds[c]);
+ FirstCharKind c1kind = FirstCharKind(firstCharKinds[unit]);
// Look for an unambiguous single-char token.
//
if (c1kind <= OneChar_Max) {
TokenStart start(sourceUnits, -1);
newSimpleToken(TokenKind(c1kind), start, modifier, ttp);
return true;
}
@@ -1922,29 +1903,29 @@ TokenStreamSpecific<CharT, AnyCharsAcces
IdentifierEscapes::None, modifier, ttp);
}
// Look for a decimal number.
//
if (c1kind == Dec) {
TokenStart start(sourceUnits, -1);
const CharT* numStart = sourceUnits.addressOfNextCodeUnit() - 1;
- return decimalNumber(c, start, numStart, modifier, ttp);
+ return decimalNumber(unit, start, numStart, modifier, ttp);
}
// Look for a string or a template string.
//
if (c1kind == String)
- return getStringOrTemplateToken(static_cast<char>(c), modifier, ttp);
+ return getStringOrTemplateToken(static_cast<char>(unit), modifier, ttp);
// Skip over EOL chars, updating line state along the way.
//
if (c1kind == EOL) {
// If it's a \r\n sequence, consume it as a single EOL.
- if (c == '\r' && sourceUnits.hasRawChars())
+ if (unit == '\r' && !sourceUnits.atEnd())
sourceUnits.matchCodeUnit('\n');
if (!updateLineInfoForEOL())
return badToken();
anyCharsAccess().updateFlagsForEOL();
continue;
}
@@ -1953,118 +1934,123 @@ TokenStreamSpecific<CharT, AnyCharsAcces
// number starting with '0' that contains '8' or '9' and is treated as
// decimal) number.
//
if (c1kind == ZeroDigit) {
TokenStart start(sourceUnits, -1);
int radix;
const CharT* numStart;
- c = getCodeUnit();
- if (c == 'x' || c == 'X') {
+ unit = getCodeUnit();
+ if (unit == 'x' || unit == 'X') {
radix = 16;
- c = getCodeUnit();
- if (!JS7_ISHEX(c)) {
- ungetCodeUnit(c);
- reportError(JSMSG_MISSING_HEXDIGITS);
+ unit = getCodeUnit();
+ if (!JS7_ISHEX(unit)) {
+ // NOTE: |unit| may be EOF here.
+ ungetCodeUnit(unit);
+ error(JSMSG_MISSING_HEXDIGITS);
return badToken();
}
// one past the '0x'
numStart = sourceUnits.addressOfNextCodeUnit() - 1;
- while (JS7_ISHEX(c))
- c = getCodeUnit();
- } else if (c == 'b' || c == 'B') {
+ while (JS7_ISHEX(unit))
+ unit = getCodeUnit();
+ } else if (unit == 'b' || unit == 'B') {
radix = 2;
- c = getCodeUnit();
- if (c != '0' && c != '1') {
- ungetCodeUnit(c);
- reportError(JSMSG_MISSING_BINARY_DIGITS);
+ unit = getCodeUnit();
+ if (unit != '0' && unit != '1') {
+ // NOTE: |unit| may be EOF here.
+ ungetCodeUnit(unit);
+ error(JSMSG_MISSING_BINARY_DIGITS);
return badToken();
}
// one past the '0b'
numStart = sourceUnits.addressOfNextCodeUnit() - 1;
- while (c == '0' || c == '1')
- c = getCodeUnit();
- } else if (c == 'o' || c == 'O') {
+ while (unit == '0' || unit == '1')
+ unit = getCodeUnit();
+ } else if (unit == 'o' || unit == 'O') {
radix = 8;
- c = getCodeUnit();
- if (c < '0' || c > '7') {
- ungetCodeUnit(c);
- reportError(JSMSG_MISSING_OCTAL_DIGITS);
+ unit = getCodeUnit();
+ if (!JS7_ISOCT(unit)) {
+ // NOTE: |unit| may be EOF here.
+ ungetCodeUnit(unit);
+ error(JSMSG_MISSING_OCTAL_DIGITS);
return badToken();
}
// one past the '0o'
numStart = sourceUnits.addressOfNextCodeUnit() - 1;
- while ('0' <= c && c <= '7')
- c = getCodeUnit();
- } else if (IsAsciiDigit(c)) {
+ while (JS7_ISOCT(unit))
+ unit = getCodeUnit();
+ } else if (IsAsciiDigit(unit)) {
radix = 8;
// one past the '0'
numStart = sourceUnits.addressOfNextCodeUnit() - 1;
do {
// Octal integer literals are not permitted in strict mode
// code.
if (!reportStrictModeError(JSMSG_DEPRECATED_OCTAL))
return badToken();
// Outside strict mode, we permit 08 and 09 as decimal
// numbers, which makes our behaviour a superset of the
// ECMA numeric grammar. We might not always be so
// permissive, so we warn about it.
- if (c >= '8') {
- if (!warning(JSMSG_BAD_OCTAL, c == '8' ? "08" : "09"))
+ if (unit >= '8') {
+ if (!warning(JSMSG_BAD_OCTAL, unit == '8' ? "08" : "09"))
return badToken();
// Use the decimal scanner for the rest of the number.
- return decimalNumber(c, start, numStart, modifier, ttp);
+ return decimalNumber(unit, start, numStart, modifier, ttp);
}
- c = getCodeUnit();
- } while (IsAsciiDigit(c));
+ unit = getCodeUnit();
+ } while (IsAsciiDigit(unit));
} else {
// '0' not followed by [XxBbOo0-9]; scan as a decimal number.
numStart = sourceUnits.addressOfNextCodeUnit() - 1;
- return decimalNumber(c, start, numStart, modifier, ttp);
+ // NOTE: |unit| may be EOF here. (This is permitted by case #3
+ // in TokenStream.h docs for this function.)
+ return decimalNumber(unit, start, numStart, modifier, ttp);
}
- ungetCodeUnit(c);
-
- if (c != EOF) {
- if (unicode::IsIdentifierStart(char16_t(c))) {
+
+ // Check for an identifier-start code point immediately after the
+ // number. This must be an error, and somewhat surprisingly, if
+ // a check doesn't happen here, it never will.
+ if (MOZ_UNLIKELY(unit == EOF)) {
+ // Technically this isn't necessary -- ungetting EOF does
+ // nothing -- but it's conceptually nicer if we consider all
+ // gets requiring an unget to revert them.
+ ungetCodeUnit(unit);
+ } else if (MOZ_LIKELY(isAsciiCodePoint(unit))) {
+ ungetCodeUnit(unit);
+
+ if (unicode::IsIdentifierStart(char16_t(unit))) {
error(JSMSG_IDSTART_AFTER_NUMBER);
return badToken();
}
-
- consumeKnownCharIgnoreEOL(c);
-
- uint32_t codePoint;
- if (!matchMultiUnitCodePoint(c, &codePoint))
+ } else {
+ int32_t codePoint;
+ if (!getNonAsciiCodePoint(unit, &codePoint))
return badToken();
- if (codePoint) {
- // In all cases revert the get of the overall code point.
- ungetCodePointIgnoreEOL(codePoint);
-
- if (unicode::IsIdentifierStart(codePoint)) {
- // This will properly point at the start of the code
- // point.
- error(JSMSG_IDSTART_AFTER_NUMBER);
- return badToken();
- }
- } else {
- // If not a multi-unit code point, we only need to unget
- // the single code unit consumed.
- ungetCodeUnit(c);
+ ungetCodePointIgnoreEOL(codePoint);
+ if (codePoint == unicode::LINE_SEPARATOR || codePoint == unicode::PARA_SEPARATOR)
+ anyCharsAccess().undoInternalUpdateLineInfoForEOL();
+
+ if (unicode::IsIdentifierStart(uint32_t(codePoint))) {
+ error(JSMSG_IDSTART_AFTER_NUMBER);
+ return badToken();
}
}
double dval;
const char16_t* dummy;
if (!GetPrefixInteger(anyCharsAccess().cx, numStart,
sourceUnits.addressOfNextCodeUnit(), radix, &dummy, &dval))
{
@@ -2082,31 +2068,34 @@ TokenStreamSpecific<CharT, AnyCharsAcces
// creation code for all such tokens. All other tokens must be handled
// by returning (or by continuing from the loop enclosing this).
//
TokenStart start(sourceUnits, -1);
TokenKind simpleKind;
#ifdef DEBUG
simpleKind = TokenKind::Limit; // sentinel value for code after switch
#endif
- switch (c) {
+ switch (static_cast<CharT>(unit)) {
case '.':
- c = getCodeUnit();
- if (IsAsciiDigit(c)) {
+ unit = getCodeUnit();
+ if (IsAsciiDigit(unit)) {
return decimalNumber('.', start, sourceUnits.addressOfNextCodeUnit() - 2, modifier,
ttp);
}
- if (c == '.') {
+ if (unit == '.') {
if (matchCodeUnit('.')) {
simpleKind = TokenKind::TripleDot;
break;
}
}
- ungetCodeUnit(c);
+
+ // NOTE: |unit| may be EOF here. A stray '.' at EOF would be an
+ // error, but subsequent code will handle it.
+ ungetCodeUnit(unit);
simpleKind = TokenKind::Dot;
break;
case '=':
if (matchCodeUnit('='))
simpleKind = matchCodeUnit('=') ? TokenKind::StrictEq : TokenKind::Eq;
else if (matchCodeUnit('>'))
@@ -2118,18 +2107,18 @@ TokenStreamSpecific<CharT, AnyCharsAcces
case '+':
if (matchCodeUnit('+'))
simpleKind = TokenKind::Inc;
else
simpleKind = matchCodeUnit('=') ? TokenKind::AddAssign : TokenKind::Add;
break;
case '\\': {
- uint32_t qc;
- if (uint32_t escapeLength = matchUnicodeEscapeIdStart(&qc)) {
+ uint32_t codePoint;
+ if (uint32_t escapeLength = matchUnicodeEscapeIdStart(&codePoint)) {
return identifierName(start,
sourceUnits.addressOfNextCodeUnit() - escapeLength - 1,
IdentifierEscapes::SawUnicodeEscape, modifier, ttp);
}
// We could point "into" a mistyped escape, e.g. for "\u{41H}" we
// could point at the 'H'. But we don't do that now, so the
// character after the '\' isn't necessarily bad, so just point at
@@ -2204,23 +2193,24 @@ TokenStreamSpecific<CharT, AnyCharsAcces
simpleKind = matchCodeUnit('=') ? TokenKind::PowAssign : TokenKind::Pow;
else
simpleKind = matchCodeUnit('=') ? TokenKind::MulAssign : TokenKind::Mul;
break;
case '/':
// Look for a single-line comment.
if (matchCodeUnit('/')) {
- c = getCodeUnit();
- if (c == '@' || c == '#') {
- bool shouldWarn = c == '@';
+ unit = getCodeUnit();
+ if (unit == '@' || unit == '#') {
+ bool shouldWarn = unit == '@';
if (!getDirectives(false, shouldWarn))
return false;
} else {
- ungetCodeUnit(c);
+ // NOTE: |unit| may be EOF here.
+ ungetCodeUnit(unit);
}
consumeRestOfSingleLineComment();
continue;
}
// Look for a multi-line comment.
if (matchCodeUnit('*')) {
@@ -2282,22 +2272,22 @@ TokenStreamSpecific<CharT, AnyCharsAcces
simpleKind = TokenKind::Dec;
} else {
simpleKind = matchCodeUnit('=') ? TokenKind::SubAssign : TokenKind::Sub;
}
break;
default:
- // We consumed a bad character/code point. Put it back so the
- // error location is the bad character.
- ungetCodePointIgnoreEOL(c);
+ // We consumed a bad ASCII code point/unit. Put it back so the
+ // error location is the bad code point.
+ ungetCodeUnit(unit);
error(JSMSG_ILLEGAL_CHARACTER);
return badToken();
- }
+ } // switch (static_cast<CharT>(unit))
MOZ_ASSERT(simpleKind != TokenKind::Limit,
"switch-statement should have set |simpleKind| before "
"breaking");
newSimpleToken(simpleKind, start, modifier, ttp);
return true;
} while (true);
@@ -2307,122 +2297,196 @@ template<typename CharT, class AnyCharsA
bool
TokenStreamSpecific<CharT, AnyCharsAccess>::getStringOrTemplateToken(char untilChar,
Modifier modifier,
TokenKind* out)
{
MOZ_ASSERT(untilChar == '\'' || untilChar == '"' || untilChar == '`',
"unexpected string/template literal delimiter");
- int c;
-
bool parsingTemplate = (untilChar == '`');
bool templateHead = false;
TokenStart start(sourceUnits, -1);
tokenbuf.clear();
// Run the bad-token code for every path out of this function except the
// one success-case.
auto noteBadToken = MakeScopeExit([this]() {
this->badToken();
});
+ auto ReportPrematureEndOfLiteral = [this, untilChar](unsigned errnum) {
+ // Unicode separators aren't end-of-line in template or (as of
+ // recently) string literals, so this assertion doesn't allow them.
+ MOZ_ASSERT(this->sourceUnits.atEnd() ||
+ this->sourceUnits.peekCodeUnit() == '\r' ||
+ this->sourceUnits.peekCodeUnit() == '\n',
+ "must be parked at EOF or EOL to call this function");
+
+ // The various errors reported here include language like "in a ''
+ // literal" or similar, with '' being '', "", or `` as appropriate.
+ const char delimiters[] = { untilChar, untilChar, '\0' };
+
+ this->error(errnum, delimiters);
+ return;
+ };
+
// We need to detect any of these chars: " or ', \n (or its
// equivalents), \\, EOF. Because we detect EOL sequences here and
// put them back immediately, we can use getCodeUnit().
- while ((c = getCodeUnit()) != untilChar) {
- if (c == EOF) {
- ungetCodeUnit(c);
- const char delimiters[] = { untilChar, untilChar, '\0' };
- error(JSMSG_EOF_BEFORE_END_OF_LITERAL, delimiters);
+ int32_t unit;
+ while ((unit = getCodeUnit()) != untilChar) {
+ if (unit == EOF) {
+ ReportPrematureEndOfLiteral(JSMSG_EOF_BEFORE_END_OF_LITERAL);
return false;
}
- if (c == '\\') {
+ // Non-ASCII code points are always directly appended -- even
+ // U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR that are
+ // ordinarily LineTerminatorSequences. (They contribute their literal
+ // values to template and [as of recently] string literals, but they're
+ // line terminators when computing line/column coordinates.) Handle
+ // the non-ASCI case early for readability.
+ if (MOZ_UNLIKELY(!isAsciiCodePoint(unit))) {
+ static_assert(mozilla::IsSame<CharT, char16_t>::value,
+ "need a getNonAsciiCodePoint that doesn't normalize "
+ "LineTerminatorSequences to correctly handle UTF-8");
+
+ int32_t codePoint;
+ if (unit == unicode::LINE_SEPARATOR || unit == unicode::PARA_SEPARATOR) {
+ if (!updateLineInfoForEOL())
+ return false;
+
+ anyCharsAccess().updateFlagsForEOL();
+
+ codePoint = unit;
+ } else {
+ if (!getNonAsciiCodePoint(unit, &codePoint))
+ return false;
+ }
+
+ if (!appendCodePointToTokenbuf(codePoint))
+ return false;
+
+ continue;
+ }
+
+ if (unit == '\\') {
// When parsing templates, we don't immediately report errors for
- // invalid escapes; these are handled by the parser.
- // In those cases we don't append to tokenbuf, since it won't be
- // read.
- if (!getChar(&c))
- return false;
-
- if (c == EOF) {
- const char delimiters[] = { untilChar, untilChar, '\0' };
- error(JSMSG_EOF_IN_ESCAPE_IN_LITERAL, delimiters);
+ // invalid escapes; these are handled by the parser. We don't
+ // append to tokenbuf in those cases because it won't be read.
+ unit = getCodeUnit();
+ if (unit == EOF) {
+ ReportPrematureEndOfLiteral(JSMSG_EOF_IN_ESCAPE_IN_LITERAL);
return false;
}
- switch (static_cast<CharT>(c)) {
- case 'b': c = '\b'; break;
- case 'f': c = '\f'; break;
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- case 'v': c = '\v'; break;
-
- case '\n':
- // ES5 7.8.4: an escaped line terminator represents
- // no character.
+ // Non-ASCII |unit| isn't handled by code after this, so dedicate
+ // an unlikely special-case to it and then continue.
+ if (MOZ_UNLIKELY(!isAsciiCodePoint(unit))) {
+ int32_t codePoint;
+ if (!getNonAsciiCodePoint(unit, &codePoint))
+ return false;
+
+ // If we consumed U+2028 LINE SEPARATOR or U+2029 PARAGRAPH
+ // SEPARATOR, they'll be normalized to '\n'. '\' followed by
+ // LineContinuation represents no code points, so don't append
+ // in this case.
+ if (codePoint != '\n') {
+ if (!tokenbuf.append(unit))
+ return false;
+ }
+
continue;
+ }
+
+ switch (static_cast<CharT>(unit)) {
+ case 'b': unit = '\b'; break;
+ case 'f': unit = '\f'; break;
+ case 'n': unit = '\n'; break;
+ case 'r': unit = '\r'; break;
+ case 't': unit = '\t'; break;
+ case 'v': unit = '\v'; break;
+
+ case '\r':
+ sourceUnits.matchCodeUnit('\n');
+ MOZ_FALLTHROUGH;
+ case '\n': {
+ // LineContinuation represents no code points. We're manually
+ // consuming a LineTerminatorSequence, so we must manually
+ // update line/column info.
+ if (!updateLineInfoForEOL())
+ return false;
+
+ continue;
+ }
// Unicode character specification.
case 'u': {
int32_t c2 = getCodeUnit();
+ if (c2 == EOF) {
+ ReportPrematureEndOfLiteral(JSMSG_EOF_IN_ESCAPE_IN_LITERAL);
+ return false;
+ }
+
+ // First handle a delimited Unicode escape, e.g. \u{1F4A9}.
if (c2 == '{') {
uint32_t start = sourceUnits.offset() - 3;
uint32_t code = 0;
bool first = true;
bool valid = true;
do {
- int32_t c = getCodeUnit();
- if (c == EOF) {
+ int32_t u3 = getCodeUnit();
+ if (u3 == EOF) {
if (parsingTemplate) {
TokenStreamAnyChars& anyChars = anyCharsAccess();
anyChars.setInvalidTemplateEscape(start,
InvalidEscapeType::Unicode);
valid = false;
break;
}
reportInvalidEscapeError(start, InvalidEscapeType::Unicode);
return false;
}
- if (c == '}') {
+ if (u3 == '}') {
if (first) {
if (parsingTemplate) {
TokenStreamAnyChars& anyChars = anyCharsAccess();
anyChars.setInvalidTemplateEscape(start,
InvalidEscapeType::Unicode);
valid = false;
break;
}
reportInvalidEscapeError(start, InvalidEscapeType::Unicode);
return false;
}
break;
}
- if (!JS7_ISHEX(c)) {
+ // Beware: |u3| may be a non-ASCII code point here; if
+ // so it'll pass into this |if|-block.
+ if (!JS7_ISHEX(u3)) {
if (parsingTemplate) {
- // We put the character back so that we read
- // it on the next pass, which matters if it
- // was '`' or '\'.
- ungetCodeUnit(c);
+ // We put the character back so that we read it
+ // on the next pass, which matters if it was
+ // '`' or '\'.
+ ungetCodeUnit(u3);
TokenStreamAnyChars& anyChars = anyCharsAccess();
anyChars.setInvalidTemplateEscape(start,
InvalidEscapeType::Unicode);
valid = false;
break;
}
reportInvalidEscapeError(start, InvalidEscapeType::Unicode);
return false;
}
- code = (code << 4) | JS7_UNHEX(c);
+ code = (code << 4) | JS7_UNHEX(u3);
if (code > unicode::NonBMPMax) {
if (parsingTemplate) {
TokenStreamAnyChars& anyChars = anyCharsAccess();
anyChars.setInvalidTemplateEscape(start + 3,
InvalidEscapeType::UnicodeOverflow);
valid = false;
break;
}
@@ -2432,147 +2496,156 @@ TokenStreamSpecific<CharT, AnyCharsAcces
first = false;
} while (true);
if (!valid)
continue;
MOZ_ASSERT(code <= unicode::NonBMPMax);
- if (code < unicode::NonBMPMin) {
- c = code;
- } else {
- if (!tokenbuf.append(unicode::LeadSurrogate(code)))
- return false;
- c = unicode::TrailSurrogate(code);
- }
- break;
- }
-
+ if (!appendCodePointToTokenbuf(code))
+ return false;
+
+ continue;
+ } // end of delimited Unicode escape handling
+
+ // Otherwise it must be a fixed-length \uXXXX Unicode escape.
+ // If it isn't, this is usually an error -- but if this is a
+ // template literal, we must defer error reporting because
+ // malformed escapes are okay in *tagged* template literals.
CharT cp[3];
- if (JS7_ISHEX(c2) && peekChars(3, cp) &&
+ if (JS7_ISHEX(c2) &&
+ sourceUnits.peekCodeUnits(3, cp) &&
JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1]) && JS7_ISHEX(cp[2]))
{
- c = (JS7_UNHEX(c2) << 12) |
- (JS7_UNHEX(cp[0]) << 8) |
- (JS7_UNHEX(cp[1]) << 4) |
- JS7_UNHEX(cp[2]);
- skipChars(3);
+ unit = (JS7_UNHEX(c2) << 12) |
+ (JS7_UNHEX(cp[0]) << 8) |
+ (JS7_UNHEX(cp[1]) << 4) |
+ JS7_UNHEX(cp[2]);
+ sourceUnits.skipCodeUnits(3);
} else {
+ // Beware: |c2| may not be an ASCII code point here!
ungetCodeUnit(c2);
uint32_t start = sourceUnits.offset() - 2;
if (parsingTemplate) {
TokenStreamAnyChars& anyChars = anyCharsAccess();
anyChars.setInvalidTemplateEscape(start, InvalidEscapeType::Unicode);
continue;
}
reportInvalidEscapeError(start, InvalidEscapeType::Unicode);
return false;
}
break;
- }
+ } // case 'u'
// Hexadecimal character specification.
case 'x': {
CharT cp[2];
- if (peekChars(2, cp) && JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1])) {
- c = (JS7_UNHEX(cp[0]) << 4) + JS7_UNHEX(cp[1]);
- skipChars(2);
+ if (sourceUnits.peekCodeUnits(2, cp) &&
+ JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1]))
+ {
+ unit = (JS7_UNHEX(cp[0]) << 4) + JS7_UNHEX(cp[1]);
+ sourceUnits.skipCodeUnits(2);
} else {
uint32_t start = sourceUnits.offset() - 2;
if (parsingTemplate) {
TokenStreamAnyChars& anyChars = anyCharsAccess();
anyChars.setInvalidTemplateEscape(start, InvalidEscapeType::Hexadecimal);
continue;
}
reportInvalidEscapeError(start, InvalidEscapeType::Hexadecimal);
return false;
}
break;
}
- default:
+ default: {
+ if (!JS7_ISOCT(unit))
+ break;
+
// Octal character specification.
- if (JS7_ISOCT(c)) {
- int32_t val = JS7_UNOCT(c);
-
- if (!peekChar(&c))
- return false;
-
- // Strict mode code allows only \0, then a non-digit.
- if (val != 0 || IsAsciiDigit(c)) {
- TokenStreamAnyChars& anyChars = anyCharsAccess();
- if (parsingTemplate) {
- anyChars.setInvalidTemplateEscape(sourceUnits.offset() - 2,
- InvalidEscapeType::Octal);
- continue;
- }
- if (!reportStrictModeError(JSMSG_DEPRECATED_OCTAL))
- return false;
- anyChars.flags.sawOctalEscape = true;
+ int32_t val = JS7_UNOCT(unit);
+
+ unit = peekCodeUnit();
+ if (MOZ_UNLIKELY(unit == EOF)) {
+ ReportPrematureEndOfLiteral(JSMSG_EOF_IN_ESCAPE_IN_LITERAL);
+ return false;
+ }
+
+ // Strict mode code allows only \0, then a non-digit.
+ if (val != 0 || IsAsciiDigit(unit)) {
+ TokenStreamAnyChars& anyChars = anyCharsAccess();
+ if (parsingTemplate) {
+ anyChars.setInvalidTemplateEscape(sourceUnits.offset() - 2,
+ InvalidEscapeType::Octal);
+ continue;
}
-
- if (JS7_ISOCT(c)) {
- val = 8 * val + JS7_UNOCT(c);
- consumeKnownChar(c);
- if (!peekChar(&c))
- return false;
- if (JS7_ISOCT(c)) {
- int32_t save = val;
- val = 8 * val + JS7_UNOCT(c);
- if (val <= 0xFF)
- consumeKnownChar(c);
- else
- val = save;
- }
+ if (!reportStrictModeError(JSMSG_DEPRECATED_OCTAL))
+ return false;
+ anyChars.flags.sawOctalEscape = true;
+ }
+
+ if (JS7_ISOCT(unit)) {
+ val = 8 * val + JS7_UNOCT(unit);
+ consumeKnownCodeUnit(unit);
+
+ unit = peekCodeUnit();
+ if (MOZ_UNLIKELY(unit == EOF)) {
+ ReportPrematureEndOfLiteral(JSMSG_EOF_IN_ESCAPE_IN_LITERAL);
+ return false;
}
- c = char16_t(val);
+ if (JS7_ISOCT(unit)) {
+ int32_t save = val;
+ val = 8 * val + JS7_UNOCT(unit);
+ if (val <= 0xFF)
+ consumeKnownCodeUnit(unit);
+ else
+ val = save;
+ }
}
+
+ unit = char16_t(val);
break;
+ } // default
}
- } else if (c == '\r' || c == '\n') {
+
+ if (!tokenbuf.append(unit))
+ return false;
+
+ continue;
+ } // (unit == '\\')
+
+ if (unit == '\r' || unit == '\n') {
if (!parsingTemplate) {
// String literals don't allow ASCII line breaks.
- ungetCodeUnit(c);
- const char delimiters[] = { untilChar, untilChar, '\0' };
- error(JSMSG_EOL_BEFORE_END_OF_STRING, delimiters);
+ ungetCodeUnit(unit);
+ ReportPrematureEndOfLiteral(JSMSG_EOL_BEFORE_END_OF_STRING);
return false;
}
- if (c == '\r') {
- c = '\n';
+ if (unit == '\r') {
+ unit = '\n';
// If it's a \r\n sequence: treat as a single EOL, skip over the \n.
- if (sourceUnits.hasRawChars())
+ if (!sourceUnits.atEnd())
sourceUnits.matchCodeUnit('\n');
}
if (!updateLineInfoForEOL())
return false;
anyCharsAccess().updateFlagsForEOL();
- } else if (c == unicode::LINE_SEPARATOR || c == unicode::PARA_SEPARATOR) {
- // U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR encode
- // their literal values in template literals and (as of fairly
- // recently) string literals, but they still count as line
- // terminators when computing line/column coordinates.
- if (!updateLineInfoForEOL())
- return false;
-
- anyCharsAccess().updateFlagsForEOL();
- } else if (parsingTemplate && c == '$' && matchCodeUnit('{')) {
+ } else if (parsingTemplate && unit == '$' && matchCodeUnit('{')) {
templateHead = true;
break;
}
- if (!tokenbuf.append(c)) {
- ReportOutOfMemory(anyCharsAccess().cx);
+ if (!tokenbuf.append(unit))
return false;
- }
}
JSAtom* atom = atomizeChars(anyCharsAccess().cx, tokenbuf.begin(), tokenbuf.length());
if (!atom)
return false;
noteBadToken.release();
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -165,16 +165,17 @@
#include "mozilla/Attributes.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/MemoryChecking.h"
#include "mozilla/PodOperations.h"
#include "mozilla/TextUtils.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/Unused.h"
+#include <algorithm>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include "jspubtd.h"
#include "frontend/ErrorReporter.h"
#include "frontend/TokenKind.h"
@@ -903,22 +904,24 @@ class SourceUnits
public:
SourceUnits(const CharT* buf, size_t length, size_t startOffset)
: base_(buf),
startOffset_(startOffset),
limit_(buf + length),
ptr(buf)
{ }
- bool hasRawChars() const {
- return ptr < limit_;
+ bool atStart() const {
+ MOZ_ASSERT(ptr, "shouldn't be using if poisoned");
+ return ptr == base_;
}
- bool atStart() const {
- return offset() == 0;
+ bool atEnd() const {
+ MOZ_ASSERT(ptr <= limit_, "shouldn't have overrun");
+ return ptr >= limit_;
}
size_t startOffset() const {
return startOffset_;
}
size_t offset() const {
return startOffset_ + mozilla::PointerRangeSize(base_, ptr);
@@ -943,16 +946,39 @@ class SourceUnits
CharT getCodeUnit() {
return *ptr++; // this will nullptr-crash if poisoned
}
CharT peekCodeUnit() const {
return *ptr; // this will nullptr-crash if poisoned
}
+ bool peekCodeUnits(uint8_t n, CharT* out) const {
+ MOZ_ASSERT(ptr, "shouldn't peek into poisoned SourceUnits");
+ if (n > mozilla::PointerRangeSize(ptr, limit_))
+ return false;
+
+ std::copy_n(ptr, n, out);
+ return true;
+ }
+
+ void skipCodeUnits(uint32_t n) {
+ MOZ_ASSERT(ptr, "shouldn't use poisoned SourceUnits");
+ MOZ_ASSERT(n <= mozilla::PointerRangeSize(ptr, limit_),
+ "shouldn't skip beyond end of SourceUnits");
+ ptr += n;
+ }
+
+ void unskipCodeUnits(uint32_t n) {
+ MOZ_ASSERT(ptr, "shouldn't use poisoned SourceUnits");
+ MOZ_ASSERT(n <= mozilla::PointerRangeSize(base_, ptr),
+ "shouldn't skip beyond start of SourceUnits");
+ ptr -= n;
+ }
+
bool matchCodeUnit(CharT c) {
if (*ptr == c) { // this will nullptr-crash if poisoned
ptr++;
return true;
}
return false;
}
@@ -1019,17 +1045,22 @@ class SourceUnits
/** Next char to get. */
const CharT* ptr;
};
template<typename CharT>
class TokenStreamCharsBase
{
protected:
- void ungetCodeUnit(int32_t c);
+ void ungetCodeUnit(int32_t c) {
+ if (c == EOF)
+ return;
+
+ sourceUnits.ungetCodeUnit();
+ }
public:
using CharBuffer = Vector<CharT, 32>;
TokenStreamCharsBase(JSContext* cx, const CharT* chars, size_t length, size_t startOffset);
static MOZ_ALWAYS_INLINE JSAtom*
atomizeChars(JSContext* cx, const CharT* chars, size_t length);
@@ -1042,20 +1073,34 @@ class TokenStreamCharsBase
using SourceUnits = frontend::SourceUnits<CharT>;
MOZ_MUST_USE bool appendCodePointToTokenbuf(uint32_t codePoint);
// |expect| cannot be an EOL char.
bool matchCodeUnit(int32_t expect) {
MOZ_ASSERT(expect != EOF, "shouldn't be matching EOFs");
MOZ_ASSERT(!SourceUnits::isRawEOLChar(expect));
- return MOZ_LIKELY(sourceUnits.hasRawChars()) && sourceUnits.matchCodeUnit(expect);
+ return MOZ_LIKELY(!sourceUnits.atEnd()) && sourceUnits.matchCodeUnit(expect);
}
protected:
+ int32_t peekCodeUnit() {
+ return MOZ_LIKELY(!sourceUnits.atEnd()) ? sourceUnits.peekCodeUnit() : EOF;
+ }
+
+ void consumeKnownCodeUnit(int32_t unit) {
+ MOZ_ASSERT(unit != EOF, "shouldn't be matching EOF");
+ MOZ_ASSERT(!sourceUnits.atEnd(), "must have units to consume");
+#ifdef DEBUG
+ CharT next =
+#endif
+ sourceUnits.getCodeUnit();
+ MOZ_ASSERT(next == unit, "must be consuming the correct unit");
+ }
+
MOZ_MUST_USE bool
fillWithTemplateStringContents(CharBuffer& charbuf, const CharT* cur, const CharT* end) {
while (cur < end) {
// U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR are
// interpreted literally inside template literal contents; only
// literal CRLF sequences are normalized to '\n'. See
// <https://tc39.github.io/ecma262/#sec-static-semantics-tv-and-trv>.
CharT ch = *cur;
@@ -1074,17 +1119,17 @@ class TokenStreamCharsBase
return true;
}
/**
* Determine whether a code unit constitutes a complete ASCII code point.
* (The code point's exact value might not be used, however, if subsequent
* code observes that |unit| is part of a LineTerminatorSequence.)
*/
- static MOZ_MUST_USE MOZ_ALWAYS_INLINE bool isAsciiCodePoint(CharT unit) {
+ static constexpr MOZ_ALWAYS_INLINE MOZ_MUST_USE bool isAsciiCodePoint(CharT unit) {
return mozilla::IsAscii(unit);
}
protected:
/** Code units in the source code being tokenized. */
SourceUnits sourceUnits;
/** Current token string buffer. */
@@ -1142,16 +1187,19 @@ class GeneralTokenStreamChars
// assert both gets used compatible modifiers.
token->modifier = modifier;
token->modifierException = TokenStreamShared::NoException;
#endif
return token;
}
+ uint32_t matchUnicodeEscape(uint32_t* codePoint);
+ uint32_t matchExtendedUnicodeEscape(uint32_t* codePoint);
+
protected:
using typename CharsSharedBase::SourceUnits;
using CharsSharedBase::sourceUnits;
public:
using CharsSharedBase::CharsSharedBase;
@@ -1206,17 +1254,33 @@ class GeneralTokenStreamChars
void newRegExpToken(RegExpFlag reflags, TokenStart start, TokenKind* out)
{
Token* token = newToken(TokenKind::RegExp, start, TokenStreamShared::Operand, out);
token->setRegExpFlags(reflags);
}
MOZ_COLD bool badToken();
- int32_t getCodeUnit();
+ /**
+ * Get the next code unit -- the next numeric sub-unit of source text,
+ * possibly smaller than a full code point -- without updating line/column
+ * counters or consuming LineTerminatorSequences.
+ *
+ * Because of these limitations, only use this if (a) the resulting code
+ * unit is guaranteed to be ungotten (by ungetCodeUnit()) if it's an EOL,
+ * and (b) the line-related state (lineno, linebase) is not used before
+ * it's ungotten.
+ */
+ int32_t getCodeUnit() {
+ if (MOZ_LIKELY(!sourceUnits.atEnd()))
+ return sourceUnits.getCodeUnit();
+
+ anyCharsAccess().flags.isEOF = true;
+ return EOF;
+ }
void ungetCodeUnit(int32_t c) {
MOZ_ASSERT_IF(c == EOF, anyCharsAccess().flags.isEOF);
CharsSharedBase::ungetCodeUnit(c);
}
void ungetChar(int32_t c);
@@ -1225,16 +1289,20 @@ class GeneralTokenStreamChars
* Consume characters til EOL/EOF following the start of a single-line
* comment, without consuming the EOL/EOF.
*/
void consumeRestOfSingleLineComment();
MOZ_MUST_USE MOZ_ALWAYS_INLINE bool updateLineInfoForEOL() {
return anyCharsAccess().internalUpdateLineInfoForEOL(sourceUnits.offset());
}
+
+ protected:
+ uint32_t matchUnicodeEscapeIdStart(uint32_t* codePoint);
+ bool matchUnicodeEscapeIdent(uint32_t* codePoint);
};
template<typename CharT, class AnyCharsAccess> class TokenStreamChars;
template<class AnyCharsAccess>
class TokenStreamChars<char16_t, AnyCharsAccess>
: public GeneralTokenStreamChars<char16_t, AnyCharsAccess>
{
@@ -1242,55 +1310,28 @@ class TokenStreamChars<char16_t, AnyChar
using Self = TokenStreamChars<char16_t, AnyCharsAccess>;
using GeneralCharsBase = GeneralTokenStreamChars<char16_t, AnyCharsAccess>;
using CharsSharedBase = TokenStreamCharsBase<char16_t>;
using GeneralCharsBase::asSpecific;
using typename GeneralCharsBase::TokenStreamSpecific;
- void matchMultiUnitCodePointSlow(char16_t lead, uint32_t* codePoint);
-
protected:
using GeneralCharsBase::anyCharsAccess;
using GeneralCharsBase::getCodeUnit;
using CharsSharedBase::isAsciiCodePoint;
using GeneralCharsBase::sourceUnits;
using CharsSharedBase::ungetCodeUnit;
using GeneralCharsBase::updateLineInfoForEOL;
using typename GeneralCharsBase::SourceUnits;
using GeneralCharsBase::GeneralCharsBase;
- // |c| must be the code unit just gotten. If it and the subsequent code
- // unit form a valid surrogate pair, get the second code unit, set
- // |*codePoint| to the code point encoded by the surrogate pair, and return
- // true. Otherwise do not get a second code unit, set |*codePoint = 0|,
- // and return true.
- //
- // ECMAScript specifically requires that unpaired UTF-16 surrogates be
- // treated as the corresponding code point and not as an error. See
- // <https://tc39.github.io/ecma262/#sec-ecmascript-language-types-string-type>.
- // Therefore this function always returns true. The |bool| return type
- // exists so that a future UTF-8 |TokenStreamChars| can treat malformed
- // multi-code unit UTF-8 sequences as errors. (Because ECMAScript only
- // interprets UTF-16 inputs, the process of translating the UTF-8 to UTF-16
- // would fail, so no script should execute. Technically, we shouldn't even
- // be tokenizing -- but it probably isn't realistic to assume every user
- // correctly passes only valid UTF-8, at least not without better types in
- // our codebase for strings that by construction only contain valid UTF-8.)
- MOZ_ALWAYS_INLINE bool matchMultiUnitCodePoint(char16_t c, uint32_t* codePoint) {
- if (MOZ_LIKELY(!unicode::IsLeadSurrogate(c)))
- *codePoint = 0;
- else
- matchMultiUnitCodePointSlow(c, codePoint);
- return true;
- }
-
// Try to get the next code point, normalizing '\r', '\r\n', '\n', and the
// Unicode line/paragraph separators into '\n'. Also updates internal
// line-counter state. Return true on success and store the character in
// |*c|. Return false and leave |*c| undefined on failure.
MOZ_MUST_USE bool getCodePoint(int32_t* cp);
// A deprecated alias for |getCodePoint|: most code using this is being
// replaced with different approaches.
@@ -1310,17 +1351,17 @@ class TokenStreamChars<char16_t, AnyChar
*/
MOZ_MUST_USE bool getFullAsciiCodePoint(char16_t lead, int32_t* codePoint) {
MOZ_ASSERT(isAsciiCodePoint(lead),
"non-ASCII code units must be handled separately");
MOZ_ASSERT(lead == sourceUnits.previousCodeUnit(),
"getFullAsciiCodePoint called incorrectly");
if (MOZ_UNLIKELY(lead == '\r')) {
- if (MOZ_LIKELY(sourceUnits.hasRawChars()))
+ if (MOZ_LIKELY(!sourceUnits.atEnd()))
sourceUnits.matchCodeUnit('\n');
} else if (MOZ_LIKELY(lead != '\n')) {
*codePoint = lead;
return true;
}
*codePoint = '\n';
bool ok = updateLineInfoForEOL();
@@ -1340,19 +1381,47 @@ class TokenStreamChars<char16_t, AnyChar
* return false and leave |*codePoint| undefined on failure.
*
* If a LineTerminatorSequence was consumed, also update line/column info.
*
* This may change the current |sourceUnits| offset.
*/
MOZ_MUST_USE bool getNonAsciiCodePoint(char16_t lead, int32_t* cp);
+ /**
+ * Unget a full code point (ASCII or not) without altering line/column
+ * state. If line/column state must be updated, this must happen manually.
+ * This method ungets a single code point, not a LineTerminatorSequence
+ * that is multiple code points. (Generally you shouldn't be in a state
+ * where you've just consumed "\r\n" and want to unget that full sequence.)
+ *
+ * This function ordinarily should be used to unget code points that have
+ * been consumed *without* line/column state having been updated.
+ */
void ungetCodePointIgnoreEOL(uint32_t codePoint);
/**
+ * Unget an originally non-ASCII, normalized code point, including undoing
+ * line/column updates that were performed for it. Don't use this if the
+ * code point was gotten *without* line/column state being updated!
+ */
+ void ungetNonAsciiNormalizedCodePoint(uint32_t codePoint) {
+ MOZ_ASSERT_IF(isAsciiCodePoint(codePoint),
+ codePoint == '\n');
+ MOZ_ASSERT(codePoint != unicode::LINE_SEPARATOR,
+ "should not be ungetting un-normalized code points");
+ MOZ_ASSERT(codePoint != unicode::PARA_SEPARATOR,
+ "should not be ungetting un-normalized code points");
+
+ ungetCodePointIgnoreEOL(codePoint);
+ if (codePoint == '\n')
+ anyCharsAccess().undoInternalUpdateLineInfoForEOL();
+ }
+
+ /**
* Unget a just-gotten LineTerminator sequence: '\r', '\n', '\r\n', or
* a Unicode line/paragraph separator, also undoing line/column information
* changes reflecting that LineTerminator.
*/
void ungetLineTerminator();
};
// TokenStream is the lexical scanner for JavaScript source text.
@@ -1427,37 +1496,41 @@ class MOZ_STACK_CLASS TokenStreamSpecifi
private:
using typename CharsSharedBase::CharBuffer;
using typename CharsSharedBase::SourceUnits;
private:
using CharsSharedBase::appendCodePointToTokenbuf;
using CharsSharedBase::atomizeChars;
using GeneralCharsBase::badToken;
+ using CharsSharedBase::consumeKnownCodeUnit;
using GeneralCharsBase::consumeRestOfSingleLineComment;
using CharsSharedBase::copyTokenbufTo;
using CharsSharedBase::fillWithTemplateStringContents;
using CharsBase::getChar;
using CharsBase::getCodePoint;
using GeneralCharsBase::getCodeUnit;
using CharsBase::getFullAsciiCodePoint;
using CharsBase::getNonAsciiCodePoint;
using CharsSharedBase::isAsciiCodePoint;
using CharsSharedBase::matchCodeUnit;
- using CharsBase::matchMultiUnitCodePoint;
+ using GeneralCharsBase::matchUnicodeEscapeIdent;
+ using GeneralCharsBase::matchUnicodeEscapeIdStart;
using GeneralCharsBase::newAtomToken;
using GeneralCharsBase::newNameToken;
using GeneralCharsBase::newNumberToken;
using GeneralCharsBase::newRegExpToken;
using GeneralCharsBase::newSimpleToken;
+ using CharsSharedBase::peekCodeUnit;
using CharsSharedBase::sourceUnits;
using CharsSharedBase::tokenbuf;
using GeneralCharsBase::ungetChar;
using CharsBase::ungetCodePointIgnoreEOL;
using CharsSharedBase::ungetCodeUnit;
+ using CharsBase::ungetNonAsciiNormalizedCodePoint;
using GeneralCharsBase::updateLineInfoForEOL;
template<typename CharU> friend class TokenStreamPosition;
public:
TokenStreamSpecific(JSContext* cx, const ReadOnlyCompileOptions& options,
const CharT* base, size_t length);
@@ -1588,51 +1661,51 @@ class MOZ_STACK_CLASS TokenStreamSpecifi
}
MOZ_MUST_USE bool putIdentInTokenbuf(const CharT* identStart);
/**
* Tokenize a decimal number that begins at |numStart| into the provided
* token.
*
- * |c| must be one of these values:
+ * |unit| must be one of these values:
*
* 1. The first decimal digit in the integral part of a decimal number
* not starting with '0' or '.', e.g. '1' for "17", '3' for "3.14", or
* '8' for "8.675309e6".
*
* In this case, the next |getCodeUnit()| must return the code unit after
- * |c| in the overall number.
+ * |unit| in the overall number.
*
* 2. The '.' in a "."/"0."-prefixed decimal number or the 'e'/'E' in a
* "0e"/"0E"-prefixed decimal number, e.g. ".17", "0.42", or "0.1e3".
*
* In this case, the next |getCodeUnit()| must return the code unit
* *after* the first decimal digit *after* the '.'. So the next code
* unit would be '7' in ".17", '2' in "0.42", 'e' in "0.4e+8", or '/' in
* "0.5/2" (three separate tokens).
*
* 3. The code unit after the '0' where "0" is the entire number token.
*
- * In this case, the next |getCodeUnit()| returns the code unit after
- * |c|.
+ * In this case, the next |getCodeUnit()| would return the code unit
+ * after |unit|, but this function will never perform such call.
*
* 4. (Non-strict mode code only) The first '8' or '9' in a "noctal"
* number that begins with a '0' but contains a non-octal digit in its
* integer part so is interpreted as decimal, e.g. '9' in "09.28" or
* '8' in "0386" or '9' in "09+7" (three separate tokens").
*
* In this case, the next |getCodeUnit()| returns the code unit after
- * |c|: '.', '6', or '+' in the examples above.
+ * |unit|: '.', '6', or '+' in the examples above.
*
* This interface is super-hairy and horribly stateful. Unfortunately, its
* hair merely reflects the intricacy of ECMAScript numeric literal syntax.
* And incredibly, it *improves* on the goto-based horror that predated it.
*/
- MOZ_MUST_USE bool decimalNumber(int c, TokenStart start, const CharT* numStart,
+ MOZ_MUST_USE bool decimalNumber(int32_t unit, TokenStart start, const CharT* numStart,
Modifier modifier, TokenKind* out);
/** Tokenize a regular expression literal beginning at |start|. */
MOZ_MUST_USE bool regexpLiteral(TokenStart start, TokenKind* out);
public:
// Advance to the next token. If the token stream encountered an error,
// return false. Otherwise return true and store the token kind in |*ttp|.
@@ -1795,58 +1868,23 @@ class MOZ_STACK_CLASS TokenStreamSpecifi
MOZ_MUST_USE bool identifierName(TokenStart start, const CharT* identStart,
IdentifierEscapes escaping, Modifier modifier,
TokenKind* out);
MOZ_MUST_USE bool getTokenInternal(TokenKind* const ttp, const Modifier modifier);
MOZ_MUST_USE bool getStringOrTemplateToken(char untilChar, Modifier modifier, TokenKind* out);
- uint32_t peekUnicodeEscape(uint32_t* codePoint);
- uint32_t peekExtendedUnicodeEscape(uint32_t* codePoint);
- uint32_t matchUnicodeEscapeIdStart(uint32_t* codePoint);
- bool matchUnicodeEscapeIdent(uint32_t* codePoint);
- bool peekChars(int n, CharT* cp);
-
MOZ_MUST_USE bool getDirectives(bool isMultiline, bool shouldWarnDeprecated);
MOZ_MUST_USE bool getDirective(bool isMultiline, bool shouldWarnDeprecated,
const char* directive, uint8_t directiveLength,
const char* errorMsgPragma,
UniquePtr<char16_t[], JS::FreePolicy>* destination);
MOZ_MUST_USE bool getDisplayURL(bool isMultiline, bool shouldWarnDeprecated);
MOZ_MUST_USE bool getSourceMappingURL(bool isMultiline, bool shouldWarnDeprecated);
-
- void consumeKnownChar(int32_t expect) {
- int32_t c;
- MOZ_ALWAYS_TRUE(getChar(&c));
- MOZ_ASSERT(c == expect);
- }
-
- void consumeKnownCharIgnoreEOL(int32_t expect) {
-#ifdef DEBUG
- auto c =
-#endif
- getCodeUnit();
- MOZ_ASSERT(c == expect);
- }
-
- MOZ_MUST_USE bool peekChar(int32_t* c) {
- if (!getChar(c))
- return false;
- ungetChar(*c);
- return true;
- }
-
- void skipChars(uint32_t n) {
- while (n-- > 0) {
- MOZ_ASSERT(sourceUnits.hasRawChars());
- mozilla::DebugOnly<int32_t> c = getCodeUnit();
- MOZ_ASSERT(!SourceUnits::isRawEOLChar(c));
- }
- }
};
// It's preferable to define this in TokenStream.cpp, but its template-ness
// means we'd then have to *instantiate* this constructor for all possible
// (CharT, AnyCharsAccess) pairs -- and that gets super-messy as AnyCharsAccess
// *itself* is templated. This symbol really isn't that huge compared to some
// defined inline in TokenStreamSpecific, so just rely on the linker commoning
// stuff up.
--- a/js/src/fuzz-tests/tests.cpp
+++ b/js/src/fuzz-tests/tests.cpp
@@ -51,17 +51,17 @@ jsfuzz_createGlobal(JSContext* cx, JSPri
options);
if (!newGlobal)
return nullptr;
JSAutoRealm ar(cx, newGlobal);
// Populate the global object with the standard globals like Object and
// Array.
- if (!JS_InitStandardClasses(cx, newGlobal))
+ if (!JS::InitRealmStandardClasses(cx))
return nullptr;
return newGlobal;
}
static bool
jsfuzz_init(JSContext** cx, JS::PersistentRootedObject* global)
{
--- a/js/src/gdb/gdb-tests.cpp
+++ b/js/src/gdb/gdb-tests.cpp
@@ -87,17 +87,17 @@ main(int argc, const char** argv)
/* Create the global object. */
JS::RealmOptions options;
RootedObject global(cx, checkPtr(JS_NewGlobalObject(cx, &global_class,
nullptr, JS::FireOnNewGlobalHook, options)));
JSAutoRealm ar(cx, global);
/* Populate the global object with the standard globals,
like Object and Array. */
- checkBool(JS_InitStandardClasses(cx, global));
+ checkBool(JS::InitRealmStandardClasses(cx));
argv++;
while (*argv) {
const char* name = *argv++;
GDBFragment* fragment;
for (fragment = GDBFragment::allFragments; fragment; fragment = fragment->next) {
if (strcmp(fragment->name(), name) == 0) {
fragment->run(cx, argv);
--- a/js/src/jsapi-tests/testDebugger.cpp
+++ b/js/src/jsapi-tests/testDebugger.cpp
@@ -15,17 +15,17 @@ BEGIN_TEST(testDebugger_newScriptHook)
// Test that top-level indirect eval fires the newScript hook.
CHECK(JS_DefineDebuggerObject(cx, global));
JS::RealmOptions options;
JS::RootedObject g(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr,
JS::FireOnNewGlobalHook, options));
CHECK(g);
{
JSAutoRealm ae(cx, g);
- CHECK(JS_InitStandardClasses(cx, g));
+ CHECK(JS::InitRealmStandardClasses(cx));
}
JS::RootedObject gWrapper(cx, g);
CHECK(JS_WrapObject(cx, &gWrapper));
JS::RootedValue v(cx, JS::ObjectValue(*gWrapper));
CHECK(JS_SetProperty(cx, global, "g", v));
EXEC("var dbg = Debugger(g);\n"
--- a/js/src/jsapi-tests/testGetPropertyDescriptor.cpp
+++ b/js/src/jsapi-tests/testGetPropertyDescriptor.cpp
@@ -34,17 +34,17 @@ BEGIN_TEST(test_GetPropertyDescriptor)
CHECK(value.isTrue());
CHECK(JS_GetProperty(cx, descObj, "enumerable", &value));
CHECK(value.isTrue());
CHECK(JS_GetPropertyDescriptor(cx, obj, "not-here", &desc));
CHECK_EQUAL(desc.object(), nullptr);
CHECK(JS_GetPropertyDescriptor(cx, obj, "toString", &desc));
- JS::RootedObject objectProto(cx, JS_GetObjectPrototype(cx, obj));
+ JS::RootedObject objectProto(cx, JS::GetRealmObjectPrototype(cx));
CHECK(objectProto);
CHECK_EQUAL(desc.object(), objectProto);
CHECK(desc.value().isObject());
CHECK(JS::IsCallable(&desc.value().toObject()));
return true;
}
END_TEST(test_GetPropertyDescriptor)
--- a/js/src/jsapi-tests/testMutedErrors.cpp
+++ b/js/src/jsapi-tests/testMutedErrors.cpp
@@ -42,17 +42,17 @@ eval(const char* asciiChars, bool mutedE
chars[i] = asciiChars[i];
chars[len] = 0;
JS::RealmOptions globalOptions;
JS::RootedObject global(cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr,
JS::FireOnNewGlobalHook, globalOptions));
CHECK(global);
JSAutoRealm ar(cx, global);
- CHECK(JS_InitStandardClasses(cx, global));
+ CHECK(JS::InitRealmStandardClasses(cx));
JS::CompileOptions options(cx);
options.setMutedErrors(mutedErrors)
.setFileAndLine("", 0);
return JS::Evaluate(cx, options, chars.get(), len, rval);
}
--- a/js/src/jsapi-tests/testResolveRecursion.cpp
+++ b/js/src/jsapi-tests/testResolveRecursion.cpp
@@ -143,17 +143,17 @@ END_TEST(testResolveRecursion)
*
* (XPConnect apparently does have global classes, such as the one created by
* nsMessageManagerScriptExecutor::InitChildGlobalInternal(), that have resolve
* hooks which can call back into JS, and on which JS_InitStandardClasses is
* called. Calling back into JS in the middle of resolving `undefined` is bad.)
*/
BEGIN_TEST(testResolveRecursion_InitStandardClasses)
{
- CHECK(JS_InitStandardClasses(cx, global));
+ CHECK(JS::InitRealmStandardClasses(cx));
return true;
}
const JSClass* getGlobalClass() override {
static const JSClassOps myGlobalClassOps = {
nullptr, // add
nullptr, // delete
nullptr, // enumerate
--- a/js/src/jsapi-tests/tests.cpp
+++ b/js/src/jsapi-tests/tests.cpp
@@ -87,17 +87,17 @@ JSObject* JSAPITest::createGlobal(JSPrin
options);
if (!newGlobal)
return nullptr;
JSAutoRealm ar(cx, newGlobal);
// Populate the global object with the standard globals like Object and
// Array.
- if (!JS_InitStandardClasses(cx, newGlobal))
+ if (!JS::InitRealmStandardClasses(cx))
return nullptr;
global = newGlobal;
return newGlobal;
}
int main(int argc, char* argv[])
{
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -941,29 +941,16 @@ JS_TransplantObject(JSContext* cx, Handl
* the inner window and global object.
*/
JS_PUBLIC_API(bool)
JS_RefreshCrossCompartmentWrappers(JSContext* cx, HandleObject obj)
{
return RemapAllWrappersForObject(cx, obj, obj);
}
-JS_PUBLIC_API(bool)
-JS_InitStandardClasses(JSContext* cx, HandleObject obj)
-{
- MOZ_ASSERT(!cx->zone()->isAtomsZone());
- AssertHeapIsIdle();
- CHECK_REQUEST(cx);
-
- assertSameCompartment(cx, obj);
-
- Rooted<GlobalObject*> global(cx, &obj->global());
- return GlobalObject::initStandardClasses(cx, global);
-}
-
typedef struct JSStdName {
size_t atomOffset; /* offset of atom pointer in JSAtomState */
JSProtoKey key;
bool isDummy() const { return key == JSProto_Null; }
bool isSentinel() const { return key == JSProto_LIMIT; }
} JSStdName;
static const JSStdName*
@@ -1219,59 +1206,16 @@ JS_IdToProtoKey(JSContext* cx, HandleId
if (GlobalObject::skipDeselectedConstructor(cx, stdnm->key))
return JSProto_Null;
MOZ_ASSERT(MOZ_ARRAY_LENGTH(standard_class_names) == JSProto_LIMIT + 1);
return static_cast<JSProtoKey>(stdnm - standard_class_names);
}
JS_PUBLIC_API(JSObject*)
-JS_GetObjectPrototype(JSContext* cx, HandleObject forObj)
-{
- CHECK_REQUEST(cx);
- assertSameCompartment(cx, forObj);
- Rooted<GlobalObject*> global(cx, &forObj->global());
- return GlobalObject::getOrCreateObjectPrototype(cx, global);
-}
-
-JS_PUBLIC_API(JSObject*)
-JS_GetFunctionPrototype(JSContext* cx, HandleObject forObj)
-{
- CHECK_REQUEST(cx);
- assertSameCompartment(cx, forObj);
- Rooted<GlobalObject*> global(cx, &forObj->global());
- return GlobalObject::getOrCreateFunctionPrototype(cx, global);
-}
-
-JS_PUBLIC_API(JSObject*)
-JS_GetArrayPrototype(JSContext* cx, HandleObject forObj)
-{
- CHECK_REQUEST(cx);
- assertSameCompartment(cx, forObj);
- Rooted<GlobalObject*> global(cx, &forObj->global());
- return GlobalObject::getOrCreateArrayPrototype(cx, global);
-}
-
-JS_PUBLIC_API(JSObject*)
-JS_GetErrorPrototype(JSContext* cx)
-{
- CHECK_REQUEST(cx);
- Rooted<GlobalObject*> global(cx, cx->global());
- return GlobalObject::getOrCreateCustomErrorPrototype(cx, global, JSEXN_ERR);
-}
-
-JS_PUBLIC_API(JSObject*)
-JS_GetIteratorPrototype(JSContext* cx)
-{
- CHECK_REQUEST(cx);
- Rooted<GlobalObject*> global(cx, cx->global());
- return GlobalObject::getOrCreateIteratorPrototype(cx, global);
-}
-
-JS_PUBLIC_API(JSObject*)
JS_GetGlobalForObject(JSContext* cx, JSObject* obj)
{
AssertHeapIsIdle();
assertSameCompartment(cx, obj);
return &obj->global();
}
extern JS_PUBLIC_API(bool)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1133,26 +1133,16 @@ JS_MarkCrossZoneId(JSContext* cx, jsid i
/**
* If value stores a jsid (an atomized string or symbol), mark that id as for
* JS_MarkCrossZoneId.
*/
extern JS_PUBLIC_API(void)
JS_MarkCrossZoneIdValue(JSContext* cx, const JS::Value& value);
/**
- * Initialize standard JS class constructors, prototypes, and any top-level
- * functions and constants associated with the standard classes (e.g. isNaN
- * for Number).
- *
- * NB: This sets cx's global object to obj if it was null.
- */
-extern JS_PUBLIC_API(bool)
-JS_InitStandardClasses(JSContext* cx, JS::Handle<JSObject*> obj);
-
-/**
* Resolve id, which must contain either a string or an int, to a standard
* class name in obj if possible, defining the class's constructor and/or
* prototype and storing true in *resolved. If id does not name a standard
* class or a top-level property induced by initializing a standard class,
* store false in *resolved and just return true. Return false on error,
* as usual for bool result-typed API entry points.
*
* This API can be called directly from a global object class's resolve op,
@@ -1202,51 +1192,16 @@ IdentifyStandardConstructor(JSObject* ob
extern JS_PUBLIC_API(void)
ProtoKeyToId(JSContext* cx, JSProtoKey key, JS::MutableHandleId idp);
} /* namespace JS */
extern JS_PUBLIC_API(JSProtoKey)
JS_IdToProtoKey(JSContext* cx, JS::HandleId id);
-/**
- * Returns the original value of |Function.prototype| from the global object in
- * which |forObj| was created.
- */
-extern JS_PUBLIC_API(JSObject*)
-JS_GetFunctionPrototype(JSContext* cx, JS::HandleObject forObj);
-
-/**
- * Returns the original value of |Object.prototype| from the global object in
- * which |forObj| was created.
- */
-extern JS_PUBLIC_API(JSObject*)
-JS_GetObjectPrototype(JSContext* cx, JS::HandleObject forObj);
-
-/**
- * Returns the original value of |Array.prototype| from the global object in
- * which |forObj| was created.
- */
-extern JS_PUBLIC_API(JSObject*)
-JS_GetArrayPrototype(JSContext* cx, JS::HandleObject forObj);
-
-/**
- * Returns the original value of |Error.prototype| from the global
- * object of the current compartment of cx.
- */
-extern JS_PUBLIC_API(JSObject*)
-JS_GetErrorPrototype(JSContext* cx);
-
-/**
- * Returns the %IteratorPrototype% object that all built-in iterator prototype
- * chains go through for the global object of the current compartment of cx.
- */
-extern JS_PUBLIC_API(JSObject*)
-JS_GetIteratorPrototype(JSContext* cx);
-
extern JS_PUBLIC_API(JSObject*)
JS_GetGlobalForObject(JSContext* cx, JSObject* obj);
extern JS_PUBLIC_API(bool)
JS_IsGlobalObject(JSObject* obj);
extern JS_PUBLIC_API(JSObject*)
JS_GlobalLexicalEnvironment(JSObject* obj);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3437,17 +3437,17 @@ NewSandbox(JSContext* cx, bool lazy)
SetStandardRealmOptions(options);
RootedObject obj(cx, JS_NewGlobalObject(cx, &sandbox_class, nullptr,
JS::DontFireOnNewGlobalHook, options));
if (!obj)
return nullptr;
{
JSAutoRealm ar(cx, obj);
- if (!lazy && !JS_InitStandardClasses(cx, obj))
+ if (!lazy && !JS::InitRealmStandardClasses(cx))
return nullptr;
RootedValue value(cx, BooleanValue(lazy));
if (!JS_DefineProperty(cx, obj, "lazy", value, JSPROP_PERMANENT | JSPROP_READONLY))
return nullptr;
JS_FireOnNewGlobalObject(cx, obj);
}
@@ -8278,17 +8278,17 @@ NewGlobalObject(JSContext* cx, JS::Realm
JS::DontFireOnNewGlobalHook, options));
if (!glob)
return nullptr;
{
JSAutoRealm ar(cx, glob);
#ifndef LAZY_STANDARD_CLASSES
- if (!JS_InitStandardClasses(cx, glob))
+ if (!JS::InitRealmStandardClasses(cx))
return nullptr;
#endif
bool succeeded;
if (!JS_SetImmutablePrototype(cx, glob, &succeeded))
return nullptr;
MOZ_ASSERT(succeeded,
"a fresh, unexposed global object is always capable of "
--- a/js/src/tests/jstests.list
+++ b/js/src/tests/jstests.list
@@ -41,21 +41,16 @@ skip-if(!this.hasOwnProperty("Intl")) in
# Skip built-ins/Simd tests when SIMD isn't available.
skip-if(!this.hasOwnProperty("SIMD")) include test262/built-ins/Simd/jstests.list
# https://bugzilla.mozilla.org/show_bug.cgi?id=1415303
skip-if(!this.hasOwnProperty("SharedArrayBuffer")) script non262/SIMD/load-sab-buffer-compat.js
skip-if(!this.hasOwnProperty("Atomics")) include test262/built-ins/Atomics/jstests.list
skip-if(!this.hasOwnProperty("SharedArrayBuffer")) include test262/built-ins/SharedArrayBuffer/jstests.list
-# flatMap and flatten are Nightly-only
-skip-if(!Array.prototype.flatMap) include test262/built-ins/Array/prototype/flatMap/jstests.list
-skip-if(!Array.prototype.flat) include test262/built-ins/Array/prototype/flat/jstests.list
-
-
#####################################
# Test262 tests disabled on browser #
#####################################
# Defines a non-configurable property on the WindowProxy object.
skip-if(!xulRuntime.shell) script test262/annexB/language/eval-code/direct/global-block-decl-eval-global-existing-global-update.js
skip-if(!xulRuntime.shell) script test262/annexB/language/eval-code/direct/global-if-decl-else-decl-a-eval-global-existing-global-update.js
skip-if(!xulRuntime.shell) script test262/annexB/language/eval-code/direct/global-if-decl-else-decl-b-eval-global-existing-global-update.js
@@ -124,30 +119,25 @@ skip script test262/built-ins/TypedArray
skip script test262/built-ins/TypedArrayConstructors/internals/HasProperty/detached-buffer-realm.js
skip script test262/built-ins/TypedArrayConstructors/internals/HasProperty/detached-buffer.js
skip script test262/built-ins/TypedArrayConstructors/internals/HasProperty/infinity-with-detached-buffer.js
skip script test262/built-ins/TypedArrayConstructors/internals/Set/detached-buffer-realm.js
skip script test262/built-ins/TypedArrayConstructors/internals/Set/detached-buffer.js
skip script test262/built-ins/TypedArrayConstructors/internals/Set/tonumber-value-detached-buffer.js
# https://bugzilla.mozilla.org/show_bug.cgi?id=1129202
-skip script test262/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/key-is-greater-than-last-index.js
-skip script test262/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/key-is-lower-than-zero.js
-skip script test262/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/key-is-minus-zero.js
skip script test262/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/key-is-not-canonical-index.js
skip script test262/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/key-is-not-integer.js
skip script test262/built-ins/TypedArrayConstructors/internals/Get/key-is-not-canonical-index.js
skip script test262/built-ins/TypedArrayConstructors/internals/Get/key-is-not-integer.js
skip script test262/built-ins/TypedArrayConstructors/internals/GetOwnProperty/key-is-not-canonical-index.js
skip script test262/built-ins/TypedArrayConstructors/internals/HasProperty/key-is-not-canonical-index.js
skip script test262/built-ins/TypedArrayConstructors/internals/HasProperty/key-is-not-integer.js
-skip script test262/built-ins/TypedArrayConstructors/internals/Set/key-is-minus-zero.js
skip script test262/built-ins/TypedArrayConstructors/internals/Set/key-is-not-canonical-index.js
skip script test262/built-ins/TypedArrayConstructors/internals/Set/key-is-not-integer.js
-skip script test262/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds.js
skip script test262/built-ins/TypedArrayConstructors/internals/Set/tonumber-value-throws.js
# https://bugzilla.mozilla.org/show_bug.cgi?id=1317405
skip script test262/language/computed-property-names/class/static/method-number.js
skip script test262/language/computed-property-names/class/static/method-string.js
skip script test262/language/computed-property-names/class/static/method-symbol.js
# https://bugzilla.mozilla.org/show_bug.cgi?id=1286997
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -1928,17 +1928,17 @@ DefineNonexistentProperty(JSContext* cx,
// 9.4.5.3 step 3. Indexed properties of typed arrays are special.
uint64_t index;
if (IsTypedArrayIndex(id, &index)) {
// This method is only called for non-existent properties, which
// means any absent indexed property must be out of range.
MOZ_ASSERT(index >= obj->as<TypedArrayObject>().length());
// We (wrongly) ignore out of range defines.
- return result.succeed();
+ return result.failSoft(JSMSG_BAD_INDEX);
}
} else if (obj->is<ArgumentsObject>()) {
// If this method is called with either |length| or |@@iterator|, the
// property was previously deleted and hence should already be marked
// as overridden.
MOZ_ASSERT_IF(id == NameToId(cx->names().length),
obj->as<ArgumentsObject>().hasOverriddenLength());
MOZ_ASSERT_IF(JSID_IS_SYMBOL(id) && JSID_TO_SYMBOL(id) == cx->wellKnownSymbols().iterator,
@@ -2635,19 +2635,22 @@ SetDenseOrTypedArrayElement(JSContext* c
double d;
if (!ToNumber(cx, v, &d))
return false;
// Silently do nothing for out-of-bounds sets, for consistency with
// current behavior. (ES6 currently says to throw for this in
// strict mode code, so we may eventually need to change.)
uint32_t len = obj->as<TypedArrayObject>().length();
- if (index < len)
+ if (index < len) {
TypedArrayObject::setElement(obj->as<TypedArrayObject>(), index, d);
- return result.succeed();
+ return result.succeed();
+ }
+
+ return result.failSoft(JSMSG_BAD_INDEX);
}
if (WouldDefinePastNonwritableLength(obj, index))
return result.fail(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
if (!obj->maybeCopyElementsForWrite(cx))
return false;
--- a/js/src/vm/Realm.cpp
+++ b/js/src/vm/Realm.cpp
@@ -1044,16 +1044,25 @@ JS::SetRealmNameCallback(JSContext* cx,
}
JS_PUBLIC_API(JSObject*)
JS::GetRealmGlobalOrNull(Handle<JS::Realm*> realm)
{
return realm->maybeGlobal();
}
+JS_PUBLIC_API(bool)
+JS::InitRealmStandardClasses(JSContext* cx)
+{
+ MOZ_ASSERT(!cx->zone()->isAtomsZone());
+ AssertHeapIsIdle();
+ CHECK_REQUEST(cx);
+ return GlobalObject::initStandardClasses(cx, cx->global());
+}
+
JS_PUBLIC_API(JSObject*)
JS::GetRealmObjectPrototype(JSContext* cx)
{
CHECK_REQUEST(cx);
return GlobalObject::getOrCreateObjectPrototype(cx, cx->global());
}
JS_PUBLIC_API(JSObject*)
--- a/js/src/vm/Scope.cpp
+++ b/js/src/vm/Scope.cpp
@@ -1,16 +1,19 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 "vm/Scope.h"
+#include <memory>
+#include <new>
+
#include "builtin/ModuleObject.h"
#include "gc/Allocator.h"
#include "gc/FreeOp.h"
#include "util/StringBuffer.h"
#include "vm/EnvironmentObject.h"
#include "vm/JSScript.h"
#include "wasm/WasmInstance.h"
@@ -138,42 +141,34 @@ CreateEnvironmentShape(JSContext* cx, Bi
}
template <typename ConcreteScope>
static UniquePtr<typename ConcreteScope::Data>
CopyScopeData(JSContext* cx, Handle<typename ConcreteScope::Data*> data)
{
// Make sure the binding names are marked in the context's zone, if we are
// copying data from another zone.
- BindingName* names = nullptr;
- uint32_t length = 0;
- ConcreteScope::getDataNamesAndLength(data, &names, &length);
+ BindingName* names = data->trailingNames.start();
+ uint32_t length = data->length;
for (size_t i = 0; i < length; i++) {
if (JSAtom* name = names[i].name())
cx->markAtom(name);
}
- size_t dataSize = ConcreteScope::sizeOfData(data->length);
- size_t headerSize = sizeof(typename ConcreteScope::Data);
- MOZ_ASSERT(dataSize >= headerSize);
- size_t extraSize = dataSize - headerSize;
-
- uint8_t* copyBytes = cx->zone()->pod_malloc<uint8_t>(dataSize);
- if (!copyBytes) {
+ size_t size = SizeOfData<typename ConcreteScope::Data>(data->length);
+ void* bytes = cx->zone()->pod_malloc<char>(size);
+ if (!bytes) {
ReportOutOfMemory(cx);
return nullptr;
}
- auto dataCopy = reinterpret_cast<typename ConcreteScope::Data*>(copyBytes);
- new (dataCopy) typename ConcreteScope::Data(*data);
+ auto* dataCopy = new (bytes) typename ConcreteScope::Data(*data);
- uint8_t* extra = reinterpret_cast<uint8_t*>(data.get()) + headerSize;
- uint8_t* extraCopy = copyBytes + headerSize;
+ std::uninitialized_copy_n(names, length, dataCopy->trailingNames.start());
- mozilla::PodCopy<uint8_t>(extraCopy, extra, extraSize);
return UniquePtr<typename ConcreteScope::Data>(dataCopy);
}
template <typename ConcreteScope>
static bool
PrepareScopeData(JSContext* cx, BindingIter& bi, Handle<UniquePtr<typename ConcreteScope::Data>> data,
const Class* cls, uint32_t baseShapeFlags, MutableHandleShape envShape)
{
@@ -198,17 +193,18 @@ PrepareScopeData(JSContext* cx, BindingI
return true;
}
template <typename ConcreteScope>
static UniquePtr<typename ConcreteScope::Data>
NewEmptyScopeData(JSContext* cx, uint32_t length = 0)
{
- uint8_t* bytes = cx->zone()->pod_malloc<uint8_t>(ConcreteScope::sizeOfData(length));
+ size_t dataSize = SizeOfData<typename ConcreteScope::Data>(length);
+ uint8_t* bytes = cx->zone()->pod_malloc<uint8_t>(dataSize);
if (!bytes)
ReportOutOfMemory(cx);
auto data = reinterpret_cast<typename ConcreteScope::Data*>(bytes);
if (data)
new (data) typename ConcreteScope::Data(length);
return UniquePtr<typename ConcreteScope::Data>(data);
}
--- a/js/src/vm/Scope.h
+++ b/js/src/vm/Scope.h
@@ -3,18 +3,21 @@
* 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 vm_Scope_h
#define vm_Scope_h
#include "mozilla/Maybe.h"
+#include "mozilla/TypeTraits.h"
#include "mozilla/Variant.h"
+#include <stddef.h>
+
#include "jsutil.h"
#include "gc/DeletePolicy.h"
#include "gc/Heap.h"
#include "gc/Policy.h"
#include "js/UbiNode.h"
#include "js/UniquePtr.h"
#include "vm/BytecodeUtil.h"
@@ -399,16 +402,30 @@ class Scope : public js::gc::TenuredCell
void traceChildren(JSTracer* trc);
void finalize(FreeOp* fop);
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
void dump();
};
+/** Empty base class for scope Data classes to inherit from. */
+class BaseScopeData
+{};
+
+template<class Data>
+inline size_t
+SizeOfData(uint32_t numBindings)
+{
+ static_assert(mozilla::IsBaseOf<BaseScopeData, Data>::value,
+ "Data must be the correct sort of data, i.e. it must "
+ "inherit from BaseScopeData");
+ return sizeof(Data) + (numBindings ? numBindings - 1 : 0) * sizeof(BindingName);
+}
+
//
// A lexical scope that holds let and const bindings. There are 4 kinds of
// LexicalScopes.
//
// Lexical
// A plain lexical scope.
//
// SimpleCatch
@@ -428,17 +445,17 @@ class Scope : public js::gc::TenuredCell
class LexicalScope : public Scope
{
friend class Scope;
friend class BindingIter;
public:
// Data is public because it is created by the frontend. See
// Parser<FullParseHandler>::newLexicalScopeData.
- struct Data
+ struct Data : BaseScopeData
{
// Bindings are sorted by kind in both frames and environments.
//
// lets - [0, constStart)
// consts - [constStart, length)
uint32_t constStart = 0;
uint32_t length = 0;
@@ -451,25 +468,16 @@ class LexicalScope : public Scope
TrailingNamesArray trailingNames;
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
Data() = delete;
void trace(JSTracer* trc);
};
- static size_t sizeOfData(uint32_t length) {
- return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
- }
-
- static void getDataNamesAndLength(Data* data, BindingName** names, uint32_t* length) {
- *names = data->trailingNames.start();
- *length = data->length;
- }
-
static LexicalScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data,
uint32_t firstFrameSlot, HandleScope enclosing);
template <XDRMode mode>
static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
MutableHandleScope scope);
private:
@@ -534,17 +542,17 @@ class FunctionScope : public Scope
friend class BindingIter;
friend class PositionalFormalParameterIter;
friend class Scope;
static const ScopeKind classScopeKind_ = ScopeKind::Function;
public:
// Data is public because it is created by the
// frontend. See Parser<FullParseHandler>::newFunctionScopeData.
- struct Data
+ struct Data : BaseScopeData
{
// The canonical function of the scope, as during a scope walk we
// often query properties of the JSFunction (e.g., is the function an
// arrow).
GCPtrFunction canonicalFunction = {};
// If parameter expressions are present, parameters act like lexical
// bindings.
@@ -577,25 +585,16 @@ class FunctionScope : public Scope
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
Data() = delete;
void trace(JSTracer* trc);
Zone* zone() const;
};
- static size_t sizeOfData(uint32_t length) {
- return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
- }
-
- static void getDataNamesAndLength(Data* data, BindingName** names, uint32_t* length) {
- *names = data->trailingNames.start();
- *length = data->length;
- }
-
static FunctionScope* create(JSContext* cx, Handle<Data*> data,
bool hasParameterExprs, bool needsEnvironment,
HandleFunction fun, HandleScope enclosing);
static FunctionScope* clone(JSContext* cx, Handle<FunctionScope*> scope, HandleFunction fun,
HandleScope enclosing);
template <XDRMode mode>
@@ -662,17 +661,17 @@ class VarScope : public Scope
{
friend class GCMarker;
friend class BindingIter;
friend class Scope;
public:
// Data is public because it is created by the
// frontend. See Parser<FullParseHandler>::newVarScopeData.
- struct Data
+ struct Data : BaseScopeData
{
// All bindings are vars.
uint32_t length = 0;
// Frame slots [firstFrameSlot(), nextFrameSlot) are live when this is
// the innermost scope.
uint32_t nextFrameSlot = 0;
@@ -681,25 +680,16 @@ class VarScope : public Scope
TrailingNamesArray trailingNames;
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
Data() = delete;
void trace(JSTracer* trc);
};
- static size_t sizeOfData(uint32_t length) {
- return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
- }
-
- static void getDataNamesAndLength(Data* data, BindingName** names, uint32_t* length) {
- *names = data->trailingNames.start();
- *length = data->length;
- }
-
static VarScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data,
uint32_t firstFrameSlot, bool needsEnvironment,
HandleScope enclosing);
template <XDRMode mode>
static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
MutableHandleScope scope);
@@ -755,17 +745,17 @@ Scope::is<VarScope>() const
class GlobalScope : public Scope
{
friend class Scope;
friend class BindingIter;
public:
// Data is public because it is created by the frontend. See
// Parser<FullParseHandler>::newGlobalScopeData.
- struct Data
+ struct Data : BaseScopeData
{
// Bindings are sorted by kind.
// `vars` includes top-level functions which is distinguished by a bit
// on the BindingName.
//
// vars - [0, letStart)
// lets - [letStart, constStart)
// consts - [constStart, length)
@@ -778,25 +768,16 @@ class GlobalScope : public Scope
TrailingNamesArray trailingNames;
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
Data() = delete;
void trace(JSTracer* trc);
};
- static size_t sizeOfData(uint32_t length) {
- return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
- }
-
- static void getDataNamesAndLength(Data* data, BindingName** names, uint32_t* length) {
- *names = data->trailingNames.start();
- *length = data->length;
- }
-
static GlobalScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data);
static GlobalScope* createEmpty(JSContext* cx, ScopeKind kind) {
return create(cx, kind, nullptr);
}
static GlobalScope* clone(JSContext* cx, Handle<GlobalScope*> scope, ScopeKind kind);
@@ -860,17 +841,17 @@ class WithScope : public Scope
class EvalScope : public Scope
{
friend class Scope;
friend class BindingIter;
public:
// Data is public because it is created by the frontend. See
// Parser<FullParseHandler>::newEvalScopeData.
- struct Data
+ struct Data : BaseScopeData
{
// All bindings in an eval script are 'var' bindings. The implicit
// lexical scope around the eval is present regardless of strictness
// and is its own LexicalScope.
// `vars` includes top-level functions which is distinguished by a bit
// on the BindingName.
//
// vars - [0, length)
@@ -886,25 +867,16 @@ class EvalScope : public Scope
TrailingNamesArray trailingNames;
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
Data() = delete;
void trace(JSTracer* trc);
};
- static size_t sizeOfData(uint32_t length) {
- return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
- }
-
- static void getDataNamesAndLength(Data* data, BindingName** names, uint32_t* length) {
- *names = data->trailingNames.start();
- *length = data->length;
- }
-
static EvalScope* create(JSContext* cx, ScopeKind kind, Handle<Data*> data,
HandleScope enclosing);
template <XDRMode mode>
static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing,
MutableHandleScope scope);
private:
@@ -965,17 +937,17 @@ class ModuleScope : public Scope
friend class GCMarker;
friend class BindingIter;
friend class Scope;
static const ScopeKind classScopeKind_ = ScopeKind::Module;
public:
// Data is public because it is created by the frontend. See
// Parser<FullParseHandler>::newModuleScopeData.
- struct Data
+ struct Data : BaseScopeData
{
// The module of the scope.
GCPtr<ModuleObject*> module = {};
// Bindings are sorted by kind.
//
// imports - [0, varStart)
// vars - [varStart, letStart)
@@ -996,25 +968,16 @@ class ModuleScope : public Scope
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
Data() = delete;
void trace(JSTracer* trc);
Zone* zone() const;
};
- static size_t sizeOfData(uint32_t length) {
- return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
- }
-
- static void getDataNamesAndLength(Data* data, BindingName** names, uint32_t* length) {
- *names = data->trailingNames.start();
- *length = data->length;
- }
-
static ModuleScope* create(JSContext* cx, Handle<Data*> data,
Handle<ModuleObject*> module, HandleScope enclosing);
private:
static ModuleScope* createWithData(JSContext* cx, MutableHandle<UniquePtr<Data>> data,
Handle<ModuleObject*> module, HandleScope enclosing);
Data& data() {
@@ -1041,17 +1004,17 @@ class ModuleScope : public Scope
class WasmInstanceScope : public Scope
{
friend class BindingIter;
friend class Scope;
static const ScopeKind classScopeKind_ = ScopeKind::WasmInstance;
public:
- struct Data
+ struct Data : BaseScopeData
{
uint32_t memoriesStart = 0;
uint32_t globalsStart = 0;
uint32_t length = 0;
uint32_t nextFrameSlot = 0;
// The wasm instance of the scope.
GCPtr<WasmInstanceObject*> instance = {};
@@ -1061,20 +1024,16 @@ class WasmInstanceScope : public Scope
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
Data() = delete;
void trace(JSTracer* trc);
};
static WasmInstanceScope* create(JSContext* cx, WasmInstanceObject* instance);
- static size_t sizeOfData(uint32_t length) {
- return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
- }
-
private:
Data& data() {
return *reinterpret_cast<Data*>(data_);
}
const Data& data() const {
return *reinterpret_cast<Data*>(data_);
}
@@ -1104,36 +1063,32 @@ class WasmInstanceScope : public Scope
//
class WasmFunctionScope : public Scope
{
friend class BindingIter;
friend class Scope;
static const ScopeKind classScopeKind_ = ScopeKind::WasmFunction;
public:
- struct Data
+ struct Data : BaseScopeData
{
uint32_t length = 0;
uint32_t nextFrameSlot = 0;
uint32_t funcIndex = 0;
TrailingNamesArray trailingNames;
explicit Data(size_t nameCount) : trailingNames(nameCount) {}
Data() = delete;
void trace(JSTracer* trc);
};
static WasmFunctionScope* create(JSContext* cx, HandleScope enclosing, uint32_t funcIndex);
- static size_t sizeOfData(uint32_t length) {
- return sizeof(Data) + (length ? length - 1 : 0) * sizeof(BindingName);
- }
-
private:
Data& data() {
return *reinterpret_cast<Data*>(data_);
}
const Data& data() const {
return *reinterpret_cast<Data*>(data_);
}
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -645,17 +645,17 @@ intrinsic_DefineProperty(JSContext* cx,
ObjectOpResult result;
if (!DefineProperty(cx, obj, id, desc, result))
return false;
bool strict = args[5].toBoolean();
if (strict && !result.checkStrict(cx, obj, id))
return false;
- args.rval().setBoolean(bool(result));
+ args.rval().setBoolean(result.reallyOk());
return true;
}
static bool
intrinsic_ObjectHasPrototype(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 2);
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -2223,18 +2223,21 @@ js::DefineTypedArrayElement(JSContext* c
// These are all substeps of 3.b.
// Steps i-iii are handled by the caller.
// Steps iv-v.
// We (wrongly) ignore out of range defines with a value.
uint32_t length = obj->as<TypedArrayObject>().length();
- if (index >= length)
- return result.succeed();
+ if (index >= length) {
+ if (obj->as<TypedArrayObject>().hasDetachedBuffer())
+ return result.failSoft(JSMSG_TYPED_ARRAY_DETACHED);
+ return result.failSoft(JSMSG_BAD_INDEX);
+ }
// Step vi.
if (desc.isAccessorDescriptor())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step vii.
if (desc.hasConfigurable() && desc.configurable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1129,17 +1129,17 @@ xpc::CreateSandboxObject(JSContext* cx,
{
JSAutoRealm ar(cx, sandbox);
// This creates a SandboxPrivate and passes ownership of it to |sandbox|.
SandboxPrivate::Create(principal, sandbox);
// Ensure |Object.prototype| is instantiated before prototype-
// splicing below.
- if (!JS_GetObjectPrototype(cx, sandbox))
+ if (!JS::GetRealmObjectPrototype(cx))
return NS_ERROR_XPC_UNEXPECTED;
if (options.proto) {
bool ok = JS_WrapObject(cx, &options.proto);
if (!ok)
return NS_ERROR_XPC_UNEXPECTED;
// Now check what sort of thing we've got in |proto|, and figure out
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -186,17 +186,17 @@ XPCWrappedNative::WrapNewGlobal(xpcObjec
return NS_ERROR_FAILURE;
XPCWrappedNativeScope* scope = RealmPrivate::Get(global)->scope;
// Immediately enter the global's realm, so that everything else we
// create ends up there.
JSAutoRealm ar(cx, global);
// If requested, initialize the standard classes on the global.
- if (initStandardClasses && ! JS_InitStandardClasses(cx, global))
+ if (initStandardClasses && !JS::InitRealmStandardClasses(cx))
return NS_ERROR_FAILURE;
// Make a proto.
XPCWrappedNativeProto* proto =
XPCWrappedNativeProto::GetNewOrUsed(scope,
nativeHelper.GetClassInfo(),
scrProto);
if (!proto)
@@ -622,23 +622,19 @@ XPCWrappedNative::Init(nsIXPCScriptable*
!!(jsclazz->flags & JSCLASS_IS_GLOBAL));
MOZ_ASSERT(jsclazz &&
jsclazz->name &&
jsclazz->flags &&
jsclazz->getResolve() &&
jsclazz->hasFinalize(), "bad class");
- // XXXbz JS_GetObjectPrototype wants an object, even though it then asserts
- // that this object is same-compartment with cx, which means it could just
- // use the cx global...
- RootedObject global(cx, CurrentGlobalOrNull(cx));
RootedObject protoJSObject(cx, HasProto() ?
GetProto()->GetJSProtoObject() :
- JS_GetObjectPrototype(cx, global));
+ JS::GetRealmObjectPrototype(cx));
if (!protoJSObject) {
return false;
}
mFlatJSObject = JS_NewObjectWithGivenProto(cx, jsclazz, protoJSObject);
if (!mFlatJSObject) {
mFlatJSObject.unsetFlags(FLAT_JS_OBJECT_VALID);
return false;
--- a/js/xpconnect/src/XPCWrappedNativeProto.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeProto.cpp
@@ -50,18 +50,17 @@ XPCWrappedNativeProto::~XPCWrappedNative
}
bool
XPCWrappedNativeProto::Init(nsIXPCScriptable* scriptable)
{
AutoJSContext cx;
mScriptable = scriptable;
- JS::RootedObject global(cx, mScope->GetGlobalJSObject());
- JS::RootedObject proto(cx, JS_GetObjectPrototype(cx, global));
+ JS::RootedObject proto(cx, JS::GetRealmObjectPrototype(cx));
mJSProtoObject = JS_NewObjectWithUniqueType(cx, js::Jsvalify(&XPC_WN_Proto_JSClass),
proto);
bool success = !!mJSProtoObject;
if (success) {
JS_SetPrivate(mJSProtoObject, this);
}
--- a/js/xpconnect/tests/chrome/test_xrayToJS.xul
+++ b/js/xpconnect/tests/chrome/test_xrayToJS.xul
@@ -196,20 +196,17 @@ https://bugzilla.mozilla.org/show_bug.cg
"preventExtensions", "freeze", "isFrozen", "seal",
"isSealed", "assign", "getPrototypeOf", "values",
"entries", "isExtensible"])
gPrototypeProperties['Array'] =
["length", "toSource", "toString", "toLocaleString", "join", "reverse", "sort", "push",
"pop", "shift", "unshift", "splice", "concat", "slice", "lastIndexOf", "indexOf",
"includes", "forEach", "map", "reduce", "reduceRight", "filter", "some", "every", "find",
"findIndex", "copyWithin", "fill", Symbol.iterator, Symbol.unscopables, "entries", "keys",
- "values", "constructor"];
- if (isNightlyBuild) {
- gPrototypeProperties['Array'].push("flat", "flatMap");
- }
+ "values", "constructor", "flat", "flatMap"];
gConstructorProperties['Array'] =
constructorProps(["join", "reverse", "sort", "push", "pop", "shift",
"unshift", "splice", "concat", "slice", "isArray",
"lastIndexOf", "indexOf", "forEach", "map", "filter",
"every", "some", "reduce", "reduceRight", "from", "of",
Symbol.species]);
for (var c of typedArrayClasses) {
gPrototypeProperties[c] = ["constructor", "BYTES_PER_ELEMENT"];
--- a/layout/forms/test/mochitest.ini
+++ b/layout/forms/test/mochitest.ini
@@ -50,17 +50,17 @@ skip-if = toolkit == 'android' || e10s #
# Bug 1023472 - Fails when pushed into a different chunk on Android
skip-if = toolkit == 'android'
[test_bug957562.html]
[test_bug960277.html]
[test_select_key_navigation_bug961363.html]
skip-if = toolkit == 'android' # Bug 1021644 - Fails when pushed into a different chunk on Android
[test_bug1111995.html]
[test_bug1301290.html]
-skip-if = buildapp == 'mulet' || toolkit == 'android'
+skip-if = toolkit == 'android'
[test_bug1305282.html]
[test_listcontrol_search.html]
skip-if = toolkit == 'android' #select elements don't use an in-page popup on Android
[test_select_prevent_default.html]
[test_select_vertical.html]
skip-if = e10s || toolkit == 'android' # Bug 1170129 - vertical <select> popup not implemented for e10s # <select> elements don't use an in-page popup on Android
[test_textarea_resize.html]
skip-if = toolkit == 'android'
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -475,16 +475,24 @@ public:
VideoInfo::Rotation rotationDeg = element->RotationDegrees();
IntSize scaleHint(static_cast<int32_t>(destGFXRect.Width()),
static_cast<int32_t>(destGFXRect.Height()));
// scaleHint is set regardless of rotation, so swap w/h if needed.
SwapScaleWidthHeightForRotation(scaleHint, rotationDeg);
container->SetScaleHint(scaleHint);
+ Matrix transformHint;
+ if (rotationDeg != VideoInfo::Rotation::kDegree_0) {
+ transformHint = ComputeRotationMatrix(destGFXRect.Width(),
+ destGFXRect.Height(),
+ rotationDeg);
+ }
+ container->SetTransformHint(transformHint);
+
// If the image container is empty, we don't want to fallback. Any other
// failure will be due to resource constraints and fallback is unlikely to
// help us. Hence we can ignore the return value from PushImage.
LayoutDeviceRect rect(destGFXRect.x, destGFXRect.y, destGFXRect.width, destGFXRect.height);
aManager->CommandBuilder().PushImage(this, container, aBuilder, aResources, aSc, rect);
return true;
}
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -455,18 +455,20 @@ public:
}
private:
RefPtr<gfxFont> mFont;
FontFamilyName mFontFamilyName;
uint32_t mGlyphID;
explicit nsOpenTypeTable(gfxFont* aFont)
- : mFont(aFont),
- mFontFamilyName(aFont->GetFontEntry()->FamilyName(), eUnquotedName) {
+ : mFont(aFont)
+ , mFontFamilyName(aFont->GetFontEntry()->FamilyName(), eUnquotedName)
+ , mGlyphID(0)
+ {
MOZ_COUNT_CTOR(nsOpenTypeTable);
}
void UpdateCache(DrawTarget* aDrawTarget,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar);
};
--- a/layout/mathml/nsMathMLChar.h
+++ b/layout/mathml/nsMathMLChar.h
@@ -87,17 +87,19 @@ struct nsGlyphCode {
// symbols).
class nsMathMLChar
{
public:
typedef gfxTextRun::Range Range;
typedef mozilla::gfx::DrawTarget DrawTarget;
// constructor and destructor
- nsMathMLChar() {
+ nsMathMLChar()
+ : mDirection(NS_STRETCH_DIRECTION_DEFAULT)
+ {
MOZ_COUNT_CTOR(nsMathMLChar);
mComputedStyle = nullptr;
mUnscaledAscent = 0;
mScaleX = mScaleY = 1.0;
mDraw = DRAW_NORMAL;
mMirrored = false;
}
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -1158,23 +1158,24 @@ GetInterFrameSpacing(int32_t a
static nscoord GetThinSpace(const nsStyleFont* aStyleFont)
{
return NSToCoordRound(float(aStyleFont->mFont.size)*float(3) / float(18));
}
class nsMathMLContainerFrame::RowChildFrameIterator {
public:
- explicit RowChildFrameIterator(nsMathMLContainerFrame* aParentFrame) :
- mParentFrame(aParentFrame),
- mReflowOutput(aParentFrame->GetWritingMode()),
- mX(0),
- mCarrySpace(0),
- mFromFrameType(eMathMLFrameType_UNKNOWN),
- mRTL(aParentFrame->StyleVisibility()->mDirection)
+ explicit RowChildFrameIterator(nsMathMLContainerFrame* aParentFrame)
+ : mParentFrame(aParentFrame)
+ , mReflowOutput(aParentFrame->GetWritingMode())
+ , mX(0)
+ , mChildFrameType(eMathMLFrameType_UNKNOWN)
+ , mCarrySpace(0)
+ , mFromFrameType(eMathMLFrameType_UNKNOWN)
+ , mRTL(aParentFrame->StyleVisibility()->mDirection)
{
if (!mRTL) {
mChildFrame = aParentFrame->mFrames.FirstChild();
} else {
mChildFrame = aParentFrame->mFrames.LastChild();
}
if (!mChildFrame)
--- a/mfbt/double-conversion/GIT-INFO
+++ b/mfbt/double-conversion/GIT-INFO
@@ -1,37 +1,9 @@
-commit 1b5fa314800a0e68e2b5d00d17e87a5b1fa3ac5d
-Author: Shane <sffc@sffc1.com>
-Date: Fri Mar 2 01:26:53 2018 -0800
-
- Clarify output charset in DoubleToAscii documentation (#61)
-
- * Clarify output charset in DoubleToAscii documentation
-
- * Fixing typo in charset docs.
+commit 9a8e518bedcf171d99eb1c00eef4beb1ecc20a4b
+Merge: ae9ad90 da420c3
+Author: Florian Loitsch <floitsch@google.com>
+Date: Tue May 22 11:24:13 2018 +0200
-diff --git a/double-conversion/double-conversion.h b/double-conversion/double-conversion.h
-index 9978bde..1ccd7fc 100644
---- a/double-conversion/double-conversion.h
-+++ b/double-conversion/double-conversion.h
-@@ -294,13 +294,18 @@ class DoubleToStringConverter {
- // should be at least kBase10MaximalLength + 1 characters long.
- static const int kBase10MaximalLength = 17;
-
-- // Converts the given double 'v' to ascii. 'v' must not be NaN, +Infinity, or
-- // -Infinity. In SHORTEST_SINGLE-mode this restriction also applies to 'v'
-- // after it has been casted to a single-precision float. That is, in this
-- // mode static_cast<float>(v) must not be NaN, +Infinity or -Infinity.
-+ // Converts the given double 'v' to digit characters. 'v' must not be NaN,
-+ // +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also
-+ // applies to 'v' after it has been casted to a single-precision float. That
-+ // is, in this mode static_cast<float>(v) must not be NaN, +Infinity or
-+ // -Infinity.
- //
- // The result should be interpreted as buffer * 10^(point-length).
- //
-+ // The digits are written to the buffer in the platform's charset, which is
-+ // often UTF-8 (with ASCII-range digits) but may be another charset, such
-+ // as EBCDIC.
-+ //
- // The output depends on the given mode:
- // - SHORTEST: produce the least amount of digits for which the internal
- // identity requirement is still satisfied. If the digits are printed
+ Merge pull request #68 from floitschG/static_size_assert
+
+ Use `static_assert` with newer compilers.
+
--- a/mfbt/double-conversion/double-conversion/double-conversion.cc
+++ b/mfbt/double-conversion/double-conversion/double-conversion.cc
@@ -885,39 +885,43 @@ double StringToDoubleConverter::StringTo
// Otherwise there are no digits in the string.
return junk_string_value_;
}
// Parse exponential part.
if (*current == 'e' || *current == 'E') {
if (octal && !allow_trailing_junk) return junk_string_value_;
if (octal) goto parsing_done;
+ Iterator junk_begin = current;
++current;
if (current == end) {
if (allow_trailing_junk) {
+ current = junk_begin;
goto parsing_done;
} else {
return junk_string_value_;
}
}
char exponen_sign = '+';
if (*current == '+' || *current == '-') {
exponen_sign = static_cast<char>(*current);
++current;
if (current == end) {
if (allow_trailing_junk) {
+ current = junk_begin;
goto parsing_done;
} else {
return junk_string_value_;
}
}
}
if (current == end || *current < '0' || *current > '9') {
if (allow_trailing_junk) {
+ current = junk_begin;
goto parsing_done;
} else {
return junk_string_value_;
}
}
const int max_exponent = INT_MAX / 2;
ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
--- a/mfbt/double-conversion/double-conversion/strtod.cc
+++ b/mfbt/double-conversion/double-conversion/strtod.cc
@@ -467,28 +467,52 @@ double Strtod(Vector<const char> buffer,
} else if ((Double(guess).Significand() & 1) == 0) {
// Round towards even.
return guess;
} else {
return Double(guess).NextDouble();
}
}
+static float SanitizedDoubletof(double d) {
+ ASSERT(d >= 0.0);
+ // ASAN has a sanitize check that disallows casting doubles to floats if
+ // they are too big.
+ // https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks
+ // The behavior should be covered by IEEE 754, but some projects use this
+ // flag, so work around it.
+ float max_finite = 3.4028234663852885981170418348451692544e+38;
+ // The half-way point between the max-finite and infinity value.
+ // Since infinity has an even significand everything equal or greater than
+ // this value should become infinity.
+ double half_max_finite_infinity =
+ 3.40282356779733661637539395458142568448e+38;
+ if (d >= max_finite) {
+ if (d >= half_max_finite_infinity) {
+ return Single::Infinity();
+ } else {
+ return max_finite;
+ }
+ } else {
+ return static_cast<float>(d);
+ }
+}
+
float Strtof(Vector<const char> buffer, int exponent) {
char copy_buffer[kMaxSignificantDecimalDigits];
Vector<const char> trimmed;
int updated_exponent;
TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
&trimmed, &updated_exponent);
exponent = updated_exponent;
double double_guess;
bool is_correct = ComputeGuess(trimmed, exponent, &double_guess);
- float float_guess = static_cast<float>(double_guess);
+ float float_guess = SanitizedDoubletof(double_guess);
if (float_guess == double_guess) {
// This shortcut triggers for integer values.
return float_guess;
}
// We must catch double-rounding. Say the double has been rounded up, and is
// now a boundary of a float, and rounds up again. This is why we have to
// look at previous too.
@@ -501,40 +525,40 @@ float Strtof(Vector<const char> buffer,
// To do this we simply look at the neigbors of the correct result and see
// if they would round to the same float. If the guess is not correct we have
// to look at four values (since two different doubles could be the correct
// double).
double double_next = Double(double_guess).NextDouble();
double double_previous = Double(double_guess).PreviousDouble();
- float f1 = static_cast<float>(double_previous);
+ float f1 = SanitizedDoubletof(double_previous);
float f2 = float_guess;
- float f3 = static_cast<float>(double_next);
+ float f3 = SanitizedDoubletof(double_next);
float f4;
if (is_correct) {
f4 = f3;
} else {
double double_next2 = Double(double_next).NextDouble();
- f4 = static_cast<float>(double_next2);
+ f4 = SanitizedDoubletof(double_next2);
}
(void) f2; // Mark variable as used.
ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4);
// If the guess doesn't lie near a single-precision boundary we can simply
// return its float-value.
if (f1 == f4) {
return float_guess;
}
ASSERT((f1 != f2 && f2 == f3 && f3 == f4) ||
(f1 == f2 && f2 != f3 && f3 == f4) ||
(f1 == f2 && f2 == f3 && f3 != f4));
- // guess and next are the two possible canditates (in the same way that
+ // guess and next are the two possible candidates (in the same way that
// double_guess was the lower candidate for a double-precision guess).
float guess = f1;
float next = f4;
DiyFp upper_boundary;
if (guess == 0.0f) {
float min_float = 1e-45f;
upper_boundary = Double(static_cast<double>(min_float) / 2).AsDiyFp();
} else {
--- a/mfbt/double-conversion/double-conversion/utils.h
+++ b/mfbt/double-conversion/double-conversion/utils.h
@@ -74,35 +74,30 @@ inline void abort_noreturn() { MOZ_CRASH
defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
defined(__SH4__) || defined(__alpha__) || \
defined(_MIPS_ARCH_MIPS32R2) || \
defined(__AARCH64EL__) || defined(__aarch64__) || \
defined(__riscv)
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
-#elif defined(__mc68000__)
+#elif defined(__mc68000__) || \
+ defined(__pnacl__) || defined(__native_client__)
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
#if defined(_WIN32)
// Windows uses a 64bit wide floating point stack.
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
#else
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
#endif // _WIN32
#else
#error Target architecture was not detected as supported by Double-Conversion.
#endif
-#if defined(__GNUC__)
-#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
-#else
-#define DOUBLE_CONVERSION_UNUSED
-#endif
-
#if defined(_WIN32) && !defined(__MINGW32__)
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t; // NOLINT
typedef unsigned short uint16_t; // NOLINT
typedef int int32_t;
typedef unsigned int uint32_t;
@@ -319,18 +314,22 @@ class StringBuilder {
// the type-based aliasing rule. If you have checked that there is no breakage
// you can use BitCast to cast one pointer type to another. This confuses gcc
// enough that it can no longer see that you have cast one pointer type to
// another thus avoiding the warning.
template <class Dest, class Source>
inline Dest BitCast(const Source& source) {
// Compile time assertion: sizeof(Dest) == sizeof(Source)
// A compile error here means your Dest and Source have different sizes.
- DOUBLE_CONVERSION_UNUSED
- typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
+#if __cplusplus >= 201103L
+ static_assert(sizeof(Dest) == sizeof(Source),
+ "source and destination size mismatch");
+#else
+ typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
+#endif
Dest dest;
memmove(&dest, &source, sizeof(dest));
return dest;
}
template <class Dest, class Source>
inline Dest BitCast(Source* source) {
--- a/netwerk/base/ProxyAutoConfig.cpp
+++ b/netwerk/base/ProxyAutoConfig.cpp
@@ -660,17 +660,17 @@ private:
if (!mGlobal) {
JS_ClearPendingException(mContext);
return NS_ERROR_OUT_OF_MEMORY;
}
JS::Rooted<JSObject*> global(mContext, mGlobal);
JSAutoRealm ar(mContext, global);
AutoPACErrorReporter aper(mContext);
- if (!JS_InitStandardClasses(mContext, global)) {
+ if (!JS::InitRealmStandardClasses(mContext)) {
return NS_ERROR_FAILURE;
}
if (!JS_DefineFunctions(mContext, global, PACGlobalFunctions)) {
return NS_ERROR_FAILURE;
}
JS_FireOnNewGlobalObject(mContext, global);
--- a/netwerk/cookie/nsCookieService.h
+++ b/netwerk/cookie/nsCookieService.h
@@ -138,17 +138,21 @@ struct CookieDomainTuple
nsCookieKey key;
mozilla::UniquePtr<ConstCookie> cookie;
};
// encapsulates in-memory and on-disk DB states, so we can
// conveniently switch state when entering or exiting private browsing.
struct DBState final
{
- DBState() : cookieCount(0), cookieOldestTime(INT64_MAX), corruptFlag(OK)
+ DBState()
+ : cookieCount(0)
+ , cookieOldestTime(INT64_MAX)
+ , corruptFlag(OK)
+ , readListener(nullptr)
{
}
private:
// Private destructor, to discourage deletion outside of Release():
~DBState() = default;
public:
--- a/netwerk/dns/nsEffectiveTLDService.cpp
+++ b/netwerk/dns/nsEffectiveTLDService.cpp
@@ -341,8 +341,40 @@ bool
nsEffectiveTLDService::LookupForAdd(const nsACString& aHost, TLDCacheEntry** aEntry)
{
MOZ_ASSERT(NS_IsMainThread());
const uint32_t hash = HashString(aHost.BeginReading(), aHost.Length());
*aEntry = &mMruTable[hash % kTableSize];
return (*aEntry)->mHost == aHost;
}
+
+NS_IMETHODIMP
+nsEffectiveTLDService::HasRootDomain(const nsACString& aInput,
+ const nsACString& aHost,
+ bool* aResult)
+{
+ if (NS_WARN_IF(!aResult)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ *aResult = false;
+
+ // If the strings are the same, we obviously have a match.
+ if (aInput == aHost) {
+ *aResult = true;
+ return NS_OK;
+ }
+
+ // If aHost is not found, we know we do not have it as a root domain.
+ int32_t index = nsAutoCString(aInput).Find(aHost.BeginReading());
+ if (index == kNotFound) {
+ return NS_OK;
+ }
+
+ // Otherwise, we have aHost as our root domain iff the index of aHost is
+ // aHost.length subtracted from our length and (since we do not have an
+ // exact match) the character before the index is a dot or slash.
+ *aResult = index > 0 &&
+ (uint32_t)index == aInput.Length() - aHost.Length() &&
+ (aInput[index - 1] == '.' || aInput[index - 1] == '/');
+ return NS_OK;
+}
--- a/netwerk/dns/nsIEffectiveTLDService.idl
+++ b/netwerk/dns/nsIEffectiveTLDService.idl
@@ -116,10 +116,21 @@ interface nsIEffectiveTLDService : nsISu
* "bbc.co.uk" would throw NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS.
*
* @param aHost The host to be analyzed. Any additional parts (e.g. scheme,
* port, or path) will cause this method to throw. ASCII/ACE and
* UTF8 encodings are acceptable as input; normalization will
* be performed as specified in getBaseDomain().
*/
ACString getNextSubDomain(in AUTF8String aHost);
+
+ /**
+ * Returns true if the |aInput| in is part of the root domain of |aHost|.
+ * For example, if |aInput| is "www.mozilla.org", and we pass in
+ * "mozilla.org" as |aHost|, this will return true. It would return false
+ * the other way around.
+ *
+ * @param aInput The host to be analyzed.
+ * @param aHost The host to compare to.
+ */
+ bool hasRootDomain(in AUTF8String aInput, in AUTF8String aHost);
};
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -1542,16 +1542,27 @@ NS_IMETHODIMP HttpBaseChannel::SetTopLev
NS_IMETHODIMP
HttpBaseChannel::GetIsTrackingResource(bool* aIsTrackingResource)
{
*aIsTrackingResource = mIsTrackingResource;
return NS_OK;
}
NS_IMETHODIMP
+HttpBaseChannel::OverrideTrackingResource(bool aIsTracking)
+{
+ LOG(("HttpBaseChannel::OverrideTrackingResource(%d) %p "
+ "mIsTrackingResource=%d",
+ (int) aIsTracking, this, (int) mIsTrackingResource));
+
+ mIsTrackingResource = aIsTracking;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
HttpBaseChannel::GetTransferSize(uint64_t *aTransferSize)
{
*aTransferSize = mTransferSize;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetDecodedBodySize(uint64_t *aDecodedBodySize)
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -206,16 +206,17 @@ public:
NS_IMETHOD GetProtocolVersion(nsACString & aProtocolVersion) override;
NS_IMETHOD GetChannelId(uint64_t *aChannelId) override;
NS_IMETHOD SetChannelId(uint64_t aChannelId) override;
NS_IMETHOD GetTopLevelContentWindowId(uint64_t *aContentWindowId) override;
NS_IMETHOD SetTopLevelContentWindowId(uint64_t aContentWindowId) override;
NS_IMETHOD GetTopLevelOuterContentWindowId(uint64_t *aWindowId) override;
NS_IMETHOD SetTopLevelOuterContentWindowId(uint64_t aWindowId) override;
NS_IMETHOD GetIsTrackingResource(bool* aIsTrackingResource) override;
+ NS_IMETHOD OverrideTrackingResource(bool aIsTracking) override;
// nsIHttpChannelInternal
NS_IMETHOD GetDocumentURI(nsIURI **aDocumentURI) override;
NS_IMETHOD SetDocumentURI(nsIURI *aDocumentURI) override;
NS_IMETHOD GetRequestVersion(uint32_t *major, uint32_t *minor) override;
NS_IMETHOD GetResponseVersion(uint32_t *major, uint32_t *minor) override;
NS_IMETHOD SetCookie(const char *aCookieHeader) override;
NS_IMETHOD GetThirdPartyFlags(uint32_t *aForce) override;
--- a/netwerk/protocol/http/NullHttpChannel.cpp
+++ b/netwerk/protocol/http/NullHttpChannel.cpp
@@ -95,16 +95,22 @@ NullHttpChannel::SetTopLevelOuterContent
NS_IMETHODIMP
NullHttpChannel::GetIsTrackingResource(bool* aIsTrackingResource)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
+NullHttpChannel::OverrideTrackingResource(bool aIsTracking)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
NullHttpChannel::GetTransferSize(uint64_t *aTransferSize)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
NullHttpChannel::GetDecodedBodySize(uint64_t *aDecodedBodySize)
{
--- a/netwerk/protocol/http/nsIHttpChannel.idl
+++ b/netwerk/protocol/http/nsIHttpChannel.idl
@@ -478,16 +478,26 @@ interface nsIHttpChannel : nsIChannel
* Returns true if the channel has loaded a resource that is on the tracking
* protection list. This is only available if the
* privacy.trackingprotection.annotate_channels pref is set and its value
* should only be relied on after the channel has established a connection.
*/
[infallible] readonly attribute boolean isTrackingResource;
/**
+ * This method is used in order to override the tracking status of an HTTP
+ * channel. This should only be called by Gecko under certain circumstances
+ * when Gecko can guarantee that the channel classifier service will not be
+ * determining the tracking status of the channel.
+ *
+ * Please avoid calling this API if you're unsure whether you should be using it.
+ */
+ [noscript] void overrideTrackingResource(in boolean aIsTracking);
+
+ /**
* ID of the top-level outer content window. Identifies this channel's
* top-level window it comes from.
*
* NOTE: The setter of this attribute is currently for xpcshell test only.
* Don't alter it otherwise.
*/
[must_use] attribute uint64_t topLevelOuterContentWindowId;
--- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
+++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
@@ -832,16 +832,23 @@ nsViewSourceChannel::SetTopLevelOuterCon
NS_IMETHODIMP
nsViewSourceChannel::GetIsTrackingResource(bool* aIsTrackingResource)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetIsTrackingResource(aIsTrackingResource);
}
NS_IMETHODIMP
+nsViewSourceChannel::OverrideTrackingResource(bool aIsTracking)
+{
+ return !mHttpChannel ? NS_ERROR_NULL_POINTER :
+ mHttpChannel->OverrideTrackingResource(aIsTracking);
+}
+
+NS_IMETHODIMP
nsViewSourceChannel::GetRequestMethod(nsACString & aRequestMethod)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetRequestMethod(aRequestMethod);
}
NS_IMETHODIMP
nsViewSourceChannel::SetRequestMethod(const nsACString & aRequestMethod)
--- a/parser/htmlparser/CParserContext.cpp
+++ b/parser/htmlparser/CParserContext.cpp
@@ -2,43 +2,44 @@
/* vim: set ts=2 sw=2 et tw=80: */
/* 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 "nsAtom.h"
#include "CParserContext.h"
-#include "prenv.h"
+#include "prenv.h"
#include "nsIHTMLContentSink.h"
#include "nsHTMLTokenizer.h"
#include "nsMimeTypes.h"
#include "nsHTMLTokenizer.h"
CParserContext::CParserContext(CParserContext* aPrevContext,
- nsScanner* aScanner,
- void *aKey,
+ nsScanner* aScanner,
+ void *aKey,
eParserCommands aCommand,
- nsIRequestObserver* aListener,
- eAutoDetectResult aStatus,
+ nsIRequestObserver* aListener,
+ eAutoDetectResult aStatus,
bool aCopyUnused)
- : mListener(aListener),
- mKey(aKey),
- mPrevContext(aPrevContext),
- mScanner(aScanner),
- mDTDMode(eDTDMode_unknown),
- mStreamListenerState(eNone),
- mContextType(eCTNone),
- mAutoDetectStatus(aStatus),
- mParserCommand(aCommand),
- mMultipart(true),
- mCopyUnused(aCopyUnused)
-{
- MOZ_COUNT_CTOR(CParserContext);
-}
+ : mListener(aListener)
+ , mKey(aKey)
+ , mPrevContext(aPrevContext)
+ , mScanner(aScanner)
+ , mDTDMode(eDTDMode_unknown)
+ , mDocType(static_cast<eParserDocType>(0))
+ , mStreamListenerState(eNone)
+ , mContextType(eCTNone)
+ , mAutoDetectStatus(aStatus)
+ , mParserCommand(aCommand)
+ , mMultipart(true)
+ , mCopyUnused(aCopyUnused)
+{
+ MOZ_COUNT_CTOR(CParserContext);
+}
CParserContext::~CParserContext()
{
// It's ok to simply ingore the PrevContext.
MOZ_COUNT_DTOR(CParserContext);
}
void
--- a/parser/htmlparser/nsParser.cpp
+++ b/parser/htmlparser/nsParser.cpp
@@ -122,17 +122,18 @@ public:
};
//-------------- End ParseContinue Event Definition ------------------------
/**
* default constructor
*/
nsParser::nsParser()
- : mCharset(WINDOWS_1252_ENCODING)
+ : mParserContext(nullptr)
+ , mCharset(WINDOWS_1252_ENCODING)
{
Initialize(true);
}
nsParser::~nsParser()
{
Cleanup();
}
--- a/parser/htmlparser/nsScannerString.h
+++ b/parser/htmlparser/nsScannerString.h
@@ -96,18 +96,21 @@ class nsScannerBufferList
/**
* Position objects serve as lightweight pointers into a buffer list.
* The mPosition member must be contained with mBuffer->DataStart()
* and mBuffer->DataEnd().
*/
class Position
{
public:
-
- Position() {}
+ Position()
+ : mBuffer(nullptr)
+ , mPosition(nullptr)
+ {
+ }
Position( Buffer* buffer, char16_t* position )
: mBuffer(buffer)
, mPosition(position)
{}
inline
explicit Position( const nsScannerIterator& aIter );
--- a/taskcluster/docker/funsize-update-generator/Dockerfile
+++ b/taskcluster/docker/funsize-update-generator/Dockerfile
@@ -4,21 +4,27 @@ MAINTAINER Simon Fraser <sfraser@mozilla
# Required software
ENV DEBIAN_FRONTEND noninteractive
# Chain apt-get commands with apt-get clean in a single docker RUN
# to make sure that files are removed within a single docker layer
RUN apt-get update -q && \
apt-get install -yyq --no-install-recommends \
python3.6 python3-setuptools python3-cryptography libgetopt-simple-perl \
bzip2 clamav clamav-freshclam python3-requests python3-sh curl \
- python3-dev gcc liblzma-dev xz-utils jq libdpkg-perl && \
+ python3-dev gcc liblzma-dev xz-utils jq libdpkg-perl locales && \
apt-get clean
RUN useradd -d /home/worker -s /bin/bash -m worker
COPY requirements.txt /tmp/
+RUN locale-gen en_CA.UTF-8
+ENV LANG en_CA.UTF-8
+ENV LANGUAGE en_CA.UTF-8
+ENV LANG_ALL en_CA.UTF-8
+ENV LC_ALL en_CA.UTF-8
+
# Freshclam may be flaky, retry if it fails
RUN for i in 1 2 3 4 5; do freshclam --verbose && break || sleep 15; done
# python-pip installs a lot of dependencies increasing the size of an image
# drastically. Install it like this saves us almost 200M.
RUN bash -c "curl -L https://bootstrap.pypa.io/get-pip.py | python3"
RUN pip install -r /tmp/requirements.txt
--- a/taskcluster/docker/funsize-update-generator/README
+++ b/taskcluster/docker/funsize-update-generator/README
@@ -1,7 +1,8 @@
To run this locally for testing/development purposes:
1. Find a funsize generating task ID
2. make pull DOCKERIO_USERNAME=mozillareleases
-3. docker run -t -e SHA1_SIGNING_CERT='nightly_sha1' -e SHA384_SIGNING_CERT='nightly_sha384' -e TASK_ID=LD5HUGP5QNeQdFKNTTuyCg mozillareleases/funsize-update-generator /runme.sh
+3. docker run -t -e SHA1_SIGNING_CERT='nightly_sha1' -e SHA384_SIGNING_CERT='nightly_sha384' -e TASK_ID=I8RveHT_RbCsAptRg4OBCw mozillareleases/funsize-update-generator /runme.sh
+The TASK_ID should be a recent "partials" Task.
--- a/taskcluster/docker/funsize-update-generator/requirements.txt
+++ b/taskcluster/docker/funsize-update-generator/requirements.txt
@@ -1,44 +1,48 @@
-aiohttp==2.3.6
-arrow==0.12.0
+aiohttp==3.3.2
+arrow==0.12.1
asn1crypto==0.24.0
-async-timeout==2.0.0
-awscli==1.14.10
-backports.lzma==0.0.8
-botocore==1.8.14
-certifi==2017.11.5
-cffi==1.11.4
+async-timeout==3.0.0
+attrs==18.1.0
+awscli==1.15.36
+backports.lzma==0.0.11
+botocore==1.10.36
+certifi==2018.4.16
+cffi==1.11.5
chardet==3.0.4
click==6.7
-colorama==0.3.7
-construct==2.8.20
-cryptography==2.1.4
-datadog==0.17.0
-decorator==4.2.1
+colorama==0.3.9
+construct==2.9.45
+cryptography==2.2.2
+datadog==0.21.0
+decorator==4.3.0
defusedxml==0.5.0
+dictdiffer==0.7.1
docutils==0.14
frozendict==1.2
-idna==2.6
+idna==2.7
+idna-ssl==1.0.1
jmespath==0.9.3
+json-e==2.5.0
jsonschema==2.6.0
-mar==2.1.2
+mar==2.2.3
mohawk==0.3.4
-multidict==4.0.0
-pexpect==4.3.1
+multidict==4.3.1
+pexpect==4.6.0
ptyprocess==0.5.2
-pyasn1==0.4.2
+pyasn1==0.4.3
pycparser==2.18
-python-dateutil==2.6.1
-python-gnupg==0.4.1
+python-dateutil==2.7.3
+python-gnupg==0.4.2
PyYAML==3.12
redo==1.6
-requests==2.18.4
+requests==2.19.0
rsa==3.4.2
-s3transfer==0.1.12
-scriptworker==6.0.0
-simplejson==3.13.2
+s3transfer==0.1.13
+scriptworker==12.1.0
+simplejson==3.15.0
six==1.11.0
slugid==1.0.7
-taskcluster==2.1.3
-urllib3==1.22
-virtualenv==15.1.0
-yarl==1.0.0
+taskcluster==3.0.1
+urllib3==1.23
+virtualenv==16.0.0
+yarl==1.2.5
--- a/toolkit/components/cleardata/ClearDataService.js
+++ b/toolkit/components/cleardata/ClearDataService.js
@@ -13,16 +13,19 @@ XPCOMUtils.defineLazyModuleGetters(this,
OfflineAppCacheHelper: "resource://gre/modules/offlineAppCache.jsm",
ServiceWorkerCleanUp: "resource://gre/modules/ServiceWorkerCleanUp.jsm",
PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
});
XPCOMUtils.defineLazyServiceGetter(this, "sas",
"@mozilla.org/storage/activity-service;1",
"nsIStorageActivityService");
+XPCOMUtils.defineLazyServiceGetter(this, "eTLDService",
+ "@mozilla.org/network/effective-tld-service;1",
+ "nsIEffectiveTLDService");
// A Cleaner is an object with 3 methods. These methods must return a Promise
// object. Here a description of these methods:
// * deleteAll() - this method _must_ exist. When called, it deletes all the
// data owned by the cleaner.
// * deleteByPrincipal() - this method is implemented only if the cleaner knows
// how to delete data by nsIPrincipal. If not
// implemented, deleteByHost will be used instead.
@@ -183,17 +186,17 @@ const PluginDataCleaner = {
new Promise(aResolve => setTimeout(aResolve, 10000 /* 10 seconds */))
]);
},
};
const DownloadsCleaner = {
deleteByHost(aHost, aOriginAttributes) {
return Downloads.getList(Downloads.ALL).then(aList => {
- aList.removeFinished(aDownload => hasRootDomain(
+ aList.removeFinished(aDownload => eTLDService.hasRootDomain(
Services.io.newURI(aDownload.source.url).host, aHost));
});
},
deleteByRange(aFrom, aTo) {
// Convert microseconds back to milliseconds for date comparisons.
let rangeBeginMs = aFrom / 1000;
let rangeEndMs = aTo / 1000;
@@ -208,17 +211,17 @@ const DownloadsCleaner = {
return Downloads.getList(Downloads.ALL).then(aList => {
aList.removeFinished(null);
});
},
};
const PasswordsCleaner = {
deleteByHost(aHost, aOriginAttributes) {
- return this._deleteInternal(aLogin => hasRootDomain(aLogin.hostname, aHost));
+ return this._deleteInternal(aLogin => eTLDService.hasRootDomain(aLogin.hostname, aHost));
},
deleteAll() {
return this._deleteInternal(() => true);
},
_deleteInternal(aCb) {
return new Promise(aResolve => {
@@ -485,17 +488,17 @@ const AuthCacheCleaner = {
const PermissionsCleaner = {
deleteByHost(aHost, aOriginAttributes) {
return new Promise(aResolve => {
let enumerator = Services.perms.enumerator;
while (enumerator.hasMoreElements()) {
let perm = enumerator.getNext().QueryInterface(Ci.nsIPermission);
try {
- if (hasRootDomain(perm.principal.URI.host, aHost)) {
+ if (eTLDService.hasRootDomain(perm.principal.URI.host, aHost)) {
Services.perms.removePermission(perm);
}
} catch (ex) {
// Ignore entry
}
}
aResolve();
@@ -561,17 +564,17 @@ const SecuritySettingsCleaner = {
for (let type of [Ci.nsISiteSecurityService.HEADER_HSTS,
Ci.nsISiteSecurityService.HEADER_HPKP]) {
// Also remove HSTS/HPKP/OMS information for subdomains by enumerating
// the information in the site security service.
let enumerator = sss.enumerate(type);
while (enumerator.hasMoreElements()) {
let entry = enumerator.getNext();
let hostname = entry.QueryInterface(Ci.nsISiteSecurityState).hostname;
- if (hasRootDomain(hostname, aHost)) {
+ if (eTLDService.hasRootDomain(hostname, aHost)) {
// This uri is used as a key to remove the state.
let uri = Services.io.newURI("https://" + hostname);
sss.removeState(type, uri, 0, entry.originAttributes);
}
}
}
aResolve();
@@ -759,32 +762,8 @@ ClearDataService.prototype = Object.free
return aHelper(c.cleaner).catch(() => { resultFlags |= c.flag; });
});
Promise.all(promises).then(() => { aCallback.onDataDeleted(resultFlags); });
return Cr.NS_OK;
},
});
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ClearDataService]);
-
-/**
- * Returns true if the string passed in is part of the root domain of the
- * current string. For example, if this is "www.mozilla.org", and we pass in
- * "mozilla.org", this will return true. It would return false the other way
- * around.
- */
-function hasRootDomain(str, aDomain) {
- let index = str.indexOf(aDomain);
- // If aDomain is not found, we know we do not have it as a root domain.
- if (index == -1)
- return false;
-
- // If the strings are the same, we obviously have a match.
- if (str == aDomain)
- return true;
-
- // Otherwise, we have aDomain as our root domain iff the index of aDomain is
- // aDomain.length subtracted from our length and (since we do not have an
- // exact match) the character before the index is a dot or slash.
- let prevChar = str[index - 1];
- return (index == (str.length - aDomain.length)) &&
- (prevChar == "." || prevChar == "/");
-}
--- a/toolkit/mozapps/extensions/test/browser/browser.ini
+++ b/toolkit/mozapps/extensions/test/browser/browser.ini
@@ -24,24 +24,22 @@ support-files =
!/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html
!/toolkit/mozapps/extensions/test/xpinstall/restartless.xpi
!/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi
!/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi
!/toolkit/mozapps/extensions/test/xpinstall/amosigned-restart-required.xpi
[browser_CTP_plugins.js]
tags = blocklist
-skip-if = buildapp == 'mulet'
[browser_bug523784.js]
[browser_bug562797.js]
[browser_bug562854.js]
[browser_bug562890.js]
skip-if = os == 'win' && !debug # Disabled on Windows opt/PGO builds due to intermittent failures (bug 1135866)
[browser_bug562899.js]
-skip-if = buildapp == 'mulet'
[browser_bug562992.js]
[browser_bug567127.js]
[browser_bug567137.js]
[browser_bug570760.js]
skip-if = verify
[browser_bug572561.js]
[browser_bug577990.js]
[browser_bug580298.js]
@@ -53,17 +51,16 @@ skip-if = os == "linux" && !debug # Bug
[browser_bug596336.js]
[browser_bug618502.js]
[browser_bug679604.js]
[browser_bug590347.js]
[browser_checkAddonCompatibility.js]
[browser_details.js]
[browser_discovery.js]
[browser_dragdrop.js]
-skip-if = buildapp == 'mulet'
[browser_dragdrop_incompat.js]
[browser_file_xpi_no_process_switch.js]
skip-if = true # Bug 1449071 - Frequent failures
[browser_getmorethemes.js]
[browser_globalwarnings.js]
[browser_gmpProvider.js]
skip-if = os == 'linux' && !debug # Bug 1398766
[browser_inlinesettings_browser.js]
@@ -73,17 +70,16 @@ skip-if = verify
[browser_langpack_signing.js]
[browser_legacy.js]
[browser_legacy_pre57.js]
[browser_legacy_themes.js]
[browser_list.js]
[browser_manualupdates.js]
[browser_pluginprefs.js]
[browser_pluginprefs_is_not_disabled.js]
-skip-if = buildapp == 'mulet'
[browser_plugin_enabled_state_locked.js]
[browser_recentupdates.js]
[browser_sorting.js]
[browser_sorting_plugins.js]
[browser_tabsettings.js]
[browser_task_next_test.js]
[browser_types.js]
[browser_uninstalling.js]
--- a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_theme.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_webextension_theme.js
@@ -229,21 +229,16 @@ add_task(async function uninstall_offers
await theme.uninstall();
await promiseRestartManager();
});
// Test that default_locale works with WE themes
add_task(async function default_locale_themes() {
let addon = await promiseInstallWebExtension({
manifest: {
- applications: {
- gecko: {
- id: "locale-theme@tests.mozilla.org",
- }
- },
default_locale: "en",
name: "__MSG_name__",
description: "__MSG_description__",
theme: {
"colors": {
"accentcolor": "black",
"textcolor": "white",
}
--- a/tools/profiler/core/platform-macos.cpp
+++ b/tools/profiler/core/platform-macos.cpp
@@ -154,22 +154,24 @@ Sampler::SuspendAndSampleAndResumeThread
static void*
ThreadEntry(void* aArg)
{
auto thread = static_cast<SamplerThread*>(aArg);
thread->Run();
return nullptr;
}
-SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
+SamplerThread::SamplerThread(PSLockRef aLock,
+ uint32_t aActivityGeneration,
double aIntervalMilliseconds)
: Sampler(aLock)
, mActivityGeneration(aActivityGeneration)
, mIntervalMicroseconds(
std::max(1, int(floor(aIntervalMilliseconds * 1000 + 0.5))))
+ , mThread{nullptr}
{
pthread_attr_t* attr_ptr = nullptr;
if (pthread_create(&mThread, attr_ptr, ThreadEntry, this) != 0) {
MOZ_CRASH("pthread_create failed");
}
}
SamplerThread::~SamplerThread()
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -605,16 +605,21 @@ public:
// We initialize mRefCount to a large non-zero value so
// that it doesn't look like a JS object to the cycle collector
// in the case where the object dies before being traversed.
MOZ_ASSERT(!IsGrayJS() && !IsBlackJS());
}
// Allow NodePool::NodeBlock's constructor to compile.
PtrInfo()
+ : mPointer{ nullptr }
+ , mParticipant{ nullptr }
+ , mColor{ 0 }
+ , mInternalRefs{ 0 }
+ , mRefCount{ 0 }
{
NS_NOTREACHED("should never be called");
}
bool IsGrayJS() const
{
return mRefCount == 0;
}
@@ -686,16 +691,17 @@ private:
// |mNext|, all without causing slop.
enum { NodeBlockSize = 4 * 1024 - 2 };
struct NodeBlock
{
// We create and destroy NodeBlock using moz_xmalloc/free rather than new
// and delete to avoid calling its constructor and destructor.
NodeBlock()
+ : mNext{ nullptr }
{
NS_NOTREACHED("should never be called");
// Ensure NodeBlock is the right size (see the comment on NodeBlockSize
// above).
static_assert(
sizeof(NodeBlock) == 81904 || // 32-bit; equals 19.996 x 4 KiB pages
sizeof(NodeBlock) == 131048, // 64-bit; equals 31.994 x 4 KiB pages