author | Csoregi Natalia <ncsoregi@mozilla.com> |
Wed, 17 Oct 2018 13:03:35 +0300 | |
changeset 441628 | 9c943fa07f723ebf4fa3a885b69fe2cb3c5da2d7 |
parent 441577 | 99c45aca2d8a868eb9e6c3c5543af78954839934 (current diff) |
parent 441627 | 09dd66ffc95aff0d95312717a450fd85e803eb35 (diff) |
child 441642 | 5cc98bf772f726daa10abb0f5e3305c6466c6c53 |
child 441648 | 1a9ecfe4c2d4aae717bdb8cdbef9391a1e1c1ba6 |
push id | 34869 |
push user | ncsoregi@mozilla.com |
push date | Wed, 17 Oct 2018 10:04:28 +0000 |
treeherder | mozilla-central@9c943fa07f72 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 64.0a1 |
first release with | nightly linux32
9c943fa07f72
/
64.0a1
/
20181017101626
/
files
nightly linux64
9c943fa07f72
/
64.0a1
/
20181017101626
/
files
nightly mac
9c943fa07f72
/
64.0a1
/
20181017101626
/
files
nightly win32
9c943fa07f72
/
64.0a1
/
20181017101626
/
files
nightly win64
9c943fa07f72
/
64.0a1
/
20181017101626
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
64.0a1
/
20181017101626
/
pushlog to previous
nightly linux64
64.0a1
/
20181017101626
/
pushlog to previous
nightly mac
64.0a1
/
20181017101626
/
pushlog to previous
nightly win32
64.0a1
/
20181017101626
/
pushlog to previous
nightly win64
64.0a1
/
20181017101626
/
pushlog to previous
|
security/nss/automation/taskcluster/windows/setup32.sh | file | annotate | diff | comparison | revisions | |
security/nss/automation/taskcluster/windows/setup64.sh | file | annotate | diff | comparison | revisions | |
testing/web-platform/meta/wasm/idlharness.any.js.ini | file | annotate | diff | comparison | revisions |
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1500,16 +1500,21 @@ pref("toolkit.telemetry.hybridContent.en pref("browser.ping-centre.telemetry", true); pref("browser.ping-centre.log", false); pref("browser.ping-centre.staging.endpoint", "https://onyx_tiles.stage.mozaws.net/v3/links/ping-centre"); pref("browser.ping-centre.production.endpoint", "https://tiles.services.mozilla.com/v3/links/ping-centre"); // Enable GMP support in the addon manager. pref("media.gmp-provider.enabled", true); +// Enable blocking access to storage from tracking resources by default on Nightly +#ifdef NIGHTLY_BUILD +pref("network.cookie.cookieBehavior", 4 /* BEHAVIOR_REJECT_TRACKER */); +#endif + pref("browser.contentblocking.allowlist.storage.enabled", true); #ifdef NIGHTLY_BUILD pref("browser.contentblocking.global-toggle.enabled", true); #else pref("browser.contentblocking.global-toggle.enabled", false); #endif
--- a/caps/SystemPrincipal.cpp +++ b/caps/SystemPrincipal.cpp @@ -97,17 +97,17 @@ SystemPrincipal::GetPreloadCsp(nsIConten return NS_OK; } NS_IMETHODIMP SystemPrincipal::EnsurePreloadCSP(nsIDocument* aDocument, nsIContentSecurityPolicy** aPreloadCSP) { // CSP on a system principal makes no sense - return NS_OK; + return NS_ERROR_FAILURE; } NS_IMETHODIMP SystemPrincipal::GetDomain(nsIURI** aDomain) { *aDomain = nullptr; return NS_OK; }
--- a/dom/payments/PaymentRequest.cpp +++ b/dom/payments/PaymentRequest.cpp @@ -5,25 +5,29 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "BasicCardPayment.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/FeaturePolicyUtils.h" #include "mozilla/dom/PaymentRequest.h" #include "mozilla/dom/PaymentRequestChild.h" #include "mozilla/dom/PaymentResponse.h" +#include "mozilla/intl/LocaleService.h" +#include "mozilla/intl/MozLocale.h" #include "mozilla/EventStateManager.h" #include "mozilla/StaticPrefs.h" #include "nsContentUtils.h" #include "nsIScriptError.h" #include "nsIURLParser.h" #include "nsNetCID.h" #include "PaymentRequestManager.h" #include "mozilla/dom/MerchantValidationEvent.h" +using mozilla::intl::LocaleService; + namespace mozilla { namespace dom { NS_IMPL_CYCLE_COLLECTION_CLASS(PaymentRequest) NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PaymentRequest, DOMEventTargetHelper) // Don't need NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER because @@ -55,21 +59,45 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION( NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) NS_IMPL_ADDREF_INHERITED(PaymentRequest, DOMEventTargetHelper) NS_IMPL_RELEASE_INHERITED(PaymentRequest, DOMEventTargetHelper) bool PaymentRequest::PrefEnabled(JSContext* aCx, JSObject* aObj) { -#ifdef NIGHTLY_BUILD +#if defined(NIGHTLY_BUILD) + const char* supportedRegions[] = { "US", "CA" }; + if (!XRE_IsContentProcess()) { return false; } - return StaticPrefs::dom_payments_request_enabled(); + if (!StaticPrefs::dom_payments_request_enabled()) { + return false; + } + nsAutoString region; + Preferences::GetString("browser.search.region", region); + bool regionIsSupported = false; + for (const char* each : supportedRegions) { + if (region.EqualsASCII(each)) { + regionIsSupported = true; + break; + } + } + if (!regionIsSupported) { + return false; + } + nsAutoCString locale; + LocaleService::GetInstance()->GetAppLocaleAsLangTag(locale); + mozilla::intl::Locale loc = mozilla::intl::Locale(locale); + if (!(loc.GetLanguage() == "en" && loc.GetRegion() == "US")) { + return false; + } + + return true; #else return false; #endif } nsresult PaymentRequest::IsValidStandardizedPMI(const nsAString& aIdentifier, nsAString& aErrorMsg)
--- a/dom/serviceworkers/test/mochitest.ini +++ b/dom/serviceworkers/test/mochitest.ini @@ -1,10 +1,16 @@ [DEFAULT] - +# Mochitests are executed in iframes. Several ServiceWorker tests use iframes +# too. The result is that we have nested iframes. CookieBehavior 4 +# (BEHAVIOR_REJECT_TRACKER) doesn't grant storage access permission to nested +# iframes because trackers could use them to follow users across sites. Let's +# use cookieBehavior 0 (BEHAVIOR_ACCEPT) here. +prefs = + network.cookie.cookieBehavior=0 skip-if = serviceworker_e10s support-files = worker.js worker2.js worker3.js fetch_event_worker.js parse_error_worker.js activate_event_error_worker.js
--- a/dom/tests/mochitest/general/test_interfaces.js +++ b/dom/tests/mochitest/general/test_interfaces.js @@ -654,16 +654,18 @@ var interfaceNamesInGlobalScope = {name: "MediaStreamAudioSourceNode", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "MediaStreamEvent", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "MediaStreamTrackEvent", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "MediaStreamTrack", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! + {name: "MerchantValidationEvent", insecureContext: false, desktop: true, nightly: true, linux: false}, +// IMPORTANT: Do not change this list without review from a DOM peer! {name: "MessageChannel", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "MessageEvent", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "MessagePort", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "MIDIAccess", disabled: true}, // IMPORTANT: Do not change this list without review from a DOM peer! @@ -734,16 +736,26 @@ var interfaceNamesInGlobalScope = {name: "PaintRequest", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "PaintRequestList", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "PannerNode", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "Path2D", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! + {name: "PaymentAddress", insecureContext: false, desktop: true, nightly: true, linux: false}, +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "PaymentMethodChangeEvent", insecureContext: false, desktop: true, nightly: true, linux: false}, +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "PaymentRequest", insecureContext: false, desktop: true, nightly: true, linux: false}, +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "PaymentRequestUpdateEvent", insecureContext: false, desktop: true, nightly: true, linux: false}, +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "PaymentResponse", insecureContext: false, desktop: true, nightly: true, linux: false}, +// IMPORTANT: Do not change this list without review from a DOM peer! {name: "Performance", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "PerformanceEntry", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "PerformanceMark", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "PerformanceMeasure", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/extensions/cookie/nsPermissionManager.cpp +++ b/extensions/cookie/nsPermissionManager.cpp @@ -1,15 +1,16 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 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 "mozilla/Attributes.h" +#include "mozilla/AntiTrackingCommon.h" #include "mozilla/DebugOnly.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/BasePrincipal.h" #include "mozilla/ContentPrincipal.h" #include "mozilla/Pair.h" #include "mozilla/Services.h" @@ -132,17 +133,19 @@ static const char* kPreloadPermissions[] "speculative", // This permission is preloaded to support properly blocking service worker // interception when a user has disabled storage for a specific site. Once // service worker interception moves to the parent process this should be // removed. See bug 1428130. "cookie", "trackingprotection", - "trackingprotection-pb" + "trackingprotection-pb", + + USER_INTERACTION_PERM }; // A list of permissions that can have a fallback default permission // set under the permissions.default.* pref. static const char* kPermissionsWithDefaults[] = { "camera", "microphone", "geo",
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -1182,17 +1182,17 @@ WebRenderBridgeParent::RecvGetSnapshot(P MOZ_ASSERT(bufferTexture->GetFormat() == SurfaceFormat::B8G8R8A8); uint32_t buffer_size = size.width * size.height * 4; // Assert the stride of the buffer is what webrender expects MOZ_ASSERT((uint32_t)(size.width * 4) == stride); FlushSceneBuilds(); FlushFrameGeneration(); - mApi->Readback(start, size, buffer, buffer_size); + mApi->Readback(start, size, Range<uint8_t>(buffer, buffer_size)); return IPC_OK(); } void WebRenderBridgeParent::AddPipelineIdForCompositable(const wr::PipelineId& aPipelineId, const CompositableHandle& aHandle, const bool& aAsync,
--- a/gfx/webrender_bindings/RenderThread.cpp +++ b/gfx/webrender_bindings/RenderThread.cpp @@ -273,17 +273,17 @@ RenderThread::HandleFrame(wr::WindowId a MutexAutoLock lock(mFrameCountMapLock); auto it = mWindowInfos.find(AsUint64(aWindowId)); MOZ_ASSERT(it != mWindowInfos.end()); WindowInfo* info = it->second; MOZ_ASSERT(info->mPendingCount > 0); startTime = info->mStartTimes.front(); } - UpdateAndRender(aWindowId, startTime, aRender, /* aReadback */ false); + UpdateAndRender(aWindowId, startTime, aRender, /* aReadbackSize */ Nothing(), /* aReadbackBuffer */ Nothing()); FrameRenderingComplete(aWindowId); } void RenderThread::WakeUp(wr::WindowId aWindowId) { if (mHasShutdown) { return; @@ -351,32 +351,33 @@ NotifyDidRender(layers::CompositorBridge wr_pipeline_info_delete(aInfo); } void RenderThread::UpdateAndRender(wr::WindowId aWindowId, const TimeStamp& aStartTime, bool aRender, - bool aReadback) + const Maybe<gfx::IntSize>& aReadbackSize, + const Maybe<Range<uint8_t>>& aReadbackBuffer) { AUTO_PROFILER_TRACING("Paint", "Composite"); MOZ_ASSERT(IsInRenderThread()); - MOZ_ASSERT(aRender || !aReadback); + MOZ_ASSERT(aRender || aReadbackBuffer.isNothing()); auto it = mRenderers.find(aWindowId); MOZ_ASSERT(it != mRenderers.end()); if (it == mRenderers.end()) { return; } auto& renderer = it->second; if (aRender) { - renderer->UpdateAndRender(aReadback); + renderer->UpdateAndRender(aReadbackSize, aReadbackBuffer); } else { renderer->Update(); } TimeStamp end = TimeStamp::Now(); auto info = renderer->FlushPipelineInfo(); RefPtr<layers::AsyncImagePipelineManager> pipelineMgr =
--- a/gfx/webrender_bindings/RenderThread.h +++ b/gfx/webrender_bindings/RenderThread.h @@ -8,16 +8,17 @@ #define MOZILLA_LAYERS_RENDERTHREAD_H #include "base/basictypes.h" // for DISALLOW_EVIL_CONSTRUCTORS #include "base/platform_thread.h" // for PlatformThreadId #include "base/thread.h" // for Thread #include "base/message_loop.h" #include "nsISupportsImpl.h" #include "ThreadSafeRefcountingWithMainThreadDestruction.h" +#include "mozilla/gfx/Point.h" #include "mozilla/MozPromise.h" #include "mozilla/Mutex.h" #include "mozilla/webrender/webrender_ffi.h" #include "mozilla/UniquePtr.h" #include "mozilla/webrender/WebRenderTypes.h" #include "mozilla/layers/SynchronousTask.h" #include "GLContext.h" @@ -146,17 +147,17 @@ public: /// Automatically forwarded to the render thread. void PipelineSizeChanged(wr::WindowId aWindowId, uint64_t aPipelineId, float aWidth, float aHeight); /// Automatically forwarded to the render thread. void RunEvent(wr::WindowId aWindowId, UniquePtr<RendererEvent> aCallBack); /// Can only be called from the render thread. - void UpdateAndRender(wr::WindowId aWindowId, const TimeStamp& aStartTime, bool aRender, bool aReadback); + void UpdateAndRender(wr::WindowId aWindowId, const TimeStamp& aStartTime, bool aRender, const Maybe<gfx::IntSize>& aReadbackSize, const Maybe<Range<uint8_t>>& aReadbackBuffer); void Pause(wr::WindowId aWindowId); bool Resume(wr::WindowId aWindowId); /// Can be called from any thread. void RegisterExternalImage(uint64_t aExternalImageId, already_AddRefed<RenderTextureHost> aTexture); /// Can be called from any thread.
--- a/gfx/webrender_bindings/RendererOGL.cpp +++ b/gfx/webrender_bindings/RendererOGL.cpp @@ -101,21 +101,21 @@ RendererOGL::Update() static void DoNotifyWebRenderContextPurge(layers::CompositorBridgeParent* aBridge) { aBridge->NotifyWebRenderContextPurge(); } bool -RendererOGL::UpdateAndRender(bool aReadback) +RendererOGL::UpdateAndRender(const Maybe<gfx::IntSize>& aReadbackSize, const Maybe<Range<uint8_t>>& aReadbackBuffer) { uint32_t flags = gfx::gfxVars::WebRenderDebugFlags(); // Disable debug flags during readback - if (aReadback) { + if (aReadbackBuffer.isSome()) { flags = 0; } if (mDebugFlags.mBits != flags) { mDebugFlags.mBits = flags; wr_renderer_set_debug_flags(mRenderer, mDebugFlags); } @@ -142,16 +142,24 @@ RendererOGL::UpdateAndRender(bool aReadb wr_renderer_update(mRenderer); auto size = mCompositor->GetBufferSize(); if (!wr_renderer_render(mRenderer, size.width, size.height)) { NotifyWebRenderError(WebRenderError::RENDER); } + if (aReadbackBuffer.isSome()) { + MOZ_ASSERT(aReadbackSize.isSome()); + wr_renderer_readback(mRenderer, + aReadbackSize.ref().width, aReadbackSize.ref().height, + &aReadbackBuffer.ref()[0], + aReadbackBuffer.ref().length()); + } + mCompositor->EndFrame(); mCompositor->GetWidget()->PostRender(&widgetContext); #if defined(ENABLE_FRAME_LATENCY_LOG) if (mFrameStartTime) { uint32_t latencyMs = round((TimeStamp::Now() - mFrameStartTime).ToMilliseconds()); printf_stderr("generate frame latencyMs latencyMs %d\n", latencyMs);
--- a/gfx/webrender_bindings/RendererOGL.h +++ b/gfx/webrender_bindings/RendererOGL.h @@ -3,16 +3,17 @@ /* 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 MOZILLA_LAYERS_RENDEREROGL_H #define MOZILLA_LAYERS_RENDEREROGL_H #include "mozilla/layers/CompositorTypes.h" +#include "mozilla/gfx/Point.h" #include "mozilla/webrender/RenderThread.h" #include "mozilla/webrender/WebRenderTypes.h" #include "mozilla/webrender/webrender_ffi.h" namespace mozilla { namespace gfx { class DrawTarget; @@ -51,17 +52,17 @@ class RendererOGL public: wr::WrExternalImageHandler GetExternalImageHandler(); /// This can be called on the render thread only. void Update(); /// This can be called on the render thread only. - bool UpdateAndRender(bool aReadback); + bool UpdateAndRender(const Maybe<gfx::IntSize>& aReadbackSize, const Maybe<Range<uint8_t>>& aReadbackBuffer); /// This can be called on the render thread only. bool RenderToTarget(gfx::DrawTarget& aTarget); /// This can be called on the render thread only. void SetProfilerEnabled(bool aEnabled); /// This can be called on the render thread only.
--- a/gfx/webrender_bindings/WebRenderAPI.cpp +++ b/gfx/webrender_bindings/WebRenderAPI.cpp @@ -391,56 +391,51 @@ WebRenderAPI::HitTest(const wr::WorldPoi aOutHitInfo.deserialize(serialized); } return result; } void WebRenderAPI::Readback(const TimeStamp& aStartTime, gfx::IntSize size, - uint8_t *buffer, - uint32_t buffer_size) + const Range<uint8_t>& buffer) { class Readback : public RendererEvent { public: explicit Readback(layers::SynchronousTask* aTask, TimeStamp aStartTime, - gfx::IntSize aSize, uint8_t *aBuffer, uint32_t aBufferSize) + gfx::IntSize aSize, const Range<uint8_t>& aBuffer) : mTask(aTask) , mStartTime(aStartTime) , mSize(aSize) , mBuffer(aBuffer) - , mBufferSize(aBufferSize) { MOZ_COUNT_CTOR(Readback); } ~Readback() { MOZ_COUNT_DTOR(Readback); } virtual void Run(RenderThread& aRenderThread, WindowId aWindowId) override { - aRenderThread.UpdateAndRender(aWindowId, mStartTime, /* aRender */ true, /* aReadback */ true); - wr_renderer_readback(aRenderThread.GetRenderer(aWindowId)->GetRenderer(), - mSize.width, mSize.height, mBuffer, mBufferSize); + aRenderThread.UpdateAndRender(aWindowId, mStartTime, /* aRender */ true, Some(mSize), Some(mBuffer)); layers::AutoCompleteTask complete(mTask); } layers::SynchronousTask* mTask; TimeStamp mStartTime; gfx::IntSize mSize; - uint8_t *mBuffer; - uint32_t mBufferSize; + const Range<uint8_t>& mBuffer; }; layers::SynchronousTask task("Readback"); - auto event = MakeUnique<Readback>(&task, aStartTime, size, buffer, buffer_size); + auto event = MakeUnique<Readback>(&task, aStartTime, size, buffer); // This event will be passed from wr_backend thread to renderer thread. That // implies that all frame data have been processed when the renderer runs this // read-back event. Then, we could make sure this read-back event gets the // latest result. RunOnRenderThread(std::move(event)); task.Wait(); }
--- a/gfx/webrender_bindings/WebRenderAPI.h +++ b/gfx/webrender_bindings/WebRenderAPI.h @@ -209,17 +209,17 @@ public: gfx::CompositorHitTestInfo& aOutHitInfo); void SendTransaction(TransactionBuilder& aTxn); void SetFrameStartTime(const TimeStamp& aTime); void RunOnRenderThread(UniquePtr<RendererEvent> aEvent); - void Readback(const TimeStamp& aStartTime, gfx::IntSize aSize, uint8_t *aBuffer, uint32_t aBufferSize); + void Readback(const TimeStamp& aStartTime, gfx::IntSize aSize, const Range<uint8_t>& aBuffer); void ClearAllCaches(); void Pause(); bool Resume(); void WakeSceneBuilder(); void FlushSceneBuilder();
--- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -261,18 +261,18 @@ struct MOZ_STACK_CLASS BytecodeEmitter BytecodeEmitter(BytecodeEmitter* parent, BCEParserHandle* parser, SharedContext* sc, HandleScript script, Handle<LazyScript*> lazyScript, uint32_t lineNum, EmitterMode emitterMode = Normal); BytecodeEmitter(BytecodeEmitter* parent, const EitherParser& parser, SharedContext* sc, HandleScript script, Handle<LazyScript*> lazyScript, uint32_t lineNum, EmitterMode emitterMode = Normal); - template<typename CharT> - BytecodeEmitter(BytecodeEmitter* parent, Parser<FullParseHandler, CharT>* parser, + template<typename Unit> + BytecodeEmitter(BytecodeEmitter* parent, Parser<FullParseHandler, Unit>* parser, SharedContext* sc, HandleScript script, Handle<LazyScript*> lazyScript, uint32_t lineNum, EmitterMode emitterMode = Normal) : BytecodeEmitter(parent, EitherParser(parser), sc, script, lazyScript, lineNum, emitterMode) {} // An alternate constructor that uses a TokenPos for the starting // line and that sets functionBodyEndPos as well. @@ -291,18 +291,18 @@ struct MOZ_STACK_CLASS BytecodeEmitter EmitterMode emitterMode = Normal) : BytecodeEmitter(parent, parser, sc, script, lazyScript, parser.errorReporter().lineAt(bodyPosition.begin), emitterMode) { initFromBodyPosition(bodyPosition); } - template<typename CharT> - BytecodeEmitter(BytecodeEmitter* parent, Parser<FullParseHandler, CharT>* parser, + template<typename Unit> + BytecodeEmitter(BytecodeEmitter* parent, Parser<FullParseHandler, Unit>* parser, SharedContext* sc, HandleScript script, Handle<LazyScript*> lazyScript, TokenPos bodyPosition, EmitterMode emitterMode = Normal) : BytecodeEmitter(parent, EitherParser(parser), sc, script, lazyScript, bodyPosition, emitterMode) {} MOZ_MUST_USE bool init();
--- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -694,180 +694,180 @@ FunctionBox::finish() { if (!isLazyFunctionWithoutEnclosingScope()) { return; } MOZ_ASSERT(enclosingScope_); function()->lazyScript()->setEnclosingScope(enclosingScope_); } -template <class ParseHandler, typename CharT> -inline typename GeneralParser<ParseHandler, CharT>::FinalParser* -GeneralParser<ParseHandler, CharT>::asFinalParser() -{ - static_assert(mozilla::IsBaseOf<GeneralParser<ParseHandler, CharT>, FinalParser>::value, +template <class ParseHandler, typename Unit> +inline typename GeneralParser<ParseHandler, Unit>::FinalParser* +GeneralParser<ParseHandler, Unit>::asFinalParser() +{ + static_assert(mozilla::IsBaseOf<GeneralParser<ParseHandler, Unit>, FinalParser>::value, "inheritance relationship required by the static_cast<> below"); return static_cast<FinalParser*>(this); } -template <class ParseHandler, typename CharT> -inline const typename GeneralParser<ParseHandler, CharT>::FinalParser* -GeneralParser<ParseHandler, CharT>::asFinalParser() const -{ - static_assert(mozilla::IsBaseOf<GeneralParser<ParseHandler, CharT>, FinalParser>::value, +template <class ParseHandler, typename Unit> +inline const typename GeneralParser<ParseHandler, Unit>::FinalParser* +GeneralParser<ParseHandler, Unit>::asFinalParser() const +{ + static_assert(mozilla::IsBaseOf<GeneralParser<ParseHandler, Unit>, FinalParser>::value, "inheritance relationship required by the static_cast<> below"); return static_cast<const FinalParser*>(this); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::error(unsigned errorNumber, ...) +GeneralParser<ParseHandler, Unit>::error(unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); ErrorMetadata metadata; if (tokenStream.computeErrorMetadata(&metadata, pos().begin)) { ReportCompileError(context, std::move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args); } va_end(args); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::errorWithNotes(UniquePtr<JSErrorNotes> notes, - unsigned errorNumber, ...) +GeneralParser<ParseHandler, Unit>::errorWithNotes(UniquePtr<JSErrorNotes> notes, + unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); ErrorMetadata metadata; if (tokenStream.computeErrorMetadata(&metadata, pos().begin)) { ReportCompileError(context, std::move(metadata), std::move(notes), JSREPORT_ERROR, errorNumber, args); } va_end(args); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::errorAt(uint32_t offset, unsigned errorNumber, ...) +GeneralParser<ParseHandler, Unit>::errorAt(uint32_t offset, unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); ErrorMetadata metadata; if (tokenStream.computeErrorMetadata(&metadata, offset)) { ReportCompileError(context, std::move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args); } va_end(args); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::errorWithNotesAt(UniquePtr<JSErrorNotes> notes, - uint32_t offset, unsigned errorNumber, ...) +GeneralParser<ParseHandler, Unit>::errorWithNotesAt(UniquePtr<JSErrorNotes> notes, + uint32_t offset, unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); ErrorMetadata metadata; if (tokenStream.computeErrorMetadata(&metadata, offset)) { ReportCompileError(context, std::move(metadata), std::move(notes), JSREPORT_ERROR, errorNumber, args); } va_end(args); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::warning(unsigned errorNumber, ...) +GeneralParser<ParseHandler, Unit>::warning(unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); ErrorMetadata metadata; bool result = tokenStream.computeErrorMetadata(&metadata, pos().begin) && anyChars.compileWarning(std::move(metadata), nullptr, JSREPORT_WARNING, errorNumber, args); va_end(args); return result; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::warningAt(uint32_t offset, unsigned errorNumber, ...) +GeneralParser<ParseHandler, Unit>::warningAt(uint32_t offset, unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); ErrorMetadata metadata; bool result = tokenStream.computeErrorMetadata(&metadata, offset); if (result) { result = anyChars.compileWarning(std::move(metadata), nullptr, JSREPORT_WARNING, errorNumber, args); } va_end(args); return result; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::extraWarning(unsigned errorNumber, ...) +GeneralParser<ParseHandler, Unit>::extraWarning(unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); bool result = tokenStream.reportExtraWarningErrorNumberVA(nullptr, pos().begin, errorNumber, &args); va_end(args); return result; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::extraWarningAt(uint32_t offset, unsigned errorNumber, ...) +GeneralParser<ParseHandler, Unit>::extraWarningAt(uint32_t offset, unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); bool result = tokenStream.reportExtraWarningErrorNumberVA(nullptr, offset, errorNumber, &args); va_end(args); return result; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::strictModeError(unsigned errorNumber, ...) +GeneralParser<ParseHandler, Unit>::strictModeError(unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); bool res = tokenStream.reportStrictModeErrorNumberVA(nullptr, pos().begin, pc->sc()->strict(), errorNumber, &args); va_end(args); return res; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::strictModeErrorAt(uint32_t offset, unsigned errorNumber, ...) +GeneralParser<ParseHandler, Unit>::strictModeErrorAt(uint32_t offset, unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); bool res = tokenStream.reportStrictModeErrorNumberVA(nullptr, offset, pc->sc()->strict(), errorNumber, &args); @@ -969,75 +969,75 @@ PerHandlerParser<ParseHandler>::PerHandl ParseGoal parseGoal, void* internalSyntaxParser) : ParserBase(cx, alloc, options, foldConstants, usedNames, sourceObject, parseGoal), handler(cx, alloc, lazyOuterFunction), internalSyntaxParser_(internalSyntaxParser) { } -template <class ParseHandler, typename CharT> -GeneralParser<ParseHandler, CharT>::GeneralParser(JSContext* cx, LifoAlloc& alloc, - const ReadOnlyCompileOptions& options, - const CharT* chars, size_t length, - bool foldConstants, - UsedNameTracker& usedNames, - SyntaxParser* syntaxParser, - LazyScript* lazyOuterFunction, - ScriptSourceObject* sourceObject, - ParseGoal parseGoal) +template <class ParseHandler, typename Unit> +GeneralParser<ParseHandler, Unit>::GeneralParser(JSContext* cx, LifoAlloc& alloc, + const ReadOnlyCompileOptions& options, + const Unit* units, size_t length, + bool foldConstants, + UsedNameTracker& usedNames, + SyntaxParser* syntaxParser, + LazyScript* lazyOuterFunction, + ScriptSourceObject* sourceObject, + ParseGoal parseGoal) : Base(cx, alloc, options, foldConstants, usedNames, syntaxParser, lazyOuterFunction, sourceObject, parseGoal), - tokenStream(cx, options, chars, length) + tokenStream(cx, options, units, length) {} -template <typename CharT> +template <typename Unit> void -Parser<SyntaxParseHandler, CharT>::setAwaitHandling(AwaitHandling awaitHandling) +Parser<SyntaxParseHandler, Unit>::setAwaitHandling(AwaitHandling awaitHandling) { this->awaitHandling_ = awaitHandling; } -template <typename CharT> +template <typename Unit> void -Parser<FullParseHandler, CharT>::setAwaitHandling(AwaitHandling awaitHandling) +Parser<FullParseHandler, Unit>::setAwaitHandling(AwaitHandling awaitHandling) { this->awaitHandling_ = awaitHandling; if (SyntaxParser* syntaxParser = getSyntaxParser()) { syntaxParser->setAwaitHandling(awaitHandling); } } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> inline void -GeneralParser<ParseHandler, CharT>::setAwaitHandling(AwaitHandling awaitHandling) +GeneralParser<ParseHandler, Unit>::setAwaitHandling(AwaitHandling awaitHandling) { asFinalParser()->setAwaitHandling(awaitHandling); } -template <typename CharT> +template <typename Unit> void -Parser<SyntaxParseHandler, CharT>::setInParametersOfAsyncFunction(bool inParameters) +Parser<SyntaxParseHandler, Unit>::setInParametersOfAsyncFunction(bool inParameters) { this->inParametersOfAsyncFunction_ = inParameters; } -template <typename CharT> +template <typename Unit> void -Parser<FullParseHandler, CharT>::setInParametersOfAsyncFunction(bool inParameters) +Parser<FullParseHandler, Unit>::setInParametersOfAsyncFunction(bool inParameters) { this->inParametersOfAsyncFunction_ = inParameters; if (SyntaxParser* syntaxParser = getSyntaxParser()) { syntaxParser->setInParametersOfAsyncFunction(inParameters); } } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> inline void -GeneralParser<ParseHandler, CharT>::setInParametersOfAsyncFunction(bool inParameters) +GeneralParser<ParseHandler, Unit>::setInParametersOfAsyncFunction(bool inParameters) { asFinalParser()->setInParametersOfAsyncFunction(inParameters); } ObjectBox* ParserBase::newObjectBox(JSObject* obj) { MOZ_ASSERT(obj); @@ -1159,19 +1159,19 @@ ParserBase::setSourceMapInfo() return true; } /* * Parse a top-level JS script. */ -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::ListNodeType -GeneralParser<ParseHandler, CharT>::parse() +GeneralParser<ParseHandler, Unit>::parse() { MOZ_ASSERT(checkOptionsCalled); Directives directives(options().strictOption); GlobalSharedContext globalsc(context, ScopeKind::Global, directives, options().extraWarningsOption); SourceParseContext globalpc(this, &globalsc, /* newDirectives = */ nullptr); if (!globalpc.init()) { @@ -1242,20 +1242,20 @@ ParserBase::hasValidSimpleStrictParamete MOZ_ASSERT(name); if (!isValidStrictBinding(name->asPropertyName())) { return false; } } return true; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::reportMissingClosing(unsigned errorNumber, unsigned noteNumber, - uint32_t openedPos) +GeneralParser<ParseHandler, Unit>::reportMissingClosing(unsigned errorNumber, unsigned noteNumber, + uint32_t openedPos) { auto notes = MakeUnique<JSErrorNotes>(); if (!notes) { ReportOutOfMemory(pc->sc()->context); return; } uint32_t line, column; @@ -1273,21 +1273,21 @@ GeneralParser<ParseHandler, CharT>::repo noteNumber, lineNumber, columnNumber)) { return; } errorWithNotes(std::move(notes), errorNumber); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::reportRedeclaration(HandlePropertyName name, - DeclarationKind prevKind, - TokenPos pos, uint32_t prevPos) +GeneralParser<ParseHandler, Unit>::reportRedeclaration(HandlePropertyName name, + DeclarationKind prevKind, + TokenPos pos, uint32_t prevPos) { UniqueChars bytes = AtomToPrintableString(context, name); if (!bytes) { return; } if (prevPos == DeclaredNameInfo::npos) { errorAt(pos.begin, JSMSG_REDECLARED_VAR, DeclarationKindString(prevKind), bytes.get()); @@ -1326,23 +1326,23 @@ GeneralParser<ParseHandler, CharT>::repo // function definition and the arguments specified by the Function // constructor. // // The 'disallowDuplicateParams' bool indicates whether the use of another // feature (destructuring or default arguments) disables duplicate arguments. // (ECMA-262 requires us to support duplicate parameter names, but, for newer // features, we consider the code to have "opted in" to higher standards and // forbid duplicates.) -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::notePositionalFormalParameter(CodeNodeType funNode, - HandlePropertyName name, - uint32_t beginPos, - bool disallowDuplicateParams, - bool* duplicatedParam) +GeneralParser<ParseHandler, Unit>::notePositionalFormalParameter(CodeNodeType funNode, + HandlePropertyName name, + uint32_t beginPos, + bool disallowDuplicateParams, + bool* duplicatedParam) { if (AddDeclaredNamePtr p = pc->functionScope().lookupDeclaredNameForAdd(name)) { if (disallowDuplicateParams) { error(JSMSG_BAD_DUP_ARGS); return false; } // Strict-mode disallows duplicate args. We may not know whether we are @@ -1628,21 +1628,21 @@ ParseContext::annexBAppliesToLexicalFunc } } // If an early error would have occurred already, this function should not // exhibit Annex B.3.3 semantics. return !redeclaredKind; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::checkLexicalDeclarationDirectlyWithinBlock(ParseContext::Statement& stmt, - DeclarationKind kind, - TokenPos pos) +GeneralParser<ParseHandler, Unit>::checkLexicalDeclarationDirectlyWithinBlock(ParseContext::Statement& stmt, + DeclarationKind kind, + TokenPos pos) { MOZ_ASSERT(DeclarationKindIsLexical(kind)); // It is an early error to declare a lexical binding not directly // within a block. if (!StatementKindIsBraced(stmt.kind()) && stmt.kind() != StatementKind::ForLoopLexicalHead) { @@ -1652,20 +1652,20 @@ GeneralParser<ParseHandler, CharT>::chec : JSMSG_LEXICAL_DECL_NOT_IN_BLOCK, DeclarationKindString(kind)); return false; } return true; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::noteDeclaredName(HandlePropertyName name, DeclarationKind kind, - TokenPos pos) +GeneralParser<ParseHandler, Unit>::noteDeclaredName(HandlePropertyName name, DeclarationKind kind, + TokenPos pos) { // The asm.js validator does all its own symbol-table management so, as an // optimization, avoid doing any work here. if (pc->useAsmOrInsideUseAsm()) { return true; } switch (kind) { @@ -1907,19 +1907,19 @@ PerHandlerParser<ParseHandler>::propagat if (isSyntaxParser && !pc->closedOverBindingsForLazy().append(nullptr)) { ReportOutOfMemory(context); return false; } return true; } -template <typename CharT> +template <typename Unit> bool -Parser<FullParseHandler, CharT>::checkStatementsEOF() +Parser<FullParseHandler, Unit>::checkStatementsEOF() { // This is designed to be paired with parsing a statement list at the top // level. // // The statementList() call breaks on TokenKind::RightCurly, so make sure // we've reached EOF here. TokenKind tt; if (!tokenStream.peekToken(&tt, TokenStream::Operand)) { @@ -2372,19 +2372,19 @@ PerHandlerParser<FullParseHandler>::fini Maybe<LexicalScope::Data*> bindings = newLexicalScopeData(scope); if (!bindings) { return nullptr; } return handler.newLexicalScope(*bindings, body); } -template <typename CharT> +template <typename Unit> LexicalScopeNode* -Parser<FullParseHandler, CharT>::evalBody(EvalSharedContext* evalsc) +Parser<FullParseHandler, Unit>::evalBody(EvalSharedContext* evalsc) { SourceParseContext evalpc(this, evalsc, /* newDirectives = */ nullptr); if (!evalpc.init()) { return nullptr; } ParseContext::VarScope varScope(this); if (!varScope.init(pc)) { @@ -2458,19 +2458,19 @@ Parser<FullParseHandler, CharT>::evalBod if (!bindings) { return nullptr; } evalsc->bindings = *bindings; return body; } -template <typename CharT> +template <typename Unit> ListNode* -Parser<FullParseHandler, CharT>::globalBody(GlobalSharedContext* globalsc) +Parser<FullParseHandler, Unit>::globalBody(GlobalSharedContext* globalsc) { SourceParseContext globalpc(this, globalsc, /* newDirectives = */ nullptr); if (!globalpc.init()) { return nullptr; } ParseContext::VarScope varScope(this); if (!varScope.init(pc)) { @@ -2507,19 +2507,19 @@ Parser<FullParseHandler, CharT>::globalB if (!bindings) { return nullptr; } globalsc->bindings = *bindings; return body; } -template <typename CharT> +template <typename Unit> CodeNode* -Parser<FullParseHandler, CharT>::moduleBody(ModuleSharedContext* modulesc) +Parser<FullParseHandler, Unit>::moduleBody(ModuleSharedContext* modulesc) { MOZ_ASSERT(checkOptionsCalled); SourceParseContext modulepc(this, modulesc, nullptr); if (!modulepc.init()) { return null(); } @@ -2528,17 +2528,17 @@ Parser<FullParseHandler, CharT>::moduleB return nullptr; } CodeNodeType moduleNode = handler.newModule(pos()); if (!moduleNode) { return null(); } - AutoAwaitIsKeyword<FullParseHandler, CharT> awaitIsKeyword(this, AwaitIsModuleKeyword); + AutoAwaitIsKeyword<FullParseHandler, Unit> awaitIsKeyword(this, AwaitIsModuleKeyword); ListNode* stmtList = statementList(YieldIsName); if (!stmtList) { return null(); } MOZ_ASSERT(stmtList->isKind(ParseNodeKind::StatementList)); moduleNode->setBody(&stmtList->as<ListNode>()); @@ -2592,19 +2592,19 @@ Parser<FullParseHandler, CharT>::moduleB if (!bindings) { return nullptr; } modulesc->bindings = *bindings; return moduleNode; } -template <typename CharT> +template <typename Unit> SyntaxParseHandler::CodeNodeType -Parser<SyntaxParseHandler, CharT>::moduleBody(ModuleSharedContext* modulesc) +Parser<SyntaxParseHandler, Unit>::moduleBody(ModuleSharedContext* modulesc) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return SyntaxParseHandler::NodeFailure; } bool ParserBase::hasUsedFunctionSpecialName(HandlePropertyName name) { @@ -2835,25 +2835,24 @@ static AwaitHandling GetAwaitHandling(FunctionAsyncKind asyncKind) { if (asyncKind == FunctionAsyncKind::SyncFunction) { return AwaitIsName; } return AwaitIsKeyword; } -template <typename CharT> +template <typename Unit> CodeNode* -Parser<FullParseHandler, CharT>::standaloneFunction(HandleFunction fun, - HandleScope enclosingScope, - const Maybe<uint32_t>& parameterListEnd, - GeneratorKind generatorKind, - FunctionAsyncKind asyncKind, - Directives inheritedDirectives, - Directives* newDirectives) +Parser<FullParseHandler, Unit>::standaloneFunction(HandleFunction fun, HandleScope enclosingScope, + const Maybe<uint32_t>& parameterListEnd, + GeneratorKind generatorKind, + FunctionAsyncKind asyncKind, + Directives inheritedDirectives, + Directives* newDirectives) { MOZ_ASSERT(checkOptionsCalled); // Skip prelude. TokenKind tt; if (!tokenStream.getToken(&tt, TokenStream::Operand)) { return null(); } @@ -2904,17 +2903,17 @@ Parser<FullParseHandler, CharT>::standal SourceParseContext funpc(this, funbox, newDirectives); if (!funpc.init()) { return null(); } funpc.setIsStandaloneFunctionBody(); YieldHandling yieldHandling = GetYieldHandling(generatorKind); AwaitHandling awaitHandling = GetAwaitHandling(asyncKind); - AutoAwaitIsKeyword<FullParseHandler, CharT> awaitIsKeyword(this, awaitHandling); + AutoAwaitIsKeyword<FullParseHandler, Unit> awaitIsKeyword(this, awaitHandling); if (!functionFormalParametersAndBody(InAllowed, yieldHandling, &funNode, FunctionSyntaxKind::Statement, parameterListEnd, /* isStandaloneFunction = */ true)) { return null(); } if (!tokenStream.getToken(&tt, TokenStream::Operand)) { @@ -3014,21 +3013,20 @@ PerHandlerParser<ParseHandler>::declareF if (pc->sc()->hasDebuggerStatement()) { funbox->setDefinitelyNeedsArgsObj(); } } return true; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::LexicalScopeNodeType -GeneralParser<ParseHandler, CharT>::functionBody(InHandling inHandling, - YieldHandling yieldHandling, - FunctionSyntaxKind kind, FunctionBodyType type) +GeneralParser<ParseHandler, Unit>::functionBody(InHandling inHandling, YieldHandling yieldHandling, + FunctionSyntaxKind kind, FunctionBodyType type) { MOZ_ASSERT(pc->isFunctionBox()); #ifdef DEBUG uint32_t startYieldOffset = pc->lastYieldOffset; #endif Node body; @@ -3197,19 +3195,19 @@ JSFunction* ParserBase::newFunction(HandleAtom atom, FunctionSyntaxKind kind, GeneratorKind generatorKind, FunctionAsyncKind asyncKind, HandleObject proto) { return AllocNewFunction(context, atom, kind, generatorKind, asyncKind, proto, options().selfHostingMode, pc->isFunctionBox()); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::matchOrInsertSemicolon() +GeneralParser<ParseHandler, Unit>::matchOrInsertSemicolon() { TokenKind tt = TokenKind::Eof; if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand)) { return false; } if (tt != TokenKind::Eof && tt != TokenKind::Eol && tt != TokenKind::Semi && @@ -3291,21 +3289,20 @@ ParserBase::prefixAccessorName(PropertyT RootedString str(context, ConcatStrings<CanGC>(context, prefix, propAtom)); if (!str) { return nullptr; } return AtomizeString(context, str); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::functionArguments(YieldHandling yieldHandling, - FunctionSyntaxKind kind, - CodeNodeType funNode) +GeneralParser<ParseHandler, Unit>::functionArguments(YieldHandling yieldHandling, + FunctionSyntaxKind kind, CodeNodeType funNode) { FunctionBox* funbox = pc->functionBox(); bool parenFreeArrow = false; // Modifier for the following tokens. // TokenStream::None for the following cases: // async a => 1 // ^ @@ -3603,20 +3600,20 @@ GeneralParser<ParseHandler, CharT>::func } else if (kind == FunctionSyntaxKind::Setter) { error(JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", ""); return false; } return true; } -template <typename CharT> +template <typename Unit> bool -Parser<FullParseHandler, CharT>::skipLazyInnerFunction(CodeNode* funNode, uint32_t toStringStart, - FunctionSyntaxKind kind, bool tryAnnexB) +Parser<FullParseHandler, Unit>::skipLazyInnerFunction(CodeNode* funNode, uint32_t toStringStart, + FunctionSyntaxKind kind, bool tryAnnexB) { // When a lazily-parsed function is called, we only fully parse (and emit) // that function, not any of its nested children. The initial syntax-only // parse recorded the free variables of nested functions and their extents, // so we can skip over them after accounting for their free variables. RootedFunction fun(context, handler.nextLazyInnerFunction()); FunctionBox* funbox = @@ -3640,41 +3637,39 @@ Parser<FullParseHandler, CharT>::skipLaz // Append possible Annex B function box only upon successfully parsing. if (tryAnnexB && !pc->innermostScope()->addPossibleAnnexBFunctionBox(pc, funbox)) { return false; } return true; } -template <typename CharT> +template <typename Unit> bool -Parser<SyntaxParseHandler, CharT>::skipLazyInnerFunction(CodeNodeType funNode, - uint32_t toStringStart, - FunctionSyntaxKind kind, - bool tryAnnexB) +Parser<SyntaxParseHandler, Unit>::skipLazyInnerFunction(CodeNodeType funNode, + uint32_t toStringStart, + FunctionSyntaxKind kind, bool tryAnnexB) { MOZ_CRASH("Cannot skip lazy inner functions when syntax parsing"); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::skipLazyInnerFunction(CodeNodeType funNode, - uint32_t toStringStart, - FunctionSyntaxKind kind, - bool tryAnnexB) +GeneralParser<ParseHandler, Unit>::skipLazyInnerFunction(CodeNodeType funNode, + uint32_t toStringStart, + FunctionSyntaxKind kind, bool tryAnnexB) { return asFinalParser()->skipLazyInnerFunction(funNode, toStringStart, kind, tryAnnexB); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::addExprAndGetNextTemplStrToken(YieldHandling yieldHandling, - ListNodeType nodeList, - TokenKind* ttp) +GeneralParser<ParseHandler, Unit>::addExprAndGetNextTemplStrToken(YieldHandling yieldHandling, + ListNodeType nodeList, + TokenKind* ttp) { Node pn = expr(InAllowed, yieldHandling, TripledotProhibited); if (!pn) { return false; } handler.addList(nodeList, pn); TokenKind tt; @@ -3684,21 +3679,20 @@ GeneralParser<ParseHandler, CharT>::addE if (tt != TokenKind::RightCurly) { error(JSMSG_TEMPLSTR_UNTERM_EXPR); return false; } return tokenStream.getToken(ttp, TokenStream::TemplateTail); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::taggedTemplate(YieldHandling yieldHandling, - ListNodeType tagArgsList, - TokenKind tt) +GeneralParser<ParseHandler, Unit>::taggedTemplate(YieldHandling yieldHandling, + ListNodeType tagArgsList, TokenKind tt) { CallSiteNodeType callSiteObjNode = handler.newCallSiteObject(pos().begin); if (!callSiteObjNode) { return false; } handler.addList(tagArgsList, callSiteObjNode); while (true) { @@ -3712,19 +3706,19 @@ GeneralParser<ParseHandler, CharT>::tagg if (!addExprAndGetNextTemplStrToken(yieldHandling, tagArgsList, &tt)) { return false; } } handler.setEndPosition(tagArgsList, callSiteObjNode); return true; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::ListNodeType -GeneralParser<ParseHandler, CharT>::templateLiteral(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::templateLiteral(YieldHandling yieldHandling) { NameNodeType literal = noSubstitutionUntaggedTemplate(); if (!literal) { return null(); } ListNodeType nodeList = handler.newList(ParseNodeKind::TemplateStringList, literal); if (!nodeList) { @@ -3742,25 +3736,25 @@ GeneralParser<ParseHandler, CharT>::temp return null(); } handler.addList(nodeList, literal); } while (tt == TokenKind::TemplateHead); return nodeList; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::CodeNodeType -GeneralParser<ParseHandler, CharT>::functionDefinition(CodeNodeType funNode, uint32_t toStringStart, - InHandling inHandling, - YieldHandling yieldHandling, - HandleAtom funName, FunctionSyntaxKind kind, - GeneratorKind generatorKind, - FunctionAsyncKind asyncKind, - bool tryAnnexB /* = false */) +GeneralParser<ParseHandler, Unit>::functionDefinition(CodeNodeType funNode, uint32_t toStringStart, + InHandling inHandling, + YieldHandling yieldHandling, + HandleAtom funName, FunctionSyntaxKind kind, + GeneratorKind generatorKind, + FunctionAsyncKind asyncKind, + bool tryAnnexB /* = false */) { MOZ_ASSERT_IF(kind == FunctionSyntaxKind::Statement, funName); // When fully parsing a LazyScript, we do not fully reparse its inner // functions, which are also lazy. Instead, their free variables and // source extents are recorded and may be skipped. if (handler.canSkipLazyInnerFunctions()) { if (!skipLazyInnerFunction(funNode, toStringStart, kind, tryAnnexB)) { @@ -3820,29 +3814,28 @@ GeneralParser<ParseHandler, CharT>::func // functionFormalParametersAndBody may have already set body before // failing. handler.setFunctionFormalParametersAndBody(funNode, null()); } return funNode; } -template <typename CharT> +template <typename Unit> bool -Parser<FullParseHandler, CharT>::trySyntaxParseInnerFunction(CodeNode** funNode, - HandleFunction fun, - uint32_t toStringStart, - InHandling inHandling, - YieldHandling yieldHandling, - FunctionSyntaxKind kind, - GeneratorKind generatorKind, - FunctionAsyncKind asyncKind, - bool tryAnnexB, - Directives inheritedDirectives, - Directives* newDirectives) +Parser<FullParseHandler, Unit>::trySyntaxParseInnerFunction(CodeNode** funNode, HandleFunction fun, + uint32_t toStringStart, + InHandling inHandling, + YieldHandling yieldHandling, + FunctionSyntaxKind kind, + GeneratorKind generatorKind, + FunctionAsyncKind asyncKind, + bool tryAnnexB, + Directives inheritedDirectives, + Directives* newDirectives) { // Try a syntax parse for this inner function. do { // If we're assuming this function is an IIFE, always perform a full // parse to avoid the overhead of a lazy syntax-only parse. Although // the prediction may be incorrect, IIFEs are common enough that it // pays off for lots of code. if ((*funNode)->isLikelyIIFE() && @@ -3919,70 +3912,72 @@ Parser<FullParseHandler, CharT>::trySynt if (!innerFunc) { return false; } *funNode = innerFunc; return true; } -template <typename CharT> +template <typename Unit> bool -Parser<SyntaxParseHandler, CharT>::trySyntaxParseInnerFunction(CodeNodeType* funNode, HandleFunction fun, - uint32_t toStringStart, - InHandling inHandling, - YieldHandling yieldHandling, - FunctionSyntaxKind kind, - GeneratorKind generatorKind, - FunctionAsyncKind asyncKind, - bool tryAnnexB, - Directives inheritedDirectives, - Directives* newDirectives) +Parser<SyntaxParseHandler, Unit>::trySyntaxParseInnerFunction(CodeNodeType* funNode, + HandleFunction fun, + uint32_t toStringStart, + InHandling inHandling, + YieldHandling yieldHandling, + FunctionSyntaxKind kind, + GeneratorKind generatorKind, + FunctionAsyncKind asyncKind, + bool tryAnnexB, + Directives inheritedDirectives, + Directives* newDirectives) { // This is already a syntax parser, so just parse the inner function. CodeNodeType innerFunc = innerFunction(*funNode, pc, fun, toStringStart, inHandling, yieldHandling, kind, generatorKind, asyncKind, tryAnnexB, inheritedDirectives, newDirectives); if (!innerFunc) { return false; } *funNode = innerFunc; return true; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> inline bool -GeneralParser<ParseHandler, CharT>::trySyntaxParseInnerFunction(CodeNodeType* funNode, HandleFunction fun, - uint32_t toStringStart, - InHandling inHandling, - YieldHandling yieldHandling, - FunctionSyntaxKind kind, - GeneratorKind generatorKind, - FunctionAsyncKind asyncKind, - bool tryAnnexB, - Directives inheritedDirectives, - Directives* newDirectives) +GeneralParser<ParseHandler, Unit>::trySyntaxParseInnerFunction(CodeNodeType* funNode, + HandleFunction fun, + uint32_t toStringStart, + InHandling inHandling, + YieldHandling yieldHandling, + FunctionSyntaxKind kind, + GeneratorKind generatorKind, + FunctionAsyncKind asyncKind, + bool tryAnnexB, + Directives inheritedDirectives, + Directives* newDirectives) { return asFinalParser()->trySyntaxParseInnerFunction(funNode, fun, toStringStart, inHandling, yieldHandling, kind, generatorKind, asyncKind, tryAnnexB, inheritedDirectives, newDirectives); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::CodeNodeType -GeneralParser<ParseHandler, CharT>::innerFunctionForFunctionBox(CodeNodeType funNode, - ParseContext* outerpc, - FunctionBox* funbox, - InHandling inHandling, - YieldHandling yieldHandling, - FunctionSyntaxKind kind, - Directives* newDirectives) +GeneralParser<ParseHandler, Unit>::innerFunctionForFunctionBox(CodeNodeType funNode, + ParseContext* outerpc, + FunctionBox* funbox, + InHandling inHandling, + YieldHandling yieldHandling, + FunctionSyntaxKind kind, + Directives* newDirectives) { // Note that it is possible for outerpc != this->pc, as we may be // attempting to syntax parse an inner function from an outer full // parser. In that case, outerpc is a SourceParseContext from the full parser // instead of the current top of the stack of the syntax parser. // Push a new ParseContext. SourceParseContext funpc(this, funbox, newDirectives); @@ -3996,27 +3991,27 @@ GeneralParser<ParseHandler, CharT>::inne if (!leaveInnerFunction(outerpc)) { return null(); } return funNode; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::CodeNodeType -GeneralParser<ParseHandler, CharT>::innerFunction(CodeNodeType funNode, ParseContext* outerpc, - HandleFunction fun, uint32_t toStringStart, - InHandling inHandling, - YieldHandling yieldHandling, - FunctionSyntaxKind kind, - GeneratorKind generatorKind, - FunctionAsyncKind asyncKind, bool tryAnnexB, - Directives inheritedDirectives, - Directives* newDirectives) +GeneralParser<ParseHandler, Unit>::innerFunction(CodeNodeType funNode, ParseContext* outerpc, + HandleFunction fun, uint32_t toStringStart, + InHandling inHandling, + YieldHandling yieldHandling, + FunctionSyntaxKind kind, + GeneratorKind generatorKind, + FunctionAsyncKind asyncKind, bool tryAnnexB, + Directives inheritedDirectives, + Directives* newDirectives) { // Note that it is possible for outerpc != this->pc, as we may be // attempting to syntax parse an inner function from an outer full // parser. In that case, outerpc is a SourceParseContext from the full parser // instead of the current top of the stack of the syntax parser. FunctionBox* funbox = newFunctionBox(funNode, fun, toStringStart, inheritedDirectives, generatorKind, asyncKind); @@ -4037,19 +4032,19 @@ GeneralParser<ParseHandler, CharT>::inne if (!pc->innermostScope()->addPossibleAnnexBFunctionBox(pc, funbox)) { return null(); } } return innerFunc; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::appendToCallSiteObj(CallSiteNodeType callSiteObj) +GeneralParser<ParseHandler, Unit>::appendToCallSiteObj(CallSiteNodeType callSiteObj) { Node cookedNode = noSubstitutionTaggedTemplate(); if (!cookedNode) { return false; } JSAtom* atom = tokenStream.getRawTemplateStringAtom(); if (!atom) { @@ -4059,21 +4054,21 @@ GeneralParser<ParseHandler, CharT>::appe if (!rawNode) { return false; } handler.addToCallSiteObject(callSiteObj, rawNode, cookedNode); return true; } -template <typename CharT> +template <typename Unit> CodeNode* -Parser<FullParseHandler, CharT>::standaloneLazyFunction(HandleFunction fun, uint32_t toStringStart, - bool strict, GeneratorKind generatorKind, - FunctionAsyncKind asyncKind) +Parser<FullParseHandler, Unit>::standaloneLazyFunction(HandleFunction fun, uint32_t toStringStart, + bool strict, GeneratorKind generatorKind, + FunctionAsyncKind asyncKind) { MOZ_ASSERT(checkOptionsCalled); CodeNodeType funNode = handler.newFunctionStatement(pos()); if (!funNode) { return null(); } @@ -4126,41 +4121,41 @@ Parser<FullParseHandler, CharT>::standal if (!FoldConstants(context, &node, this)) { return null(); } funNode = &node->as<CodeNode>(); return funNode; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::functionFormalParametersAndBody(InHandling inHandling, - YieldHandling yieldHandling, - CodeNodeType* funNode, - FunctionSyntaxKind kind, - const Maybe<uint32_t>& parameterListEnd /* = Nothing() */, - bool isStandaloneFunction /* = false */) +GeneralParser<ParseHandler, Unit>::functionFormalParametersAndBody(InHandling inHandling, + YieldHandling yieldHandling, + CodeNodeType* funNode, + FunctionSyntaxKind kind, + const Maybe<uint32_t>& parameterListEnd /* = Nothing() */, + bool isStandaloneFunction /* = false */) { // Given a properly initialized parse context, try to parse an actual // function without concern for conversion to strict mode, use of lazy // parsing and such. FunctionBox* funbox = pc->functionBox(); RootedFunction fun(context, funbox->function()); // See below for an explanation why arrow function parameters and arrow // function bodies are parsed with different yield/await settings. { AwaitHandling awaitHandling = (funbox->isAsync() || (kind == FunctionSyntaxKind::Arrow && awaitIsKeyword())) ? AwaitIsKeyword : AwaitIsName; - AutoAwaitIsKeyword<ParseHandler, CharT> awaitIsKeyword(this, awaitHandling); - AutoInParametersOfAsyncFunction<ParseHandler, CharT> inParameters(this, funbox->isAsync()); + AutoAwaitIsKeyword<ParseHandler, Unit> awaitIsKeyword(this, awaitHandling); + AutoInParametersOfAsyncFunction<ParseHandler, Unit> inParameters(this, funbox->isAsync()); if (!functionArguments(yieldHandling, kind, *funNode)) { return false; } } Maybe<ParseContext::VarScope> varScope; if (funbox->hasParameterExprs) { varScope.emplace(this); @@ -4215,18 +4210,18 @@ GeneralParser<ParseHandler, CharT>::func // whether the arrow function is enclosed in a generator function or not. // Whereas the |yield| in the function body is always parsed as a name. // The same goes when parsing |await| in arrow functions. YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind()); AwaitHandling bodyAwaitHandling = GetAwaitHandling(pc->asyncKind()); bool inheritedStrict = pc->sc()->strict(); LexicalScopeNodeType body; { - AutoAwaitIsKeyword<ParseHandler, CharT> awaitIsKeyword(this, bodyAwaitHandling); - AutoInParametersOfAsyncFunction<ParseHandler, CharT> inParameters(this, false); + AutoAwaitIsKeyword<ParseHandler, Unit> awaitIsKeyword(this, bodyAwaitHandling); + AutoInParametersOfAsyncFunction<ParseHandler, Unit> inParameters(this, false); body = functionBody(inHandling, bodyYieldHandling, kind, bodyType); if (!body) { return false; } } // Revalidate the function name when we transitioned to strict mode. if ((kind == FunctionSyntaxKind::Statement || kind == FunctionSyntaxKind::Expression) && @@ -4286,22 +4281,22 @@ GeneralParser<ParseHandler, CharT>::func handler.setEndPosition(body, pos().begin); handler.setEndPosition(*funNode, pos().end); handler.setFunctionBody(*funNode, body); return true; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::CodeNodeType -GeneralParser<ParseHandler, CharT>::functionStmt(uint32_t toStringStart, - YieldHandling yieldHandling, - DefaultHandling defaultHandling, - FunctionAsyncKind asyncKind) +GeneralParser<ParseHandler, Unit>::functionStmt(uint32_t toStringStart, + YieldHandling yieldHandling, + DefaultHandling defaultHandling, + FunctionAsyncKind asyncKind) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Function)); // In sloppy mode, Annex B.3.2 allows labelled function declarations. // Otherwise it's a parse error. ParseContext::Statement* declaredInStmt = pc->innermostStatement(); if (declaredInStmt && declaredInStmt->kind() == StatementKind::Label) { MOZ_ASSERT(!pc->sc()->strict(), @@ -4383,25 +4378,24 @@ GeneralParser<ParseHandler, CharT>::func // Scope::propagateAndMarkAnnexBFunctionBoxes. bool tryAnnexB = kind == DeclarationKind::SloppyLexicalFunction; YieldHandling newYieldHandling = GetYieldHandling(generatorKind); return functionDefinition(funNode, toStringStart, InAllowed, newYieldHandling, name, FunctionSyntaxKind::Statement, generatorKind, asyncKind, tryAnnexB); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::CodeNodeType -GeneralParser<ParseHandler, CharT>::functionExpr(uint32_t toStringStart, - InvokedPrediction invoked, - FunctionAsyncKind asyncKind) +GeneralParser<ParseHandler, Unit>::functionExpr(uint32_t toStringStart, InvokedPrediction invoked, + FunctionAsyncKind asyncKind) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Function)); - AutoAwaitIsKeyword<ParseHandler, CharT> awaitIsKeyword(this, GetAwaitHandling(asyncKind)); + AutoAwaitIsKeyword<ParseHandler, Unit> awaitIsKeyword(this, GetAwaitHandling(asyncKind)); GeneratorKind generatorKind = GeneratorKind::NotGenerator; TokenKind tt; if (!tokenStream.getToken(&tt)) { return null(); } if (tt == TokenKind::Mul) { generatorKind = GeneratorKind::Generator; @@ -4448,19 +4442,19 @@ IsEscapeFreeStringLiteral(const TokenPos /* * If the string's length in the source code is its length as a value, * accounting for the quotes, then it must not contain any escape * sequences or line continuations. */ return pos.begin + str->length() + 2 == pos.end; } -template <typename CharT> +template <typename Unit> bool -Parser<SyntaxParseHandler, CharT>::asmJS(ListNodeType list) +Parser<SyntaxParseHandler, Unit>::asmJS(ListNodeType list) { // While asm.js could technically be validated and compiled during syntax // parsing, we have no guarantee that some later JS wouldn't abort the // syntax parse and cause us to re-parse (and re-compile) the asm.js module. // For simplicity, unconditionally abort the syntax parse when "use asm" is // encountered so that asm.js is always validated/compiled exactly once // during a full parse. MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); @@ -4520,19 +4514,19 @@ bool Parser<FullParseHandler, Utf8Unit>::asmJS(ListNodeType list) { // Just succeed without setting the asm.js directive flag. Given Web // Assembly's rapid advance, it's probably not worth the trouble to really // support UTF-8 asm.js. return true; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> inline bool -GeneralParser<ParseHandler, CharT>::asmJS(ListNodeType list) +GeneralParser<ParseHandler, Unit>::asmJS(ListNodeType list) { return asFinalParser()->asmJS(list); } /* * Recognize Directive Prologue members and directives. Assuming |pn| is a * candidate for membership in a directive prologue, recognize directives and * set |pc|'s flags accordingly. If |pn| is indeed part of a prologue, set its @@ -4546,20 +4540,20 @@ GeneralParser<ParseHandler, CharT>::asmJ * "use\x20loose" * "use strict" * } * * That is, even though "use\x20loose" can never be a directive, now or in the * future (because of the hex escape), the Directive Prologue extends through it * to the "use strict" statement, which is indeed a directive. */ -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::maybeParseDirective(ListNodeType list, Node possibleDirective, - bool* cont) +GeneralParser<ParseHandler, Unit>::maybeParseDirective(ListNodeType list, Node possibleDirective, + bool* cont) { TokenPos directivePos; JSAtom* directive = handler.isStringExprStatement(possibleDirective, &directivePos); *cont = !!directive; if (!*cont) { return true; } @@ -4612,19 +4606,19 @@ GeneralParser<ParseHandler, CharT>::mayb return asmJS(list); } return warningAt(directivePos.begin, JSMSG_USE_ASM_DIRECTIVE_FAIL); } } return true; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::ListNodeType -GeneralParser<ParseHandler, CharT>::statementList(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::statementList(YieldHandling yieldHandling) { if (!CheckRecursionLimit(context)) { return null(); } ListNodeType stmtList = handler.newStatementList(pos()); if (!stmtList) { return null(); @@ -4686,19 +4680,19 @@ GeneralParser<ParseHandler, CharT>::stat } handler.addStatementToList(stmtList, next); } return stmtList; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::condition(InHandling inHandling, YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::condition(InHandling inHandling, YieldHandling yieldHandling) { MUST_MATCH_TOKEN(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_COND); Node pn = exprInParens(inHandling, yieldHandling, TripledotProhibited); if (!pn) { return null(); } @@ -4708,20 +4702,20 @@ GeneralParser<ParseHandler, CharT>::cond if (handler.isUnparenthesizedAssignment(pn)) { if (!extraWarning(JSMSG_EQUAL_AS_ASSIGN)) { return null(); } } return pn; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::matchLabel(YieldHandling yieldHandling, - MutableHandle<PropertyName*> label) +GeneralParser<ParseHandler, Unit>::matchLabel(YieldHandling yieldHandling, + MutableHandle<PropertyName*> label) { TokenKind tt = TokenKind::Eof; if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand)) { return false; } if (TokenKindIsPossibleIdentifier(tt)) { tokenStream.consumeKnownToken(tt, TokenStream::Operand); @@ -4731,180 +4725,180 @@ GeneralParser<ParseHandler, CharT>::matc return false; } } else { label.set(nullptr); } return true; } -template <class ParseHandler, typename CharT> -GeneralParser<ParseHandler, CharT>::PossibleError::PossibleError(GeneralParser<ParseHandler, CharT>& parser) +template <class ParseHandler, typename Unit> +GeneralParser<ParseHandler, Unit>::PossibleError::PossibleError(GeneralParser<ParseHandler, Unit>& parser) : parser_(parser) {} -template <class ParseHandler, typename CharT> -typename GeneralParser<ParseHandler, CharT>::PossibleError::Error& -GeneralParser<ParseHandler, CharT>::PossibleError::error(ErrorKind kind) +template <class ParseHandler, typename Unit> +typename GeneralParser<ParseHandler, Unit>::PossibleError::Error& +GeneralParser<ParseHandler, Unit>::PossibleError::error(ErrorKind kind) { if (kind == ErrorKind::Expression) { return exprError_; } if (kind == ErrorKind::Destructuring) { return destructuringError_; } MOZ_ASSERT(kind == ErrorKind::DestructuringWarning); return destructuringWarning_; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::PossibleError::setResolved(ErrorKind kind) +GeneralParser<ParseHandler, Unit>::PossibleError::setResolved(ErrorKind kind) { error(kind).state_ = ErrorState::None; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::PossibleError::hasError(ErrorKind kind) +GeneralParser<ParseHandler, Unit>::PossibleError::hasError(ErrorKind kind) { return error(kind).state_ == ErrorState::Pending; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::PossibleError::hasPendingDestructuringError() +GeneralParser<ParseHandler, Unit>::PossibleError::hasPendingDestructuringError() { return hasError(ErrorKind::Destructuring); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::PossibleError::setPending(ErrorKind kind, const TokenPos& pos, - unsigned errorNumber) +GeneralParser<ParseHandler, Unit>::PossibleError::setPending(ErrorKind kind, const TokenPos& pos, + unsigned errorNumber) { // Don't overwrite a previously recorded error. if (hasError(kind)) { return; } // If we report an error later, we'll do it from the position where we set // the state to pending. Error& err = error(kind); err.offset_ = pos.begin; err.errorNumber_ = errorNumber; err.state_ = ErrorState::Pending; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::PossibleError::setPendingDestructuringErrorAt(const TokenPos& pos, - unsigned errorNumber) +GeneralParser<ParseHandler, Unit>::PossibleError::setPendingDestructuringErrorAt(const TokenPos& pos, + unsigned errorNumber) { setPending(ErrorKind::Destructuring, pos, errorNumber); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::PossibleError::setPendingDestructuringWarningAt(const TokenPos& pos, - unsigned errorNumber) +GeneralParser<ParseHandler, Unit>::PossibleError::setPendingDestructuringWarningAt(const TokenPos& pos, + unsigned errorNumber) { setPending(ErrorKind::DestructuringWarning, pos, errorNumber); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::PossibleError::setPendingExpressionErrorAt(const TokenPos& pos, - unsigned errorNumber) +GeneralParser<ParseHandler, Unit>::PossibleError::setPendingExpressionErrorAt(const TokenPos& pos, + unsigned errorNumber) { setPending(ErrorKind::Expression, pos, errorNumber); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::PossibleError::checkForError(ErrorKind kind) +GeneralParser<ParseHandler, Unit>::PossibleError::checkForError(ErrorKind kind) { if (!hasError(kind)) { return true; } Error& err = error(kind); parser_.errorAt(err.offset_, err.errorNumber_); return false; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::PossibleError::checkForWarning(ErrorKind kind) +GeneralParser<ParseHandler, Unit>::PossibleError::checkForWarning(ErrorKind kind) { if (!hasError(kind)) { return true; } Error& err = error(kind); return parser_.extraWarningAt(err.offset_, err.errorNumber_); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::PossibleError::checkForDestructuringErrorOrWarning() +GeneralParser<ParseHandler, Unit>::PossibleError::checkForDestructuringErrorOrWarning() { // Clear pending expression error, because we're definitely not in an // expression context. setResolved(ErrorKind::Expression); // Report any pending destructuring error or warning. return checkForError(ErrorKind::Destructuring) && checkForWarning(ErrorKind::DestructuringWarning); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::PossibleError::checkForExpressionError() +GeneralParser<ParseHandler, Unit>::PossibleError::checkForExpressionError() { // Clear pending destructuring error or warning, because we're definitely // not in a destructuring context. setResolved(ErrorKind::Destructuring); setResolved(ErrorKind::DestructuringWarning); // Report any pending expression error. return checkForError(ErrorKind::Expression); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::PossibleError::transferErrorTo(ErrorKind kind, - PossibleError* other) +GeneralParser<ParseHandler, Unit>::PossibleError::transferErrorTo(ErrorKind kind, + PossibleError* other) { if (hasError(kind) && !other->hasError(kind)) { Error& err = error(kind); Error& otherErr = other->error(kind); otherErr.offset_ = err.offset_; otherErr.errorNumber_ = err.errorNumber_; otherErr.state_ = err.state_; } } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::PossibleError::transferErrorsTo(PossibleError* other) +GeneralParser<ParseHandler, Unit>::PossibleError::transferErrorsTo(PossibleError* other) { MOZ_ASSERT(other); MOZ_ASSERT(this != other); MOZ_ASSERT(&parser_ == &other->parser_, "Can't transfer fields to an instance which belongs to a different parser"); transferErrorTo(ErrorKind::Destructuring, other); transferErrorTo(ErrorKind::Expression, other); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::BinaryNodeType -GeneralParser<ParseHandler, CharT>::bindingInitializer(Node lhs, DeclarationKind kind, - YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::bindingInitializer(Node lhs, DeclarationKind kind, + YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Assign)); if (kind == DeclarationKind::FormalParameter) { pc->functionBox()->hasParameterExprs = true; } Node rhs = assignExpr(InAllowed, yieldHandling, TripledotProhibited); @@ -4923,39 +4917,39 @@ GeneralParser<ParseHandler, CharT>::bind return null(); } assign = handler.asBinary(node); } return assign; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::NameNodeType -GeneralParser<ParseHandler, CharT>::bindingIdentifier(DeclarationKind kind, - YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::bindingIdentifier(DeclarationKind kind, + YieldHandling yieldHandling) { RootedPropertyName name(context, bindingIdentifier(yieldHandling)); if (!name) { return null(); } NameNodeType binding = newName(name); if (!binding || !noteDeclaredName(name, kind, pos())) { return null(); } return binding; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::bindingIdentifierOrPattern(DeclarationKind kind, - YieldHandling yieldHandling, - TokenKind tt) +GeneralParser<ParseHandler, Unit>::bindingIdentifierOrPattern(DeclarationKind kind, + YieldHandling yieldHandling, + TokenKind tt) { if (tt == TokenKind::LeftBracket) { return arrayBindingPattern(kind, yieldHandling); } if (tt == TokenKind::LeftCurly) { return objectBindingPattern(kind, yieldHandling); } @@ -4963,20 +4957,20 @@ GeneralParser<ParseHandler, CharT>::bind if (!TokenKindIsPossibleIdentifierName(tt)) { error(JSMSG_NO_VARIABLE_NAME); return null(); } return bindingIdentifier(kind, yieldHandling); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::ListNodeType -GeneralParser<ParseHandler, CharT>::objectBindingPattern(DeclarationKind kind, - YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::objectBindingPattern(DeclarationKind kind, + YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftCurly)); if (!CheckRecursionLimit(context)) { return null(); } uint32_t begin = pos().begin; @@ -5110,20 +5104,20 @@ GeneralParser<ParseHandler, CharT>::obje MUST_MATCH_TOKEN_MOD_WITH_REPORT(TokenKind::RightCurly, TokenStream::Operand, reportMissingClosing(JSMSG_CURLY_AFTER_LIST, JSMSG_CURLY_OPENED, begin)); handler.setEndPosition(literal, pos().end); return literal; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::ListNodeType -GeneralParser<ParseHandler, CharT>::arrayBindingPattern(DeclarationKind kind, - YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::arrayBindingPattern(DeclarationKind kind, + YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftBracket)); if (!CheckRecursionLimit(context)) { return null(); } uint32_t begin = pos().begin; @@ -5211,35 +5205,35 @@ GeneralParser<ParseHandler, CharT>::arra MUST_MATCH_TOKEN_MOD_WITH_REPORT(TokenKind::RightBracket, TokenStream::Operand, reportMissingClosing(JSMSG_BRACKET_AFTER_LIST, JSMSG_BRACKET_OPENED, begin)); handler.setEndPosition(literal, pos().end); return literal; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::destructuringDeclaration(DeclarationKind kind, - YieldHandling yieldHandling, - TokenKind tt) +GeneralParser<ParseHandler, Unit>::destructuringDeclaration(DeclarationKind kind, + YieldHandling yieldHandling, + TokenKind tt) { MOZ_ASSERT(anyChars.isCurrentTokenType(tt)); MOZ_ASSERT(tt == TokenKind::LeftBracket || tt == TokenKind::LeftCurly); return tt == TokenKind::LeftBracket ? arrayBindingPattern(kind, yieldHandling) : objectBindingPattern(kind, yieldHandling); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::destructuringDeclarationWithoutYieldOrAwait(DeclarationKind kind, - YieldHandling yieldHandling, - TokenKind tt) +GeneralParser<ParseHandler, Unit>::destructuringDeclarationWithoutYieldOrAwait(DeclarationKind kind, + YieldHandling yieldHandling, + TokenKind tt) { uint32_t startYieldOffset = pc->lastYieldOffset; uint32_t startAwaitOffset = pc->lastAwaitOffset; Node res = destructuringDeclaration(kind, yieldHandling, tt); if (res) { if (pc->lastYieldOffset != startYieldOffset) { errorAt(pc->lastYieldOffset, JSMSG_YIELD_IN_PARAMETER); return null(); @@ -5247,20 +5241,20 @@ GeneralParser<ParseHandler, CharT>::dest if (pc->lastAwaitOffset != startAwaitOffset) { errorAt(pc->lastAwaitOffset, JSMSG_AWAIT_IN_PARAMETER); return null(); } } return res; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::LexicalScopeNodeType -GeneralParser<ParseHandler, CharT>::blockStatement(YieldHandling yieldHandling, - unsigned errorNumber) +GeneralParser<ParseHandler, Unit>::blockStatement(YieldHandling yieldHandling, + unsigned errorNumber) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftCurly)); uint32_t openedPos = pos().begin; ParseContext::Statement stmt(pc, StatementKind::Block); ParseContext::Scope scope(this); if (!scope.init(pc)) { return null(); @@ -5273,35 +5267,35 @@ GeneralParser<ParseHandler, CharT>::bloc MUST_MATCH_TOKEN_MOD_WITH_REPORT(TokenKind::RightCurly, TokenStream::Operand, reportMissingClosing(errorNumber, JSMSG_CURLY_OPENED, openedPos)); return finishLexicalScope(scope, list); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::expressionAfterForInOrOf(ParseNodeKind forHeadKind, - YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::expressionAfterForInOrOf(ParseNodeKind forHeadKind, + YieldHandling yieldHandling) { MOZ_ASSERT(forHeadKind == ParseNodeKind::ForIn || forHeadKind == ParseNodeKind::ForOf); Node pn = forHeadKind == ParseNodeKind::ForOf ? assignExpr(InAllowed, yieldHandling, TripledotProhibited) : expr(InAllowed, yieldHandling, TripledotProhibited); return pn; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::declarationPattern(DeclarationKind declKind, TokenKind tt, - bool initialDeclaration, - YieldHandling yieldHandling, - ParseNodeKind* forHeadKind, - Node* forInOrOfExpression) +GeneralParser<ParseHandler, Unit>::declarationPattern(DeclarationKind declKind, TokenKind tt, + bool initialDeclaration, + YieldHandling yieldHandling, + ParseNodeKind* forHeadKind, + Node* forInOrOfExpression) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftBracket) || anyChars.isCurrentTokenType(TokenKind::LeftCurly)); Node pattern = destructuringDeclaration(declKind, yieldHandling, tt); if (!pattern) { return null(); } @@ -5341,24 +5335,24 @@ GeneralParser<ParseHandler, CharT>::decl yieldHandling, TripledotProhibited); if (!init) { return null(); } return handler.newAssignment(ParseNodeKind::Assign, pattern, init); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::initializerInNameDeclaration(NameNodeType binding, - DeclarationKind declKind, - bool initialDeclaration, - YieldHandling yieldHandling, - ParseNodeKind* forHeadKind, - Node* forInOrOfExpression) +GeneralParser<ParseHandler, Unit>::initializerInNameDeclaration(NameNodeType binding, + DeclarationKind declKind, + bool initialDeclaration, + YieldHandling yieldHandling, + ParseNodeKind* forHeadKind, + Node* forInOrOfExpression) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Assign)); uint32_t initializerOffset; if (!tokenStream.peekOffset(&initializerOffset, TokenStream::Operand)) { return false; } @@ -5405,23 +5399,23 @@ GeneralParser<ParseHandler, CharT>::init } else { *forHeadKind = ParseNodeKind::ForHead; } } return handler.finishInitializerAssignment(binding, initializer); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::NameNodeType -GeneralParser<ParseHandler, CharT>::declarationName(DeclarationKind declKind, TokenKind tt, - bool initialDeclaration, - YieldHandling yieldHandling, - ParseNodeKind* forHeadKind, - Node* forInOrOfExpression) +GeneralParser<ParseHandler, Unit>::declarationName(DeclarationKind declKind, TokenKind tt, + bool initialDeclaration, + YieldHandling yieldHandling, + ParseNodeKind* forHeadKind, + Node* forInOrOfExpression) { // Anything other than possible identifier is an error. if (!TokenKindIsPossibleIdentifier(tt)) { error(JSMSG_NO_VARIABLE_NAME); return null(); } RootedPropertyName name(context, bindingIdentifier(yieldHandling)); @@ -5494,22 +5488,22 @@ GeneralParser<ParseHandler, CharT>::decl // loop, due to special early error semantics in Annex B.3.5. if (!noteDeclaredName(name, declKind, namePos)) { return null(); } return binding; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::ListNodeType -GeneralParser<ParseHandler, CharT>::declarationList(YieldHandling yieldHandling, - ParseNodeKind kind, - ParseNodeKind* forHeadKind /* = nullptr */, - Node* forInOrOfExpression /* = nullptr */) +GeneralParser<ParseHandler, Unit>::declarationList(YieldHandling yieldHandling, + ParseNodeKind kind, + ParseNodeKind* forHeadKind /* = nullptr */, + Node* forInOrOfExpression /* = nullptr */) { MOZ_ASSERT(kind == ParseNodeKind::Var || kind == ParseNodeKind::Let || kind == ParseNodeKind::Const); DeclarationKind declKind; switch (kind) { case ParseNodeKind::Var: @@ -5563,20 +5557,20 @@ GeneralParser<ParseHandler, CharT>::decl if (!tokenStream.matchToken(&moreDeclarations, TokenKind::Comma, TokenStream::Operand)) { return null(); } } while (moreDeclarations); return decl; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::ListNodeType -GeneralParser<ParseHandler, CharT>::lexicalDeclaration(YieldHandling yieldHandling, - DeclarationKind kind) +GeneralParser<ParseHandler, Unit>::lexicalDeclaration(YieldHandling yieldHandling, + DeclarationKind kind) { MOZ_ASSERT(kind == DeclarationKind::Const || kind == DeclarationKind::Let); /* * Parse body-level lets without a new block object. ES6 specs * that an execution environment's initial lexical environment * is the VariableEnvironment, i.e., body-level lets are in * the same environment record as vars. @@ -5592,20 +5586,20 @@ GeneralParser<ParseHandler, CharT>::lexi : ParseNodeKind::Let); if (!decl || !matchOrInsertSemicolon()) { return null(); } return decl; } -template <typename CharT> +template <typename Unit> bool -Parser<FullParseHandler, CharT>::namedImportsOrNamespaceImport(TokenKind tt, - ListNodeType importSpecSet) +Parser<FullParseHandler, Unit>::namedImportsOrNamespaceImport(TokenKind tt, + ListNodeType importSpecSet) { if (tt == TokenKind::LeftCurly) { while (true) { // Handle the forms |import {} from 'a'| and // |import { ..., } from 'a'| (where ... is non empty), by // escaping the loop early if the next token is }. if (!tokenStream.getToken(&tt)) { return false; @@ -5726,19 +5720,19 @@ Parser<FullParseHandler, CharT>::namedIm } handler.addList(importSpecSet, importSpec); } return true; } -template<typename CharT> +template<typename Unit> BinaryNode* -Parser<FullParseHandler, CharT>::importDeclaration() +Parser<FullParseHandler, Unit>::importDeclaration() { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Import)); if (!pc->atModuleLevel()) { error(JSMSG_IMPORT_DECL_AT_TOP_LEVEL); return null(); } @@ -5835,84 +5829,84 @@ Parser<FullParseHandler, CharT>::importD handler.newImportDeclaration(importSpecSet, moduleSpec, TokenPos(begin, pos().end)); if (!node || !pc->sc()->asModuleContext()->builder.processImport(node)) { return null(); } return node; } -template<typename CharT> +template<typename Unit> inline SyntaxParseHandler::BinaryNodeType -Parser<SyntaxParseHandler, CharT>::importDeclaration() +Parser<SyntaxParseHandler, Unit>::importDeclaration() { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return SyntaxParseHandler::NodeFailure; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> inline typename ParseHandler::BinaryNodeType -GeneralParser<ParseHandler, CharT>::importDeclaration() +GeneralParser<ParseHandler, Unit>::importDeclaration() { return asFinalParser()->importDeclaration(); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> inline typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::importDeclarationOrImportExpr(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::importDeclarationOrImportExpr(YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Import)); TokenKind tt; if (!tokenStream.peekToken(&tt)) { return null(); } if (tt == TokenKind::Dot || tt == TokenKind::LeftParen) { return expressionStatement(yieldHandling); } return importDeclaration(); } -template<typename CharT> +template<typename Unit> bool -Parser<FullParseHandler, CharT>::checkExportedName(JSAtom* exportName) +Parser<FullParseHandler, Unit>::checkExportedName(JSAtom* exportName) { if (!pc->sc()->asModuleContext()->builder.hasExportedName(exportName)) { return true; } UniqueChars str = AtomToPrintableString(context, exportName); if (!str) { return false; } error(JSMSG_DUPLICATE_EXPORT_NAME, str.get()); return false; } -template<typename CharT> +template<typename Unit> inline bool -Parser<SyntaxParseHandler, CharT>::checkExportedName(JSAtom* exportName) +Parser<SyntaxParseHandler, Unit>::checkExportedName(JSAtom* exportName) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return false; } -template<class ParseHandler, typename CharT> +template<class ParseHandler, typename Unit> inline bool -GeneralParser<ParseHandler, CharT>::checkExportedName(JSAtom* exportName) +GeneralParser<ParseHandler, Unit>::checkExportedName(JSAtom* exportName) { return asFinalParser()->checkExportedName(exportName); } -template<typename CharT> +template<typename Unit> bool -Parser<FullParseHandler, CharT>::checkExportedNamesForArrayBinding(ListNode* array) +Parser<FullParseHandler, Unit>::checkExportedNamesForArrayBinding(ListNode* array) { MOZ_ASSERT(array->isKind(ParseNodeKind::Array)); for (ParseNode* node : array->contents()) { if (node->isKind(ParseNodeKind::Elision)) { continue; } @@ -5928,34 +5922,34 @@ Parser<FullParseHandler, CharT>::checkEx if (!checkExportedNamesForDeclaration(binding)) { return false; } } return true; } -template<typename CharT> +template<typename Unit> inline bool -Parser<SyntaxParseHandler, CharT>::checkExportedNamesForArrayBinding(ListNodeType array) +Parser<SyntaxParseHandler, Unit>::checkExportedNamesForArrayBinding(ListNodeType array) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return false; } -template<class ParseHandler, typename CharT> +template<class ParseHandler, typename Unit> inline bool -GeneralParser<ParseHandler, CharT>::checkExportedNamesForArrayBinding(ListNodeType array) +GeneralParser<ParseHandler, Unit>::checkExportedNamesForArrayBinding(ListNodeType array) { return asFinalParser()->checkExportedNamesForArrayBinding(array); } -template<typename CharT> +template<typename Unit> bool -Parser<FullParseHandler, CharT>::checkExportedNamesForObjectBinding(ListNode* obj) +Parser<FullParseHandler, Unit>::checkExportedNamesForObjectBinding(ListNode* obj) { MOZ_ASSERT(obj->isKind(ParseNodeKind::Object)); for (ParseNode* node : obj->contents()) { MOZ_ASSERT(node->isKind(ParseNodeKind::MutateProto) || node->isKind(ParseNodeKind::Colon) || node->isKind(ParseNodeKind::Shorthand) || node->isKind(ParseNodeKind::Spread)); @@ -5978,34 +5972,34 @@ Parser<FullParseHandler, CharT>::checkEx if (!checkExportedNamesForDeclaration(target)) { return false; } } return true; } -template<typename CharT> +template<typename Unit> inline bool -Parser<SyntaxParseHandler, CharT>::checkExportedNamesForObjectBinding(ListNodeType obj) +Parser<SyntaxParseHandler, Unit>::checkExportedNamesForObjectBinding(ListNodeType obj) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return false; } -template<class ParseHandler, typename CharT> +template<class ParseHandler, typename Unit> inline bool -GeneralParser<ParseHandler, CharT>::checkExportedNamesForObjectBinding(ListNodeType obj) +GeneralParser<ParseHandler, Unit>::checkExportedNamesForObjectBinding(ListNodeType obj) { return asFinalParser()->checkExportedNamesForObjectBinding(obj); } -template<typename CharT> +template<typename Unit> bool -Parser<FullParseHandler, CharT>::checkExportedNamesForDeclaration(ParseNode* node) +Parser<FullParseHandler, Unit>::checkExportedNamesForDeclaration(ParseNode* node) { if (node->isKind(ParseNodeKind::Name)) { if (!checkExportedName(node->as<NameNode>().atom())) { return false; } } else if (node->isKind(ParseNodeKind::Array)) { if (!checkExportedNamesForArrayBinding(&node->as<ListNode>())) { return false; @@ -6015,128 +6009,128 @@ Parser<FullParseHandler, CharT>::checkEx if (!checkExportedNamesForObjectBinding(&node->as<ListNode>())) { return false; } } return true; } -template<typename CharT> +template<typename Unit> inline bool -Parser<SyntaxParseHandler, CharT>::checkExportedNamesForDeclaration(Node node) +Parser<SyntaxParseHandler, Unit>::checkExportedNamesForDeclaration(Node node) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return false; } -template<class ParseHandler, typename CharT> +template<class ParseHandler, typename Unit> inline bool -GeneralParser<ParseHandler, CharT>::checkExportedNamesForDeclaration(Node node) +GeneralParser<ParseHandler, Unit>::checkExportedNamesForDeclaration(Node node) { return asFinalParser()->checkExportedNamesForDeclaration(node); } -template<typename CharT> +template<typename Unit> bool -Parser<FullParseHandler, CharT>::checkExportedNamesForDeclarationList(ListNode* node) +Parser<FullParseHandler, Unit>::checkExportedNamesForDeclarationList(ListNode* node) { for (ParseNode* binding : node->contents()) { if (binding->isKind(ParseNodeKind::Assign)) { binding = binding->as<AssignmentNode>().left(); } else { MOZ_ASSERT(binding->isKind(ParseNodeKind::Name)); } if (!checkExportedNamesForDeclaration(binding)) { return false; } } return true; } -template<typename CharT> +template<typename Unit> inline bool -Parser<SyntaxParseHandler, CharT>::checkExportedNamesForDeclarationList(ListNodeType node) +Parser<SyntaxParseHandler, Unit>::checkExportedNamesForDeclarationList(ListNodeType node) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return false; } -template<class ParseHandler, typename CharT> +template<class ParseHandler, typename Unit> inline bool -GeneralParser<ParseHandler, CharT>::checkExportedNamesForDeclarationList(ListNodeType node) +GeneralParser<ParseHandler, Unit>::checkExportedNamesForDeclarationList(ListNodeType node) { return asFinalParser()->checkExportedNamesForDeclarationList(node); } -template<typename CharT> +template<typename Unit> inline bool -Parser<FullParseHandler, CharT>::checkExportedNameForClause(NameNode* nameNode) +Parser<FullParseHandler, Unit>::checkExportedNameForClause(NameNode* nameNode) { return checkExportedName(nameNode->atom()); } -template<typename CharT> +template<typename Unit> inline bool -Parser<SyntaxParseHandler, CharT>::checkExportedNameForClause(NameNodeType nameNode) +Parser<SyntaxParseHandler, Unit>::checkExportedNameForClause(NameNodeType nameNode) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return false; } -template<class ParseHandler, typename CharT> +template<class ParseHandler, typename Unit> inline bool -GeneralParser<ParseHandler, CharT>::checkExportedNameForClause(NameNodeType nameNode) +GeneralParser<ParseHandler, Unit>::checkExportedNameForClause(NameNodeType nameNode) { return asFinalParser()->checkExportedNameForClause(nameNode); } -template<typename CharT> +template<typename Unit> bool -Parser<FullParseHandler, CharT>::checkExportedNameForFunction(CodeNode* funNode) +Parser<FullParseHandler, Unit>::checkExportedNameForFunction(CodeNode* funNode) { return checkExportedName(funNode->funbox()->function()->explicitName()); } -template<typename CharT> +template<typename Unit> inline bool -Parser<SyntaxParseHandler, CharT>::checkExportedNameForFunction(CodeNodeType funNode) +Parser<SyntaxParseHandler, Unit>::checkExportedNameForFunction(CodeNodeType funNode) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return false; } -template<class ParseHandler, typename CharT> +template<class ParseHandler, typename Unit> inline bool -GeneralParser<ParseHandler, CharT>::checkExportedNameForFunction(CodeNodeType funNode) +GeneralParser<ParseHandler, Unit>::checkExportedNameForFunction(CodeNodeType funNode) { return asFinalParser()->checkExportedNameForFunction(funNode); } -template<typename CharT> +template<typename Unit> bool -Parser<FullParseHandler, CharT>::checkExportedNameForClass(ClassNode* classNode) +Parser<FullParseHandler, Unit>::checkExportedNameForClass(ClassNode* classNode) { MOZ_ASSERT(classNode->names()); return checkExportedName(classNode->names()->innerBinding()->atom()); } -template<typename CharT> +template<typename Unit> inline bool -Parser<SyntaxParseHandler, CharT>::checkExportedNameForClass(ClassNodeType classNode) +Parser<SyntaxParseHandler, Unit>::checkExportedNameForClass(ClassNodeType classNode) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return false; } -template<class ParseHandler, typename CharT> +template<class ParseHandler, typename Unit> inline bool -GeneralParser<ParseHandler, CharT>::checkExportedNameForClass(ClassNodeType classNode) +GeneralParser<ParseHandler, Unit>::checkExportedNameForClass(ClassNodeType classNode) { return asFinalParser()->checkExportedNameForClass(classNode); } template<> inline bool PerHandlerParser<FullParseHandler>::processExport(ParseNode* node) { @@ -6161,19 +6155,19 @@ PerHandlerParser<FullParseHandler>::proc template<> inline bool PerHandlerParser<SyntaxParseHandler>::processExportFrom(BinaryNodeType node) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return false; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::BinaryNodeType -GeneralParser<ParseHandler, CharT>::exportFrom(uint32_t begin, Node specList) +GeneralParser<ParseHandler, Unit>::exportFrom(uint32_t begin, Node specList) { if (!abortIfSyntaxParser()) { return null(); } MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::From)); if (!abortIfSyntaxParser()) { @@ -6198,19 +6192,19 @@ GeneralParser<ParseHandler, CharT>::expo if (!processExportFrom(node)) { return null(); } return node; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::BinaryNodeType -GeneralParser<ParseHandler, CharT>::exportBatch(uint32_t begin) +GeneralParser<ParseHandler, Unit>::exportBatch(uint32_t begin) { if (!abortIfSyntaxParser()) { return null(); } MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Mul)); ListNodeType kid = handler.newList(ParseNodeKind::ExportSpecList, pos()); @@ -6227,52 +6221,52 @@ GeneralParser<ParseHandler, CharT>::expo handler.addList(kid, exportSpec); MUST_MATCH_TOKEN(TokenKind::From, JSMSG_FROM_AFTER_EXPORT_STAR); return exportFrom(begin, kid); } -template<typename CharT> +template<typename Unit> bool -Parser<FullParseHandler, CharT>::checkLocalExportNames(ListNode* node) +Parser<FullParseHandler, Unit>::checkLocalExportNames(ListNode* node) { // ES 2017 draft 15.2.3.1. for (ParseNode* next : node->contents()) { ParseNode* name = next->as<BinaryNode>().left(); MOZ_ASSERT(name->isKind(ParseNodeKind::Name)); RootedPropertyName ident(context, name->as<NameNode>().atom()->asPropertyName()); if (!checkLocalExportName(ident, name->pn_pos.begin)) { return false; } } return true; } -template<typename CharT> +template<typename Unit> bool -Parser<SyntaxParseHandler, CharT>::checkLocalExportNames(ListNodeType node) +Parser<SyntaxParseHandler, Unit>::checkLocalExportNames(ListNodeType node) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return false; } -template<class ParseHandler, typename CharT> +template<class ParseHandler, typename Unit> inline bool -GeneralParser<ParseHandler, CharT>::checkLocalExportNames(ListNodeType node) +GeneralParser<ParseHandler, Unit>::checkLocalExportNames(ListNodeType node) { return asFinalParser()->checkLocalExportNames(node); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::exportClause(uint32_t begin) +GeneralParser<ParseHandler, Unit>::exportClause(uint32_t begin) { if (!abortIfSyntaxParser()) { return null(); } MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftCurly)); ListNodeType kid = handler.newList(ParseNodeKind::ExportSpecList, pos()); @@ -6378,19 +6372,19 @@ GeneralParser<ParseHandler, CharT>::expo if (!processExport(node)) { return null(); } return node; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::UnaryNodeType -GeneralParser<ParseHandler, CharT>::exportVariableStatement(uint32_t begin) +GeneralParser<ParseHandler, Unit>::exportVariableStatement(uint32_t begin) { if (!abortIfSyntaxParser()) { return null(); } MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Var)); ListNodeType kid = declarationList(YieldIsName, ParseNodeKind::Var); @@ -6411,21 +6405,21 @@ GeneralParser<ParseHandler, CharT>::expo if (!processExport(node)) { return null(); } return node; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::UnaryNodeType -GeneralParser<ParseHandler, CharT>::exportFunctionDeclaration(uint32_t begin, - uint32_t toStringStart, - FunctionAsyncKind asyncKind /* = SyncFunction */) +GeneralParser<ParseHandler, Unit>::exportFunctionDeclaration(uint32_t begin, + uint32_t toStringStart, + FunctionAsyncKind asyncKind /* = SyncFunction */) { if (!abortIfSyntaxParser()) { return null(); } MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Function)); Node kid = functionStmt(toStringStart, YieldIsName, NameRequired, asyncKind); @@ -6444,19 +6438,19 @@ GeneralParser<ParseHandler, CharT>::expo if (!processExport(node)) { return null(); } return node; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::UnaryNodeType -GeneralParser<ParseHandler, CharT>::exportClassDeclaration(uint32_t begin) +GeneralParser<ParseHandler, Unit>::exportClassDeclaration(uint32_t begin) { if (!abortIfSyntaxParser()) { return null(); } MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Class)); ClassNodeType kid = classDefinition(YieldIsName, ClassStatement, NameRequired); @@ -6475,19 +6469,19 @@ GeneralParser<ParseHandler, CharT>::expo if (!processExport(node)) { return null(); } return node; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::UnaryNodeType -GeneralParser<ParseHandler, CharT>::exportLexicalDeclaration(uint32_t begin, DeclarationKind kind) +GeneralParser<ParseHandler, Unit>::exportLexicalDeclaration(uint32_t begin, DeclarationKind kind) { if (!abortIfSyntaxParser()) { return null(); } MOZ_ASSERT(kind == DeclarationKind::Const || kind == DeclarationKind::Let); MOZ_ASSERT_IF(kind == DeclarationKind::Const, anyChars.isCurrentTokenType(TokenKind::Const)); MOZ_ASSERT_IF(kind == DeclarationKind::Let, anyChars.isCurrentTokenType(TokenKind::Let)); @@ -6507,21 +6501,21 @@ GeneralParser<ParseHandler, CharT>::expo if (!processExport(node)) { return null(); } return node; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::BinaryNodeType -GeneralParser<ParseHandler, CharT>::exportDefaultFunctionDeclaration(uint32_t begin, - uint32_t toStringStart, - FunctionAsyncKind asyncKind /* = SyncFunction */) +GeneralParser<ParseHandler, Unit>::exportDefaultFunctionDeclaration(uint32_t begin, + uint32_t toStringStart, + FunctionAsyncKind asyncKind /* = SyncFunction */) { if (!abortIfSyntaxParser()) { return null(); } MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Function)); Node kid = functionStmt(toStringStart, YieldIsName, AllowDefaultName, asyncKind); @@ -6537,19 +6531,19 @@ GeneralParser<ParseHandler, CharT>::expo if (!processExport(node)) { return null(); } return node; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::BinaryNodeType -GeneralParser<ParseHandler, CharT>::exportDefaultClassDeclaration(uint32_t begin) +GeneralParser<ParseHandler, Unit>::exportDefaultClassDeclaration(uint32_t begin) { if (!abortIfSyntaxParser()) { return null(); } MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Class)); ClassNodeType kid = classDefinition(YieldIsName, ClassStatement, AllowDefaultName); @@ -6565,19 +6559,19 @@ GeneralParser<ParseHandler, CharT>::expo if (!processExport(node)) { return null(); } return node; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::BinaryNodeType -GeneralParser<ParseHandler, CharT>::exportDefaultAssignExpr(uint32_t begin) +GeneralParser<ParseHandler, Unit>::exportDefaultAssignExpr(uint32_t begin) { if (!abortIfSyntaxParser()) { return null(); } HandlePropertyName name = context->names().default_; NameNodeType nameNode = newName(name); if (!nameNode) { @@ -6604,19 +6598,19 @@ GeneralParser<ParseHandler, CharT>::expo if (!processExport(node)) { return null(); } return node; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::BinaryNodeType -GeneralParser<ParseHandler, CharT>::exportDefault(uint32_t begin) +GeneralParser<ParseHandler, Unit>::exportDefault(uint32_t begin) { if (!abortIfSyntaxParser()) { return null(); } MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Default)); TokenKind tt; @@ -6653,19 +6647,19 @@ GeneralParser<ParseHandler, CharT>::expo return exportDefaultClassDeclaration(begin); default: anyChars.ungetToken(); return exportDefaultAssignExpr(begin); } } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::exportDeclaration() +GeneralParser<ParseHandler, Unit>::exportDeclaration() { if (!abortIfSyntaxParser()) { return null(); } MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Export)); if (!pc->atModuleLevel()) { @@ -6722,36 +6716,36 @@ GeneralParser<ParseHandler, CharT>::expo return exportDefault(begin); default: error(JSMSG_DECLARATION_AFTER_EXPORT); return null(); } } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::UnaryNodeType -GeneralParser<ParseHandler, CharT>::expressionStatement(YieldHandling yieldHandling, - InvokedPrediction invoked) +GeneralParser<ParseHandler, Unit>::expressionStatement(YieldHandling yieldHandling, + InvokedPrediction invoked) { anyChars.ungetToken(); Node pnexpr = expr(InAllowed, yieldHandling, TripledotProhibited, /* possibleError = */ nullptr, invoked); if (!pnexpr) { return null(); } if (!matchOrInsertSemicolon()) { return null(); } return handler.newExprStatement(pnexpr, pos().end); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::consequentOrAlternative(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::consequentOrAlternative(YieldHandling yieldHandling) { TokenKind next; if (!tokenStream.peekToken(&next, TokenStream::Operand)) { return null(); } // Annex B.3.4 says that unbraced FunctionDeclarations under if/else in // non-strict code act as if they were braced: |if (x) function f() {}| @@ -6798,19 +6792,19 @@ GeneralParser<ParseHandler, CharT>::cons handler.addStatementToList(block, fun); return finishLexicalScope(scope, block); } return statement(yieldHandling); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::TernaryNodeType -GeneralParser<ParseHandler, CharT>::ifStatement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::ifStatement(YieldHandling yieldHandling) { Vector<Node, 4> condList(context), thenList(context); Vector<uint32_t, 4> posList(context); Node elseBranch; ParseContext::Statement stmt(pc, StatementKind::If); while (true) { @@ -6869,19 +6863,19 @@ GeneralParser<ParseHandler, CharT>::ifSt return null(); } elseBranch = ifNode; } return ifNode; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::BinaryNodeType -GeneralParser<ParseHandler, CharT>::doWhileStatement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::doWhileStatement(YieldHandling yieldHandling) { uint32_t begin = pos().begin; ParseContext::Statement stmt(pc, StatementKind::DoLoop); Node body = statement(yieldHandling); if (!body) { return null(); } MUST_MATCH_TOKEN_MOD(TokenKind::While, TokenStream::Operand, JSMSG_WHILE_AFTER_DO); @@ -6898,58 +6892,58 @@ GeneralParser<ParseHandler, CharT>::doWh // To parse |do {} while (true) false| correctly, use Operand. bool ignored; if (!tokenStream.matchToken(&ignored, TokenKind::Semi, TokenStream::Operand)) { return null(); } return handler.newDoWhileStatement(body, cond, TokenPos(begin, pos().end)); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::BinaryNodeType -GeneralParser<ParseHandler, CharT>::whileStatement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::whileStatement(YieldHandling yieldHandling) { uint32_t begin = pos().begin; ParseContext::Statement stmt(pc, StatementKind::WhileLoop); Node cond = condition(InAllowed, yieldHandling); if (!cond) { return null(); } Node body = statement(yieldHandling); if (!body) { return null(); } return handler.newWhileStatement(begin, cond, body); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::matchInOrOf(bool* isForInp, bool* isForOfp) +GeneralParser<ParseHandler, Unit>::matchInOrOf(bool* isForInp, bool* isForOfp) { TokenKind tt; if (!tokenStream.getToken(&tt, TokenStream::Operand)) { return false; } *isForInp = tt == TokenKind::In; *isForOfp = tt == TokenKind::Of; if (!*isForInp && !*isForOfp) { anyChars.ungetToken(); } MOZ_ASSERT_IF(*isForInp || *isForOfp, *isForInp != *isForOfp); return true; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::forHeadStart(YieldHandling yieldHandling, - ParseNodeKind* forHeadKind, Node* forInitialPart, - Maybe<ParseContext::Scope>& forLoopLexicalScope, - Node* forInOrOfExpression) +GeneralParser<ParseHandler, Unit>::forHeadStart(YieldHandling yieldHandling, + ParseNodeKind* forHeadKind, Node* forInitialPart, + Maybe<ParseContext::Scope>& forLoopLexicalScope, + Node* forInOrOfExpression) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftParen)); TokenKind tt; if (!tokenStream.peekToken(&tt, TokenStream::Operand)) { return false; } @@ -7100,19 +7094,19 @@ GeneralParser<ParseHandler, CharT>::forH } // Finally, parse the iterated expression, making the for-loop's closing // ')' the next token. *forInOrOfExpression = expressionAfterForInOrOf(*forHeadKind, yieldHandling); return *forInOrOfExpression != null(); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::forStatement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::forStatement(YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::For)); uint32_t begin = pos().begin; ParseContext::Statement stmt(pc, StatementKind::ForLoop); IteratorKind iterKind = IteratorKind::Sync; @@ -7269,19 +7263,19 @@ GeneralParser<ParseHandler, CharT>::forS if (forLoopLexicalScope) { return finishLexicalScope(*forLoopLexicalScope, forLoop); } return forLoop; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::SwitchStatementType -GeneralParser<ParseHandler, CharT>::switchStatement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::switchStatement(YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Switch)); uint32_t begin = pos().begin; MUST_MATCH_TOKEN(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_SWITCH); Node discriminant = exprInParens(InAllowed, yieldHandling, TripledotProhibited); if (!discriminant) { @@ -7390,19 +7384,19 @@ GeneralParser<ParseHandler, CharT>::swit return null(); } handler.setEndPosition(lexicalForCaseList, pos().end); return handler.newSwitchStatement(begin, discriminant, lexicalForCaseList, seenDefault); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::ContinueStatementType -GeneralParser<ParseHandler, CharT>::continueStatement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::continueStatement(YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Continue)); uint32_t begin = pos().begin; RootedPropertyName label(context); if (!matchLabel(yieldHandling, &label)) { return null(); } @@ -7422,19 +7416,19 @@ GeneralParser<ParseHandler, CharT>::cont if (!matchOrInsertSemicolon()) { return null(); } return handler.newContinueStatement(label, TokenPos(begin, pos().end)); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::BreakStatementType -GeneralParser<ParseHandler, CharT>::breakStatement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::breakStatement(YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Break)); uint32_t begin = pos().begin; RootedPropertyName label(context); if (!matchLabel(yieldHandling, &label)) { return null(); } @@ -7464,19 +7458,19 @@ GeneralParser<ParseHandler, CharT>::brea if (!matchOrInsertSemicolon()) { return null(); } return handler.newBreakStatement(label, TokenPos(begin, pos().end)); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::UnaryNodeType -GeneralParser<ParseHandler, CharT>::returnStatement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::returnStatement(YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Return)); uint32_t begin = pos().begin; MOZ_ASSERT(pc->isFunctionBox()); pc->functionBox()->usesReturn = true; // Parse an optional operand. @@ -7504,19 +7498,19 @@ GeneralParser<ParseHandler, CharT>::retu if (!matchOrInsertSemicolon()) { return null(); } return handler.newReturnStatement(exprNode, TokenPos(begin, pos().end)); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::UnaryNodeType -GeneralParser<ParseHandler, CharT>::yieldExpression(InHandling inHandling) +GeneralParser<ParseHandler, Unit>::yieldExpression(InHandling inHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Yield)); uint32_t begin = pos().begin; MOZ_ASSERT(pc->isGenerator()); MOZ_ASSERT(pc->isFunctionBox()); pc->lastYieldOffset = begin; @@ -7558,19 +7552,19 @@ GeneralParser<ParseHandler, CharT>::yiel } } if (kind == ParseNodeKind::YieldStar) { return handler.newYieldStarExpression(begin, exprNode); } return handler.newYieldExpression(begin, exprNode); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::BinaryNodeType -GeneralParser<ParseHandler, CharT>::withStatement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::withStatement(YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::With)); uint32_t begin = pos().begin; // Usually we want the constructs forbidden in strict mode code to be a // subset of those that ContextOptions::extraWarnings() warns about, and we // use strictModeError directly. But while 'with' is forbidden in strict // mode code, it doesn't even merit a warning in non-strict code. See @@ -7599,19 +7593,19 @@ GeneralParser<ParseHandler, CharT>::with } } pc->sc()->setBindingsAccessedDynamically(); return handler.newWithStatement(begin, objectExpr, innerBlock); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::labeledItem(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::labeledItem(YieldHandling yieldHandling) { TokenKind tt; if (!tokenStream.getToken(&tt, TokenStream::Operand)) { return null(); } if (tt == TokenKind::Function) { TokenKind next; @@ -7636,19 +7630,19 @@ GeneralParser<ParseHandler, CharT>::labe return functionStmt(pos().begin, yieldHandling, NameRequired); } anyChars.ungetToken(); return statement(yieldHandling); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::LabeledStatementType -GeneralParser<ParseHandler, CharT>::labeledStatement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::labeledStatement(YieldHandling yieldHandling) { RootedPropertyName label(context, labelIdentifier(yieldHandling)); if (!label) { return null(); } auto hasSameLabel = [&label](ParseContext::LabelStatement* stmt) { return stmt->label() == label; @@ -7668,19 +7662,19 @@ GeneralParser<ParseHandler, CharT>::labe Node pn = labeledItem(yieldHandling); if (!pn) { return null(); } return handler.newLabeledStatement(label, pn, begin); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::UnaryNodeType -GeneralParser<ParseHandler, CharT>::throwStatement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::throwStatement(YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Throw)); uint32_t begin = pos().begin; /* ECMA-262 Edition 3 says 'throw [no LineTerminator here] Expr'. */ TokenKind tt = TokenKind::Eof; if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand)) { return null(); @@ -7701,19 +7695,19 @@ GeneralParser<ParseHandler, CharT>::thro if (!matchOrInsertSemicolon()) { return null(); } return handler.newThrowStatement(throwExpr, TokenPos(begin, pos().end)); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::TernaryNodeType -GeneralParser<ParseHandler, CharT>::tryStatement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::tryStatement(YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Try)); uint32_t begin = pos().begin; /* * try nodes are ternary. * kid1 is the try statement * kid2 is the catch node list or null @@ -7875,20 +7869,20 @@ GeneralParser<ParseHandler, CharT>::tryS if (!catchScope && !finallyBlock) { error(JSMSG_CATCH_OR_FINALLY); return null(); } return handler.newTryStatement(begin, innerBlock, catchScope, finallyBlock); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::LexicalScopeNodeType -GeneralParser<ParseHandler, CharT>::catchBlockStatement(YieldHandling yieldHandling, - ParseContext::Scope& catchParamScope) +GeneralParser<ParseHandler, Unit>::catchBlockStatement(YieldHandling yieldHandling, + ParseContext::Scope& catchParamScope) { uint32_t openedPos = pos().begin; ParseContext::Statement stmt(pc, StatementKind::Block); // ES 13.15.7 CatchClauseEvaluation // // Step 8 means that the body of a catch block always has an additional @@ -7914,19 +7908,19 @@ GeneralParser<ParseHandler, CharT>::catc JSMSG_CURLY_OPENED, openedPos)); // The catch parameter names are not bound in the body scope, so remove // them before generating bindings. scope.removeCatchParameters(pc, catchParamScope); return finishLexicalScope(scope, list); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::DebuggerStatementType -GeneralParser<ParseHandler, CharT>::debuggerStatement() +GeneralParser<ParseHandler, Unit>::debuggerStatement() { TokenPos p; p.begin = pos().begin; if (!matchOrInsertSemicolon()) { return null(); } p.end = pos().end; @@ -7952,21 +7946,21 @@ ToAccessorType(PropertyType propType) case PropertyType::Constructor: case PropertyType::DerivedConstructor: return AccessorType::None; default: MOZ_CRASH("unexpected property type"); } } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::ClassNodeType -GeneralParser<ParseHandler, CharT>::classDefinition(YieldHandling yieldHandling, - ClassContext classContext, - DefaultHandling defaultHandling) +GeneralParser<ParseHandler, Unit>::classDefinition(YieldHandling yieldHandling, + ClassContext classContext, + DefaultHandling defaultHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Class)); uint32_t classStartOffset = pos().begin; bool savedStrictness = setLocalStrictMode(true); TokenKind tt; if (!tokenStream.getToken(&tt)) { @@ -8226,33 +8220,33 @@ ParserBase::nextTokenContinuesLetDeclara // that we should parse this as two ExpressionStatements? No. ASI // resolves during parsing. Static semantics only apply to the full // parse tree with ASI applied. No backsies! // Otherwise a let declaration must have a name. return TokenKindIsPossibleIdentifier(next); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::variableStatement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::variableStatement(YieldHandling yieldHandling) { ListNodeType vars = declarationList(yieldHandling, ParseNodeKind::Var); if (!vars) { return null(); } if (!matchOrInsertSemicolon()) { return null(); } return vars; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::statement(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::statement(YieldHandling yieldHandling) { MOZ_ASSERT(checkOptionsCalled); if (!CheckRecursionLimit(context)) { return null(); } TokenKind tt; @@ -8468,20 +8462,20 @@ GeneralParser<ParseHandler, CharT>::stat case TokenKind::Finally: error(JSMSG_FINALLY_WITHOUT_TRY); return null(); // NOTE: default case handled in the ExpressionStatement section. } } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::statementListItem(YieldHandling yieldHandling, - bool canHaveDirectives /* = false */) +GeneralParser<ParseHandler, Unit>::statementListItem(YieldHandling yieldHandling, + bool canHaveDirectives /* = false */) { MOZ_ASSERT(checkOptionsCalled); if (!CheckRecursionLimit(context)) { return null(); } TokenKind tt; @@ -8674,22 +8668,22 @@ GeneralParser<ParseHandler, CharT>::stat case TokenKind::Finally: error(JSMSG_FINALLY_WITHOUT_TRY); return null(); // NOTE: default case handled in the ExpressionStatement section. } } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::expr(InHandling inHandling, YieldHandling yieldHandling, - TripledotHandling tripledotHandling, - PossibleError* possibleError /* = nullptr */, - InvokedPrediction invoked /* = PredictUninvoked */) +GeneralParser<ParseHandler, Unit>::expr(InHandling inHandling, YieldHandling yieldHandling, + TripledotHandling tripledotHandling, + PossibleError* possibleError /* = nullptr */, + InvokedPrediction invoked /* = PredictUninvoked */) { Node pn = assignExpr(inHandling, yieldHandling, tripledotHandling, possibleError, invoked); if (!pn) { return null(); } bool matched; @@ -8811,22 +8805,22 @@ Precedence(ParseNodeKind pnk) return 0; } MOZ_ASSERT(pnk >= ParseNodeKind::BinOpFirst); MOZ_ASSERT(pnk <= ParseNodeKind::BinOpLast); return PrecedenceTable[size_t(pnk) - size_t(ParseNodeKind::BinOpFirst)]; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> MOZ_ALWAYS_INLINE typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::orExpr(InHandling inHandling, YieldHandling yieldHandling, - TripledotHandling tripledotHandling, - PossibleError* possibleError, - InvokedPrediction invoked /* = PredictUninvoked */) +GeneralParser<ParseHandler, Unit>::orExpr(InHandling inHandling, YieldHandling yieldHandling, + TripledotHandling tripledotHandling, + PossibleError* possibleError, + InvokedPrediction invoked /* = PredictUninvoked */) { // Shift-reduce parser for the binary operator part of the JS expression // syntax. // Conceptually there's just one stack, a stack of pairs (lhs, op). // It's implemented using two separate arrays, though. Node nodeStack[PRECEDENCE_CLASSES]; ParseNodeKind kindStack[PRECEDENCE_CLASSES]; @@ -8897,22 +8891,22 @@ GeneralParser<ParseHandler, CharT>::orEx // modifier can be Operand. anyChars.ungetToken(); anyChars.addModifierException(TokenStream::OperandIsNone); MOZ_ASSERT(depth == 0); return pn; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> MOZ_ALWAYS_INLINE typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::condExpr(InHandling inHandling, YieldHandling yieldHandling, - TripledotHandling tripledotHandling, - PossibleError* possibleError, - InvokedPrediction invoked /* = PredictUninvoked */) +GeneralParser<ParseHandler, Unit>::condExpr(InHandling inHandling, YieldHandling yieldHandling, + TripledotHandling tripledotHandling, + PossibleError* possibleError, + InvokedPrediction invoked /* = PredictUninvoked */) { Node condition = orExpr(inHandling, yieldHandling, tripledotHandling, possibleError, invoked); if (!condition) { return null(); } bool matched; if (!tokenStream.matchToken(&matched, TokenKind::Hook)) { @@ -8932,22 +8926,22 @@ GeneralParser<ParseHandler, CharT>::cond Node elseExpr = assignExpr(inHandling, yieldHandling, TripledotProhibited); if (!elseExpr) { return null(); } return handler.newConditional(condition, thenExpr, elseExpr); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::assignExpr(InHandling inHandling, YieldHandling yieldHandling, - TripledotHandling tripledotHandling, - PossibleError* possibleError /* = nullptr */, - InvokedPrediction invoked /* = PredictUninvoked */) +GeneralParser<ParseHandler, Unit>::assignExpr(InHandling inHandling, YieldHandling yieldHandling, + TripledotHandling tripledotHandling, + PossibleError* possibleError /* = nullptr */, + InvokedPrediction invoked /* = PredictUninvoked */) { if (!CheckRecursionLimit(context)) { return null(); } // It's very common at this point to have a "detectably simple" expression, // i.e. a name/number/string token followed by one of the following tokens // that obviously isn't part of an expression: , ; : ) ] } @@ -9228,19 +9222,19 @@ PerHandlerParser<ParseHandler>::nameIsAr return js_eval_str; } if (handler.isArgumentsName(node, context)) { return js_arguments_str; } return nullptr; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::checkIncDecOperand(Node operand, uint32_t operandOffset) +GeneralParser<ParseHandler, Unit>::checkIncDecOperand(Node operand, uint32_t operandOffset) { if (handler.isName(operand)) { if (const char* chars = nameIsArgumentsOrEval(operand)) { if (!strictModeErrorAt(operandOffset, JSMSG_BAD_STRICT_ASSIGN, chars)) { return false; } } } else if (handler.isPropertyAccess(operand)) { @@ -9258,34 +9252,34 @@ GeneralParser<ParseHandler, CharT>::chec return false; } MOZ_ASSERT(isValidSimpleAssignmentTarget(operand, PermitAssignmentToFunctionCalls), "inconsistent increment/decrement operand validation"); return true; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::UnaryNodeType -GeneralParser<ParseHandler, CharT>::unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind, +GeneralParser<ParseHandler, Unit>::unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind, uint32_t begin) { Node kid = unaryExpr(yieldHandling, TripledotProhibited); if (!kid) { return null(); } return handler.newUnary(kind, begin, kid); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::unaryExpr(YieldHandling yieldHandling, - TripledotHandling tripledotHandling, - PossibleError* possibleError /* = nullptr */, - InvokedPrediction invoked /* = PredictUninvoked */) +GeneralParser<ParseHandler, Unit>::unaryExpr(YieldHandling yieldHandling, + TripledotHandling tripledotHandling, + PossibleError* possibleError /* = nullptr */, + InvokedPrediction invoked /* = PredictUninvoked */) { if (!CheckRecursionLimit(context)) { return null(); } TokenKind tt; if (!tokenStream.getToken(&tt, TokenStream::Operand)) { return null(); @@ -9409,19 +9403,19 @@ GeneralParser<ParseHandler, CharT>::unar ? ParseNodeKind::PostIncrement : ParseNodeKind::PostDecrement; return handler.newUpdate(pnk, begin, expr); } } } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::assignExprWithoutYieldOrAwait(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::assignExprWithoutYieldOrAwait(YieldHandling yieldHandling) { uint32_t startYieldOffset = pc->lastYieldOffset; uint32_t startAwaitOffset = pc->lastAwaitOffset; Node res = assignExpr(InAllowed, yieldHandling, TripledotProhibited); if (res) { if (pc->lastYieldOffset != startYieldOffset) { errorAt(pc->lastYieldOffset, JSMSG_YIELD_IN_PARAMETER); return null(); @@ -9429,20 +9423,20 @@ GeneralParser<ParseHandler, CharT>::assi if (pc->lastAwaitOffset != startAwaitOffset) { errorAt(pc->lastAwaitOffset, JSMSG_AWAIT_IN_PARAMETER); return null(); } } return res; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::ListNodeType -GeneralParser<ParseHandler, CharT>::argumentList(YieldHandling yieldHandling, bool* isSpread, - PossibleError* possibleError /* = nullptr */) +GeneralParser<ParseHandler, Unit>::argumentList(YieldHandling yieldHandling, bool* isSpread, + PossibleError* possibleError /* = nullptr */) { ListNodeType argsList = handler.newArguments(pos()); if (!argsList) { return null(); } bool matched; if (!tokenStream.matchToken(&matched, TokenKind::RightParen, TokenStream::Operand)) { @@ -9507,23 +9501,23 @@ ParserBase::checkAndMarkSuperScope() if (!pc->sc()->allowSuperProperty()) { return false; } pc->setSuperScopeNeedsHomeObject(); return true; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::memberExpr(YieldHandling yieldHandling, - TripledotHandling tripledotHandling, - TokenKind tt, bool allowCallSyntax /* = true */, - PossibleError* possibleError /* = nullptr */, - InvokedPrediction invoked /* = PredictUninvoked */) +GeneralParser<ParseHandler, Unit>::memberExpr(YieldHandling yieldHandling, + TripledotHandling tripledotHandling, + TokenKind tt, bool allowCallSyntax /* = true */, + PossibleError* possibleError /* = nullptr */, + InvokedPrediction invoked /* = PredictUninvoked */) { MOZ_ASSERT(anyChars.isCurrentTokenType(tt)); Node lhs; if (!CheckRecursionLimit(context)) { return null(); } @@ -9803,22 +9797,22 @@ PerHandlerParser<ParseHandler>::newName( template <class ParseHandler> inline typename ParseHandler::NameNodeType PerHandlerParser<ParseHandler>::newName(PropertyName* name, TokenPos pos) { return handler.newName(name, pos, context); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::checkLabelOrIdentifierReference(PropertyName* ident, - uint32_t offset, - YieldHandling yieldHandling, - TokenKind hint /* = TokenKind::Limit */) +GeneralParser<ParseHandler, Unit>::checkLabelOrIdentifierReference(PropertyName* ident, + uint32_t offset, + YieldHandling yieldHandling, + TokenKind hint /* = TokenKind::Limit */) { TokenKind tt; if (hint == TokenKind::Limit) { tt = ReservedWordTokenKind(ident); } else { MOZ_ASSERT(hint == ReservedWordTokenKind(ident), "hint doesn't match actual token kind"); tt = hint; } @@ -9877,21 +9871,21 @@ GeneralParser<ParseHandler, CharT>::chec if (TokenKindIsFutureReservedWord(tt)) { errorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(tt)); return false; } MOZ_ASSERT_UNREACHABLE("Unexpected reserved word kind."); return false; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::checkBindingIdentifier(PropertyName* ident, uint32_t offset, - YieldHandling yieldHandling, - TokenKind hint /* = TokenKind::Limit */) +GeneralParser<ParseHandler, Unit>::checkBindingIdentifier(PropertyName* ident, uint32_t offset, + YieldHandling yieldHandling, + TokenKind hint /* = TokenKind::Limit */) { if (pc->sc()->needStrictChecks()) { if (ident == context->names().arguments) { if (!strictModeErrorAt(offset, JSMSG_BAD_STRICT_ASSIGN, "arguments")) { return false; } return true; } @@ -9902,19 +9896,19 @@ GeneralParser<ParseHandler, CharT>::chec } return true; } } return checkLabelOrIdentifierReference(ident, offset, yieldHandling, hint); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> PropertyName* -GeneralParser<ParseHandler, CharT>::labelOrIdentifierReference(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::labelOrIdentifierReference(YieldHandling yieldHandling) { // ES 2017 draft 12.1.1. // StringValue of IdentifierName normalizes any Unicode escape sequences // in IdentifierName hence such escapes cannot be used to write an // Identifier whose code point sequence is the same as a ReservedWord. // // Use PropertyName* instead of TokenKind to reflect the normalization. @@ -9925,19 +9919,19 @@ GeneralParser<ParseHandler, CharT>::labe : TokenKind::Limit; RootedPropertyName ident(context, anyChars.currentName()); if (!checkLabelOrIdentifierReference(ident, pos().begin, yieldHandling, hint)) { return nullptr; } return ident; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> PropertyName* -GeneralParser<ParseHandler, CharT>::bindingIdentifier(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::bindingIdentifier(YieldHandling yieldHandling) { TokenKind hint = !anyChars.currentNameHasEscapes() ? anyChars.currentToken().type : TokenKind::Limit; RootedPropertyName ident(context, anyChars.currentName()); if (!checkBindingIdentifier(ident, pos().begin, yieldHandling, hint)) { return nullptr; } @@ -9974,30 +9968,30 @@ PerHandlerParser<ParseHandler>::noSubsti if (anyChars.hasInvalidTemplateEscape()) { anyChars.clearInvalidTemplateEscape(); return handler.newRawUndefinedLiteral(pos()); } return handler.newTemplateStringLiteral(anyChars.currentToken().atom(), pos()); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::NameNodeType -GeneralParser<ParseHandler, CharT>::noSubstitutionUntaggedTemplate() +GeneralParser<ParseHandler, Unit>::noSubstitutionUntaggedTemplate() { if (!tokenStream.checkForInvalidTemplateEscapeError()) { return null(); } return handler.newTemplateStringLiteral(anyChars.currentToken().atom(), pos()); } -template <typename CharT> +template <typename Unit> RegExpLiteral* -Parser<FullParseHandler, CharT>::newRegExp() +Parser<FullParseHandler, Unit>::newRegExp() { MOZ_ASSERT(!options().selfHostingMode); // Create the regexp and check its syntax. const auto& chars = tokenStream.getCharBuffer(); RegExpFlag flags = anyChars.currentToken().regExpFlags(); Rooted<RegExpObject*> reobj(context); @@ -10005,49 +9999,49 @@ Parser<FullParseHandler, CharT>::newRegE TenuredObject); if (!reobj) { return null(); } return handler.newRegExp(reobj, pos(), *this); } -template <typename CharT> +template <typename Unit> SyntaxParseHandler::RegExpLiteralType -Parser<SyntaxParseHandler, CharT>::newRegExp() +Parser<SyntaxParseHandler, Unit>::newRegExp() { MOZ_ASSERT(!options().selfHostingMode); // Only check the regexp's syntax, but don't create a regexp object. const auto& chars = tokenStream.getCharBuffer(); RegExpFlag flags = anyChars.currentToken().regExpFlags(); mozilla::Range<const char16_t> source(chars.begin(), chars.length()); if (!js::irregexp::ParsePatternSyntax(anyChars, alloc, source, flags & UnicodeFlag)) { return null(); } return handler.newRegExp(SyntaxParseHandler::NodeGeneric, pos(), *this); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::RegExpLiteralType -GeneralParser<ParseHandler, CharT>::newRegExp() +GeneralParser<ParseHandler, Unit>::newRegExp() { return asFinalParser()->newRegExp(); } // |exprPossibleError| is the PossibleError state within |expr|, // |possibleError| is the surrounding PossibleError state. -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::checkDestructuringAssignmentTarget(Node expr, TokenPos exprPos, - PossibleError* exprPossibleError, - PossibleError* possibleError, - TargetBehavior behavior) +GeneralParser<ParseHandler, Unit>::checkDestructuringAssignmentTarget(Node expr, TokenPos exprPos, + PossibleError* exprPossibleError, + PossibleError* possibleError, + TargetBehavior behavior) { // Report any pending expression error if we're definitely not in a // destructuring context or the possible destructuring target is a // property accessor. if (!possibleError || handler.isPropertyAccess(expr)) { return exprPossibleError->checkForExpressionError(); } @@ -10084,21 +10078,21 @@ GeneralParser<ParseHandler, CharT>::chec possibleError->setPendingDestructuringErrorAt(exprPos, JSMSG_BAD_DESTRUCT_PARENS); } else { possibleError->setPendingDestructuringErrorAt(exprPos, JSMSG_BAD_DESTRUCT_TARGET); } return true; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> void -GeneralParser<ParseHandler, CharT>::checkDestructuringAssignmentName(NameNodeType name, - TokenPos namePos, - PossibleError* possibleError) +GeneralParser<ParseHandler, Unit>::checkDestructuringAssignmentName(NameNodeType name, + TokenPos namePos, + PossibleError* possibleError) { #ifdef DEBUG // GCC 8.0.1 crashes if this is a one-liner. bool isName = handler.isName(name); MOZ_ASSERT(isName); #endif // Return early if a pending destructuring error is already present. @@ -10126,21 +10120,21 @@ GeneralParser<ParseHandler, CharT>::chec possibleError->setPendingDestructuringWarningAt(namePos, JSMSG_BAD_STRICT_ASSIGN_EVAL); } return; } } } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::checkDestructuringAssignmentElement(Node expr, TokenPos exprPos, - PossibleError* exprPossibleError, - PossibleError* possibleError) +GeneralParser<ParseHandler, Unit>::checkDestructuringAssignmentElement(Node expr, TokenPos exprPos, + PossibleError* exprPossibleError, + PossibleError* possibleError) { // ES2018 draft rev 0719f44aab93215ed9a626b2f45bd34f36916834 // 12.15.5 Destructuring Assignment // // AssignmentElement[Yield, Await]: // DestructuringAssignmentTarget[?Yield, ?Await] // DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] @@ -10155,20 +10149,20 @@ GeneralParser<ParseHandler, CharT>::chec } exprPossibleError->transferErrorsTo(possibleError); return true; } return checkDestructuringAssignmentTarget(expr, exprPos, exprPossibleError, possibleError); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::ListNodeType -GeneralParser<ParseHandler, CharT>::arrayInitializer(YieldHandling yieldHandling, - PossibleError* possibleError) +GeneralParser<ParseHandler, Unit>::arrayInitializer(YieldHandling yieldHandling, + PossibleError* possibleError) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftBracket)); uint32_t begin = pos().begin; ListNodeType literal = handler.newArrayLiteral(begin); if (!literal) { return null(); } @@ -10273,23 +10267,23 @@ GeneralParser<ParseHandler, CharT>::arra reportMissingClosing(JSMSG_BRACKET_AFTER_LIST, JSMSG_BRACKET_OPENED, begin)); } handler.setEndPosition(literal, pos().end); return literal; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::propertyName(YieldHandling yieldHandling, - const Maybe<DeclarationKind>& maybeDecl, - ListNodeType propList, - PropertyType* propType, - MutableHandleAtom propAtom) +GeneralParser<ParseHandler, Unit>::propertyName(YieldHandling yieldHandling, + const Maybe<DeclarationKind>& maybeDecl, + ListNodeType propList, + PropertyType* propType, + MutableHandleAtom propAtom) { TokenKind ltok; if (!tokenStream.getToken(<ok)) { return null(); } MOZ_ASSERT(ltok != TokenKind::RightCurly, "caller should have handled TokenKind::RightCurly"); @@ -10485,21 +10479,21 @@ GeneralParser<ParseHandler, CharT>::prop } return propName; } error(JSMSG_COLON_AFTER_ID); return null(); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::UnaryNodeType -GeneralParser<ParseHandler, CharT>::computedPropertyName(YieldHandling yieldHandling, - const Maybe<DeclarationKind>& maybeDecl, - ListNodeType literal) +GeneralParser<ParseHandler, Unit>::computedPropertyName(YieldHandling yieldHandling, + const Maybe<DeclarationKind>& maybeDecl, + ListNodeType literal) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftBracket)); uint32_t begin = pos().begin; if (maybeDecl) { if (*maybeDecl == DeclarationKind::FormalParameter) { pc->functionBox()->hasParameterExprs = true; @@ -10512,20 +10506,20 @@ GeneralParser<ParseHandler, CharT>::comp if (!assignNode) { return null(); } MUST_MATCH_TOKEN_MOD(TokenKind::RightBracket, TokenStream::Operand, JSMSG_COMP_PROP_UNTERM_EXPR); return handler.newComputedName(assignNode, begin, pos().end); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::ListNodeType -GeneralParser<ParseHandler, CharT>::objectLiteral(YieldHandling yieldHandling, - PossibleError* possibleError) +GeneralParser<ParseHandler, Unit>::objectLiteral(YieldHandling yieldHandling, + PossibleError* possibleError) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftCurly)); uint32_t openedPos = pos().begin; ListNodeType literal = handler.newObjectLiteral(pos().begin); if (!literal) { return null(); @@ -10766,20 +10760,20 @@ GeneralParser<ParseHandler, CharT>::obje MUST_MATCH_TOKEN_MOD_WITH_REPORT(TokenKind::RightCurly, TokenStream::Operand, reportMissingClosing(JSMSG_CURLY_AFTER_LIST, JSMSG_CURLY_OPENED, openedPos)); handler.setEndPosition(literal, pos().end); return literal; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::CodeNodeType -GeneralParser<ParseHandler, CharT>::methodDefinition(uint32_t toStringStart, PropertyType propType, - HandleAtom funName) +GeneralParser<ParseHandler, Unit>::methodDefinition(uint32_t toStringStart, PropertyType propType, + HandleAtom funName) { FunctionSyntaxKind kind; switch (propType) { case PropertyType::Getter: kind = FunctionSyntaxKind::Getter; break; case PropertyType::Setter: @@ -10821,19 +10815,19 @@ GeneralParser<ParseHandler, CharT>::meth if (!funNode) { return null(); } return functionDefinition(funNode, toStringStart, InAllowed, yieldHandling, funName, kind, generatorKind, asyncKind); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> bool -GeneralParser<ParseHandler, CharT>::tryNewTarget(BinaryNodeType* newTarget) +GeneralParser<ParseHandler, Unit>::tryNewTarget(BinaryNodeType* newTarget) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::New)); *newTarget = null(); NullaryNodeType newHolder = handler.newPosHolder(pos()); if (!newHolder) { return false; @@ -10870,19 +10864,19 @@ GeneralParser<ParseHandler, CharT>::tryN if (!targetHolder) { return false; } *newTarget = handler.newNewTarget(newHolder, targetHolder); return !!*newTarget; } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::BinaryNodeType -GeneralParser<ParseHandler, CharT>::importExpr(YieldHandling yieldHandling) +GeneralParser<ParseHandler, Unit>::importExpr(YieldHandling yieldHandling) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Import)); NullaryNodeType importHolder = handler.newPosHolder(pos()); if (!importHolder) { return null(); } @@ -10925,22 +10919,22 @@ GeneralParser<ParseHandler, CharT>::impo return handler.newCallImport(importHolder, arg); } else { error(JSMSG_UNEXPECTED_TOKEN_NO_EXPECT, TokenKindToDesc(next)); return null(); } } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::primaryExpr(YieldHandling yieldHandling, - TripledotHandling tripledotHandling, - TokenKind tt, PossibleError* possibleError, - InvokedPrediction invoked /* = PredictUninvoked */) +GeneralParser<ParseHandler, Unit>::primaryExpr(YieldHandling yieldHandling, + TripledotHandling tripledotHandling, + TokenKind tt, PossibleError* possibleError, + InvokedPrediction invoked /* = PredictUninvoked */) { MOZ_ASSERT(anyChars.isCurrentTokenType(tt)); if (!CheckRecursionLimit(context)) { return null(); } switch (tt) { case TokenKind::Function: @@ -11108,22 +11102,22 @@ GeneralParser<ParseHandler, CharT>::prim anyChars.ungetToken(); // put back right paren // Return an arbitrary expression node. See case TokenKind::RightParen above. return handler.newNullLiteral(pos()); } } } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> typename ParseHandler::Node -GeneralParser<ParseHandler, CharT>::exprInParens(InHandling inHandling, - YieldHandling yieldHandling, - TripledotHandling tripledotHandling, - PossibleError* possibleError /* = nullptr */) +GeneralParser<ParseHandler, Unit>::exprInParens(InHandling inHandling, + YieldHandling yieldHandling, + TripledotHandling tripledotHandling, + PossibleError* possibleError /* = nullptr */) { MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftParen)); return expr(inHandling, yieldHandling, tripledotHandling, possibleError, PredictInvoked); } template class PerHandlerParser<FullParseHandler>; template class PerHandlerParser<SyntaxParseHandler>; template class GeneralParser<FullParseHandler, Utf8Unit>;
--- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -54,17 +54,17 @@ * syntax and full parsing but (because no source characters are examined) does * not vary by source text character type. Such functionality is implemented * through functions in PerHandlerParser. * * Functionality only used by syntax parsing or full parsing doesn't live here: * it should be implemented in the appropriate Parser<ParseHandler> (described * further below). * - * == GeneralParser<ParseHandler, CharT> → PerHandlerParser<ParseHandler> == + * == GeneralParser<ParseHandler, Unit> → PerHandlerParser<ParseHandler> == * * Most parsing behavior varies across the character-type axis (and possibly * along the full/syntax axis). For example: * * * Parsing ECMAScript's Expression production, implemented by * GeneralParser::expr, varies in this manner: different types are used to * represent nodes in full and syntax parsing (ParseNode* versus an enum), * and reading the tokens comprising the expression requires inspecting @@ -83,90 +83,90 @@ * |TokenStreamSpecific| component, for all aspects of tokenizing that (contra * |TokenStreamAnyChars| in ParserBase above) are character-type-sensitive. As * noted above, this field's existence separate from that in ParserBase * motivates the |AnyCharsAccess| template parameters on various token stream * classes. * * Everything in PerHandlerParser *could* be folded into GeneralParser (below) * if desired. We don't fold in this manner because all such functions would - * be instantiated once per CharT -- but if exactly equivalent code would be - * generated (because PerHandlerParser functions have no awareness of CharT), + * be instantiated once per Unit -- but if exactly equivalent code would be + * generated (because PerHandlerParser functions have no awareness of Unit), * it's risky to *depend* upon the compiler coalescing the instantiations into * one in the final binary. PerHandlerParser guarantees no duplication. * - * == Parser<ParseHandler, CharT> final → GeneralParser<ParseHandler, CharT> == + * == Parser<ParseHandler, Unit> final → GeneralParser<ParseHandler, Unit> == * * The final (pun intended) axis of complexity lies in Parser. * * Some functionality depends on character type, yet also is defined in * significantly different form in full and syntax parsing. For example, * attempting to parse the source text of a module will do so in full parsing * but immediately fail in syntax parsing -- so the former is a mess'o'code * while the latter is effectively |return null();|. Such functionality is - * defined in Parser<SyntaxParseHandler or FullParseHandler, CharT> as + * defined in Parser<SyntaxParseHandler or FullParseHandler, Unit> as * appropriate. * * There's a crucial distinction between GeneralParser and Parser, that * explains why both must exist (despite taking exactly the same template * parameters, and despite GeneralParser and Parser existing in a one-to-one * relationship). GeneralParser is one unspecialized template class: * - * template<class ParseHandler, typename CharT> + * template<class ParseHandler, typename Unit> * class GeneralParser : ... * { * ...parsing functions... * }; * * but Parser is one undefined template class with two separate * specializations: * * // Declare, but do not define. - * template<class ParseHandler, typename CharT> class Parser; + * template<class ParseHandler, typename Unit> class Parser; * * // Define a syntax-parsing specialization. - * template<typename CharT> - * class Parser<SyntaxParseHandler, CharT> final - * : public GeneralParser<SyntaxParseHandler, CharT> + * template<typename Unit> + * class Parser<SyntaxParseHandler, Unit> final + * : public GeneralParser<SyntaxParseHandler, Unit> * { * ...parsing functions... * }; * * // Define a full-parsing specialization. - * template<typename CharT> - * class Parser<SyntaxParseHandler, CharT> final - * : public GeneralParser<SyntaxParseHandler, CharT> + * template<typename Unit> + * class Parser<SyntaxParseHandler, Unit> final + * : public GeneralParser<SyntaxParseHandler, Unit> * { * ...parsing functions... * }; * * This odd distinction is necessary because C++ unfortunately doesn't allow * partial function specialization: * * // BAD: You can only specialize a template function if you specify *every* - * // template parameter, i.e. ParseHandler *and* CharT. - * template<typename CharT> + * // template parameter, i.e. ParseHandler *and* Unit. + * template<typename Unit> * void - * GeneralParser<SyntaxParseHandler, CharT>::foo() {} + * GeneralParser<SyntaxParseHandler, Unit>::foo() {} * * But if you specialize Parser *as a class*, then this is allowed: * - * template<typename CharT> + * template<typename Unit> * void - * Parser<SyntaxParseHandler, CharT>::foo() {} + * Parser<SyntaxParseHandler, Unit>::foo() {} * - * template<typename CharT> + * template<typename Unit> * void - * Parser<FullParseHandler, CharT>::foo() {} + * Parser<FullParseHandler, Unit>::foo() {} * - * because the only template parameter on the function is CharT -- and so all + * because the only template parameter on the function is Unit -- and so all * template parameters *are* varying, not a strict subset of them. * * So -- any parsing functionality that is differently defined for different - * ParseHandlers, *but* is defined textually identically for different CharT + * ParseHandlers, *but* is defined textually identically for different Unit * (even if different code ends up generated for them by the compiler), should * reside in Parser. */ #include "mozilla/Array.h" #include "mozilla/Maybe.h" #include "mozilla/TypeTraits.h" @@ -185,24 +185,24 @@ namespace js { class ModuleObject; namespace frontend { class ParserBase; -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> class GeneralParser; class SourceParseContext: public ParseContext { public: - template<typename ParseHandler, typename CharT> - SourceParseContext(GeneralParser<ParseHandler, CharT>* prs, SharedContext* sc, + template<typename ParseHandler, typename Unit> + SourceParseContext(GeneralParser<ParseHandler, Unit>* prs, SharedContext* sc, Directives* newDirectives) : ParseContext(prs->context, prs->pc, sc, prs->tokenStream, prs->usedNames, newDirectives, mozilla::IsSame<ParseHandler, FullParseHandler>::value) { } }; template <typename T> inline T& @@ -240,20 +240,20 @@ enum class PropertyType { AsyncMethod, AsyncGeneratorMethod, Constructor, DerivedConstructor }; enum AwaitHandling : uint8_t { AwaitIsName, AwaitIsKeyword, AwaitIsModuleKeyword }; -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> class AutoAwaitIsKeyword; -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> class AutoInParametersOfAsyncFunction; class MOZ_STACK_CLASS ParserBase : public StrictModeGetter, private JS::AutoGCRooter { private: ParserBase* thisForCtor() { return this; } @@ -474,36 +474,36 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE // parsing of inner functions. If null, then lazy parsing is disabled. // // When ParseHandler is SyntaxParseHandler: // // If non-null, this field must be a sentinel value signaling that the // syntax parse was aborted. If null, then lazy parsing was aborted due // to encountering unsupported language constructs. // - // |internalSyntaxParser_| is really a |Parser<SyntaxParseHandler, CharT>*| - // where |CharT| varies per |Parser<ParseHandler, CharT>|. But this - // template class doesn't know |CharT|, so we store a |void*| here and make - // |GeneralParser<ParseHandler, CharT>::getSyntaxParser| impose the real type. + // |internalSyntaxParser_| is really a |Parser<SyntaxParseHandler, Unit>*| + // where |Unit| varies per |Parser<ParseHandler, Unit>|. But this + // template class doesn't know |Unit|, so we store a |void*| here and make + // |GeneralParser<ParseHandler, Unit>::getSyntaxParser| impose the real type. void* internalSyntaxParser_; private: // NOTE: The argument ordering here is deliberately different from the // public constructor so that typos calling the public constructor // are less likely to select this overload. PerHandlerParser(JSContext* cx, LifoAlloc& alloc, const JS::ReadOnlyCompileOptions& options, bool foldConstants, UsedNameTracker& usedNames, LazyScript* lazyOuterFunction, ScriptSourceObject* sourceObject, ParseGoal parseGoal, void* internalSyntaxParser); protected: - template<typename CharT> + template<typename Unit> PerHandlerParser(JSContext* cx, LifoAlloc& alloc, const JS::ReadOnlyCompileOptions& options, bool foldConstants, UsedNameTracker& usedNames, - GeneralParser<SyntaxParseHandler, CharT>* syntaxParser, + GeneralParser<SyntaxParseHandler, Unit>* syntaxParser, LazyScript* lazyOuterFunction, ScriptSourceObject* sourceObject, ParseGoal parseGoal) : PerHandlerParser(cx, alloc, options, foldConstants, usedNames, lazyOuterFunction, sourceObject, parseGoal, // JSOPTION_EXTRA_WARNINGS adds extra warnings not // generated when functions are parsed lazily. // ("use strict" doesn't inhibit lazy parsing.) static_cast<void*>(options.extraWarningsOption ? nullptr : syntaxParser)) @@ -674,38 +674,38 @@ class ParserAnyCharsAccess // [Return] because its behavior is exactly equivalent to checking whether // we're in a function box -- easier and simpler than passing an extra // parameter everywhere. enum YieldHandling { YieldIsName, YieldIsKeyword }; enum InHandling { InAllowed, InProhibited }; enum DefaultHandling { NameRequired, AllowDefaultName }; enum TripledotHandling { TripledotAllowed, TripledotProhibited }; -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> class Parser; -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> { public: - using TokenStream = TokenStreamSpecific<CharT, ParserAnyCharsAccess<GeneralParser>>; + using TokenStream = TokenStreamSpecific<Unit, ParserAnyCharsAccess<GeneralParser>>; private: using Base = PerHandlerParser<ParseHandler>; - using FinalParser = Parser<ParseHandler, CharT>; + using FinalParser = Parser<ParseHandler, Unit>; using Node = typename ParseHandler::Node; #define DECLARE_TYPE(typeName, longTypeName, asMethodName) \ using longTypeName = typename ParseHandler::longTypeName; FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) #undef DECLARE_TYPE using typename Base::InvokedPrediction; - using SyntaxParser = Parser<SyntaxParseHandler, CharT>; + using SyntaxParser = Parser<SyntaxParseHandler, Unit>; protected: using Modifier = TokenStreamShared::Modifier; using Position = typename TokenStream::Position; using Base::PredictUninvoked; using Base::PredictInvoked; @@ -832,17 +832,17 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE struct Error { ErrorState state_ = ErrorState::None; // Error reporting fields. uint32_t offset_; unsigned errorNumber_; }; - GeneralParser<ParseHandler, CharT>& parser_; + GeneralParser<ParseHandler, Unit>& parser_; Error exprError_; Error destructuringError_; Error destructuringWarning_; // Returns the error report. Error& error(ErrorKind kind); // Return true if an error is pending without reporting. @@ -862,17 +862,17 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE // If there is a pending warning, report it and return either false or // true depending on the werror option, otherwise return true. MOZ_MUST_USE bool checkForWarning(ErrorKind kind); // Transfer an existing error to another instance. void transferErrorTo(ErrorKind kind, PossibleError* other); public: - explicit PossibleError(GeneralParser<ParseHandler, CharT>& parser); + explicit PossibleError(GeneralParser<ParseHandler, Unit>& parser); // Return true if a pending destructuring error is present. bool hasPendingDestructuringError(); // Set a pending destructuring error. Only a single error may be set // per instance, i.e. subsequent calls to this method are ignored and // won't overwrite the existing pending error. void setPendingDestructuringErrorAt(const TokenPos& pos, unsigned errorNumber); @@ -909,17 +909,17 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE return reinterpret_cast<SyntaxParser*>(Base::internalSyntaxParser_); } public: TokenStream tokenStream; public: GeneralParser(JSContext* cx, LifoAlloc& alloc, const JS::ReadOnlyCompileOptions& options, - const CharT* chars, size_t length, bool foldConstants, + const Unit* units, size_t length, bool foldConstants, UsedNameTracker& usedNames, SyntaxParser* syntaxParser, LazyScript* lazyOuterFunction, ScriptSourceObject* sourceObject, ParseGoal parseGoal); inline void setAwaitHandling(AwaitHandling awaitHandling); inline void setInParametersOfAsyncFunction(bool inParameters); @@ -1302,37 +1302,37 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE bool matchOrInsertSemicolon(); bool noteDeclaredName(HandlePropertyName name, DeclarationKind kind, TokenPos pos); private: inline bool asmJS(ListNodeType list); }; -template <typename CharT> -class MOZ_STACK_CLASS Parser<SyntaxParseHandler, CharT> final - : public GeneralParser<SyntaxParseHandler, CharT> +template <typename Unit> +class MOZ_STACK_CLASS Parser<SyntaxParseHandler, Unit> final + : public GeneralParser<SyntaxParseHandler, Unit> { - using Base = GeneralParser<SyntaxParseHandler, CharT>; + using Base = GeneralParser<SyntaxParseHandler, Unit>; using Node = SyntaxParseHandler::Node; #define DECLARE_TYPE(typeName, longTypeName, asMethodName) \ using longTypeName = SyntaxParseHandler::longTypeName; FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) #undef DECLARE_TYPE - using SyntaxParser = Parser<SyntaxParseHandler, CharT>; + using SyntaxParser = Parser<SyntaxParseHandler, Unit>; // Numerous Base::* functions have bodies like // // return asFinalParser()->func(...); // // and must be able to call functions here. Add a friendship relationship // so functions here can be hidden when appropriate. - friend class GeneralParser<SyntaxParseHandler, CharT>; + friend class GeneralParser<SyntaxParseHandler, Unit>; public: using Base::Base; // Inherited types, listed here to have non-dependent names. using typename Base::Modifier; using typename Base::Position; using typename Base::TokenStream; @@ -1383,17 +1383,17 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE // Functions with multiple overloads of different visibility. We can't // |using| the whole thing into existence because of the visibility // distinction, so we instead must manually delegate the required overload. PropertyName* bindingIdentifier(YieldHandling yieldHandling) { return Base::bindingIdentifier(yieldHandling); } - // Functions present in both Parser<ParseHandler, CharT> specializations. + // Functions present in both Parser<ParseHandler, Unit> specializations. inline void setAwaitHandling(AwaitHandling awaitHandling); inline void setInParametersOfAsyncFunction(bool inParameters); RegExpLiteralType newRegExp(); // Parse a module. CodeNodeType moduleBody(ModuleSharedContext* modulesc); @@ -1416,40 +1416,40 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE FunctionAsyncKind asyncKind, bool tryAnnexB, Directives inheritedDirectives, Directives* newDirectives); bool skipLazyInnerFunction(CodeNodeType funNode, uint32_t toStringStart, FunctionSyntaxKind kind, bool tryAnnexB); bool asmJS(ListNodeType list); - // Functions present only in Parser<SyntaxParseHandler, CharT>. + // Functions present only in Parser<SyntaxParseHandler, Unit>. }; -template <typename CharT> -class MOZ_STACK_CLASS Parser<FullParseHandler, CharT> final - : public GeneralParser<FullParseHandler, CharT> +template <typename Unit> +class MOZ_STACK_CLASS Parser<FullParseHandler, Unit> final + : public GeneralParser<FullParseHandler, Unit> { - using Base = GeneralParser<FullParseHandler, CharT>; + using Base = GeneralParser<FullParseHandler, Unit>; using Node = FullParseHandler::Node; #define DECLARE_TYPE(typeName, longTypeName, asMethodName) \ using longTypeName = FullParseHandler::longTypeName; FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) #undef DECLARE_TYPE - using SyntaxParser = Parser<SyntaxParseHandler, CharT>; + using SyntaxParser = Parser<SyntaxParseHandler, Unit>; // Numerous Base::* functions have bodies like // // return asFinalParser()->func(...); // // and must be able to call functions here. Add a friendship relationship // so functions here can be hidden when appropriate. - friend class GeneralParser<FullParseHandler, CharT>; + friend class GeneralParser<FullParseHandler, Unit>; public: using Base::Base; // Inherited types, listed here to have non-dependent names. using typename Base::Modifier; using typename Base::Position; using typename Base::TokenStream; @@ -1506,22 +1506,22 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE // Functions with multiple overloads of different visibility. We can't // |using| the whole thing into existence because of the visibility // distinction, so we instead must manually delegate the required overload. PropertyName* bindingIdentifier(YieldHandling yieldHandling) { return Base::bindingIdentifier(yieldHandling); } - // Functions present in both Parser<ParseHandler, CharT> specializations. + // Functions present in both Parser<ParseHandler, Unit> specializations. - friend class AutoAwaitIsKeyword<SyntaxParseHandler, CharT>; + friend class AutoAwaitIsKeyword<SyntaxParseHandler, Unit>; inline void setAwaitHandling(AwaitHandling awaitHandling); - friend class AutoInParametersOfAsyncFunction<SyntaxParseHandler, CharT>; + friend class AutoInParametersOfAsyncFunction<SyntaxParseHandler, Unit>; inline void setInParametersOfAsyncFunction(bool inParameters); RegExpLiteralType newRegExp(); // Parse a module. CodeNodeType moduleBody(ModuleSharedContext* modulesc); BinaryNodeType importDeclaration(); @@ -1540,17 +1540,17 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE InHandling inHandling, YieldHandling yieldHandling, FunctionSyntaxKind kind, GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB, Directives inheritedDirectives, Directives* newDirectives); bool skipLazyInnerFunction(CodeNodeType funNode, uint32_t toStringStart, FunctionSyntaxKind kind, bool tryAnnexB); - // Functions present only in Parser<FullParseHandler, CharT>. + // Functions present only in Parser<FullParseHandler, Unit>. // Parse the body of an eval. // // Eval scripts are distinguished from global scripts in that in ES6, per // 18.2.1.1 steps 9 and 10, all eval scripts are executed under a fresh // lexical scope. LexicalScopeNodeType evalBody(EvalSharedContext* evalsc); @@ -1629,20 +1629,20 @@ template<class Parser> ParserAnyCharsAccess<Parser>::anyChars(GeneralTokenStreamChars* ts) { const TokenStreamAnyChars& anyCharsConst = anyChars(const_cast<const GeneralTokenStreamChars*>(ts)); return const_cast<TokenStreamAnyChars&>(anyCharsConst); } -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> class MOZ_STACK_CLASS AutoAwaitIsKeyword { - using GeneralParser = frontend::GeneralParser<ParseHandler, CharT>; + using GeneralParser = frontend::GeneralParser<ParseHandler, Unit>; private: GeneralParser* parser_; AwaitHandling oldAwaitHandling_; public: AutoAwaitIsKeyword(GeneralParser* parser, AwaitHandling awaitHandling) { parser_ = parser; @@ -1655,20 +1655,20 @@ class MOZ_STACK_CLASS AutoAwaitIsKeyword } } ~AutoAwaitIsKeyword() { parser_->setAwaitHandling(oldAwaitHandling_); } }; -template <class ParseHandler, typename CharT> +template <class ParseHandler, typename Unit> class MOZ_STACK_CLASS AutoInParametersOfAsyncFunction { - using GeneralParser = frontend::GeneralParser<ParseHandler, CharT>; + using GeneralParser = frontend::GeneralParser<ParseHandler, Unit>; private: GeneralParser* parser_; bool oldInParametersOfAsyncFunction_; public: AutoInParametersOfAsyncFunction(GeneralParser* parser, bool inParameters) { parser_ = parser;
--- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -462,21 +462,21 @@ TokenStreamAnyChars::TokenStreamAnyChars isExprEnding[size_t(TokenKind::Comma)] = true; isExprEnding[size_t(TokenKind::Semi)] = true; isExprEnding[size_t(TokenKind::Colon)] = true; isExprEnding[size_t(TokenKind::RightParen)] = true; isExprEnding[size_t(TokenKind::RightBracket)] = true; isExprEnding[size_t(TokenKind::RightCurly)] = true; } -template<typename CharT> -TokenStreamCharsBase<CharT>::TokenStreamCharsBase(JSContext* cx, const CharT* chars, size_t length, - size_t startOffset) +template<typename Unit> +TokenStreamCharsBase<Unit>::TokenStreamCharsBase(JSContext* cx, const Unit* units, size_t length, + size_t startOffset) : TokenStreamCharsShared(cx), - sourceUnits(chars, length, startOffset) + sourceUnits(units, length, startOffset) {} template<> MOZ_MUST_USE bool TokenStreamCharsBase<char16_t>::fillCharBufferFromSourceNormalizingAsciiLineBreaks(const char16_t* cur, const char16_t* end) { MOZ_ASSERT(this->charBuffer.length() == 0); @@ -532,21 +532,21 @@ TokenStreamCharsBase<Utf8Unit>::fillChar return false; } } MOZ_ASSERT(cur == end); return true; } -template<typename CharT, class AnyCharsAccess> -TokenStreamSpecific<CharT, AnyCharsAccess>::TokenStreamSpecific(JSContext* cx, - const ReadOnlyCompileOptions& options, - const CharT* base, size_t length) - : TokenStreamChars<CharT, AnyCharsAccess>(cx, base, length, options.scriptSourceOffset) +template<typename Unit, class AnyCharsAccess> +TokenStreamSpecific<Unit, AnyCharsAccess>::TokenStreamSpecific(JSContext* cx, + const ReadOnlyCompileOptions& options, + const Unit* units, size_t length) + : TokenStreamChars<Unit, AnyCharsAccess>(cx, units, length, options.scriptSourceOffset) {} bool TokenStreamAnyChars::checkOptions() { // Constrain starting columns to half of the range of a signed 32-bit value, // to avoid overflow. if (options().column >= mozilla::MaxValue<int32_t>::value / 2 + 1) { @@ -875,19 +875,19 @@ TokenStreamChars<char16_t, AnyCharsAcces } // Otherwise we have a multi-unit code point. *codePoint = unicode::UTF16Decode(lead, this->sourceUnits.getCodeUnit()); MOZ_ASSERT(!IsLineTerminator(AssertedCast<char32_t>(*codePoint))); return true; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::getCodePoint(int32_t* cp) +TokenStreamSpecific<Unit, AnyCharsAccess>::getCodePoint(int32_t* cp) { int32_t unit = getCodeUnit(); if (unit == EOF) { MOZ_ASSERT(anyCharsAccess().flags.isEOF, "flags.isEOF should have been set by getCodeUnit()"); *cp = EOF; return true; } @@ -1196,75 +1196,75 @@ SourceUnits<Utf8Unit>::findWindowEnd(siz p += len; } MOZ_ASSERT(HalfWindowSize() <= WindowRadius); return offset + HalfWindowSize(); } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::advance(size_t position) +TokenStreamSpecific<Unit, AnyCharsAccess>::advance(size_t position) { - const CharT* end = this->sourceUnits.codeUnitPtrAt(position); + const Unit* end = this->sourceUnits.codeUnitPtrAt(position); while (this->sourceUnits.addressOfNextCodeUnit() < end) { int32_t c; if (!getCodePoint(&c)) { return false; } } TokenStreamAnyChars& anyChars = anyCharsAccess(); Token* cur = const_cast<Token*>(&anyChars.currentToken()); cur->pos.begin = this->sourceUnits.offset(); MOZ_MAKE_MEM_UNDEFINED(&cur->type, sizeof(cur->type)); anyChars.lookahead = 0; return true; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> void -TokenStreamSpecific<CharT, AnyCharsAccess>::seek(const Position& pos) +TokenStreamSpecific<Unit, AnyCharsAccess>::seek(const Position& pos) { TokenStreamAnyChars& anyChars = anyCharsAccess(); this->sourceUnits.setAddressOfNextCodeUnit(pos.buf, /* allowPoisoned = */ true); anyChars.flags = pos.flags; anyChars.lineno = pos.lineno; anyChars.linebase = pos.linebase; anyChars.prevLinebase = pos.prevLinebase; anyChars.lookahead = pos.lookahead; anyChars.tokens[anyChars.cursor()] = pos.currentToken; for (unsigned i = 0; i < anyChars.lookahead; i++) { anyChars.tokens[anyChars.aheadCursor(1 + i)] = pos.lookaheadTokens[i]; } } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::seek(const Position& pos, +TokenStreamSpecific<Unit, AnyCharsAccess>::seek(const Position& pos, const TokenStreamAnyChars& other) { if (!anyCharsAccess().srcCoords.fill(other.srcCoords)) { return false; } seek(pos); return true; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::reportStrictModeErrorNumberVA(UniquePtr<JSErrorNotes> notes, - uint32_t offset, - bool strictMode, - unsigned errorNumber, - va_list* args) +TokenStreamSpecific<Unit, AnyCharsAccess>::reportStrictModeErrorNumberVA(UniquePtr<JSErrorNotes> notes, + uint32_t offset, + bool strictMode, + unsigned errorNumber, + va_list* args) { TokenStreamAnyChars& anyChars = anyCharsAccess(); if (!strictMode && !anyChars.options().extraWarningsOption) { return true; } ErrorMetadata metadata; if (!computeErrorMetadata(&metadata, offset)) { @@ -1324,42 +1324,42 @@ TokenStreamAnyChars::fillExcludingContex } // Otherwise use this TokenStreamAnyChars's location information. err->filename = filename_; srcCoords.lineNumAndColumnIndex(offset, &err->lineNumber, &err->columnNumber); return true; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::hasTokenizationStarted() const +TokenStreamSpecific<Unit, AnyCharsAccess>::hasTokenizationStarted() const { const TokenStreamAnyChars& anyChars = anyCharsAccess(); return anyChars.isCurrentTokenType(TokenKind::Eof) && !anyChars.isEOF(); } void TokenStreamAnyChars::lineAndColumnAt(size_t offset, uint32_t* line, uint32_t* column) const { srcCoords.lineNumAndColumnIndex(offset, line, column); } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> void -TokenStreamSpecific<CharT, AnyCharsAccess>::currentLineAndColumn(uint32_t* line, uint32_t* column) const +TokenStreamSpecific<Unit, AnyCharsAccess>::currentLineAndColumn(uint32_t* line, uint32_t* column) const { const TokenStreamAnyChars& anyChars = anyCharsAccess(); uint32_t offset = anyChars.currentToken().pos.begin; anyChars.srcCoords.lineNumAndColumnIndex(offset, line, column); } -template<typename CharT> +template<typename Unit> bool -TokenStreamCharsBase<CharT>::addLineOfContext(ErrorMetadata* err, uint32_t offset) +TokenStreamCharsBase<Unit>::addLineOfContext(ErrorMetadata* err, uint32_t offset) { size_t windowStart = sourceUnits.findWindowStart(offset); size_t windowEnd = sourceUnits.findWindowEnd(offset); size_t windowLength = windowEnd - windowStart; MOZ_ASSERT(windowLength <= SourceUnits::WindowRadius * 2); // Don't add a useless "line" of context when the window ends up empty @@ -1372,17 +1372,17 @@ TokenStreamCharsBase<CharT>::addLineOfCo } // We might have hit an error while processing some source code feature // that's accumulating text into |this->charBuffer| -- e.g. we could be // halfway into a regular expression literal, then encounter invalid UTF-8. // Thus we must clear |this->charBuffer| of prior work. this->charBuffer.clear(); - const CharT* start = sourceUnits.codeUnitPtrAt(windowStart); + const Unit* start = sourceUnits.codeUnitPtrAt(windowStart); if (!fillCharBufferFromSourceNormalizingAsciiLineBreaks(start, start + windowLength)) { return false; } // The windowed string is null-terminated. if (!this->charBuffer.append('\0')) { return false; } @@ -1392,20 +1392,20 @@ TokenStreamCharsBase<CharT>::addLineOfCo return false; } err->lineLength = windowLength; err->tokenOffset = offset - windowStart; return true; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::computeErrorMetadata(ErrorMetadata* err, - uint32_t offset) +TokenStreamSpecific<Unit, AnyCharsAccess>::computeErrorMetadata(ErrorMetadata* err, + uint32_t offset) { if (offset == NoOffset) { anyCharsAccess().computeErrorMetadataNoOffset(err); return true; } // This function's return value isn't a success/failure indication: it // returns true if this TokenStream's location information could be used, @@ -1414,34 +1414,34 @@ TokenStreamSpecific<CharT, AnyCharsAcces if (!anyCharsAccess().fillExcludingContext(err, offset)) { return true; } // Add a line of context from this TokenStream to help with debugging. return internalComputeLineOfContext(err, offset); } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::reportStrictModeError(unsigned errorNumber, ...) +TokenStreamSpecific<Unit, AnyCharsAccess>::reportStrictModeError(unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); TokenStreamAnyChars& anyChars = anyCharsAccess(); bool result = reportStrictModeErrorNumberVA(nullptr, anyChars.currentToken().pos.begin, anyChars.strictMode(), errorNumber, &args); va_end(args); return result; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> void -TokenStreamSpecific<CharT, AnyCharsAccess>::reportError(unsigned errorNumber, ...) +TokenStreamSpecific<Unit, AnyCharsAccess>::reportError(unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); TokenStreamAnyChars& anyChars = anyCharsAccess(); ErrorMetadata metadata; if (computeErrorMetadata(&metadata, anyChars.currentToken().pos.begin)) { ReportCompileError(anyChars.cx, std::move(metadata), nullptr, JSREPORT_ERROR, errorNumber, @@ -1466,111 +1466,111 @@ void TokenStreamAnyChars::reportErrorNoOffsetVA(unsigned errorNumber, va_list args) { ErrorMetadata metadata; computeErrorMetadataNoOffset(&metadata); ReportCompileError(cx, std::move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args); } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::warning(unsigned errorNumber, ...) +TokenStreamSpecific<Unit, AnyCharsAccess>::warning(unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); ErrorMetadata metadata; bool result = computeErrorMetadata(&metadata, anyCharsAccess().currentToken().pos.begin) && anyCharsAccess().compileWarning(std::move(metadata), nullptr, JSREPORT_WARNING, errorNumber, args); va_end(args); return result; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::reportExtraWarningErrorNumberVA(UniquePtr<JSErrorNotes> notes, - uint32_t offset, - unsigned errorNumber, - va_list* args) +TokenStreamSpecific<Unit, AnyCharsAccess>::reportExtraWarningErrorNumberVA(UniquePtr<JSErrorNotes> notes, + uint32_t offset, + unsigned errorNumber, + va_list* args) { TokenStreamAnyChars& anyChars = anyCharsAccess(); if (!anyChars.options().extraWarningsOption) { return true; } ErrorMetadata metadata; if (!computeErrorMetadata(&metadata, offset)) { return false; } return anyChars.compileWarning(std::move(metadata), std::move(notes), JSREPORT_STRICT | JSREPORT_WARNING, errorNumber, *args); } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> void -TokenStreamSpecific<CharT, AnyCharsAccess>::error(unsigned errorNumber, ...) +TokenStreamSpecific<Unit, AnyCharsAccess>::error(unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); ErrorMetadata metadata; if (computeErrorMetadata(&metadata, this->sourceUnits.offset())) { TokenStreamAnyChars& anyChars = anyCharsAccess(); ReportCompileError(anyChars.cx, std::move(metadata), nullptr, JSREPORT_ERROR, errorNumber, args); } va_end(args); } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> void -TokenStreamSpecific<CharT, AnyCharsAccess>::errorAtVA(uint32_t offset, unsigned errorNumber, va_list *args) +TokenStreamSpecific<Unit, AnyCharsAccess>::errorAtVA(uint32_t offset, unsigned errorNumber, va_list *args) { ErrorMetadata metadata; if (computeErrorMetadata(&metadata, offset)) { TokenStreamAnyChars& anyChars = anyCharsAccess(); ReportCompileError(anyChars.cx, std::move(metadata), nullptr, JSREPORT_ERROR, errorNumber, *args); } } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> void -TokenStreamSpecific<CharT, AnyCharsAccess>::errorAt(uint32_t offset, unsigned errorNumber, ...) +TokenStreamSpecific<Unit, AnyCharsAccess>::errorAt(uint32_t offset, unsigned errorNumber, ...) { va_list args; va_start(args, errorNumber); errorAtVA(offset, errorNumber, &args); va_end(args); } // We have encountered a '\': check for a Unicode escape sequence after it. // Return the length of the escape sequence and the encoded code point (by // value) if we found a Unicode escape sequence, and skip all code units // involed. Otherwise, return 0 and don't advance along the buffer. -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> uint32_t -GeneralTokenStreamChars<CharT, AnyCharsAccess>::matchUnicodeEscape(uint32_t* codePoint) +GeneralTokenStreamChars<Unit, AnyCharsAccess>::matchUnicodeEscape(uint32_t* codePoint) { - MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('\\')); + MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == Unit('\\')); int32_t unit = getCodeUnit(); if (unit != 'u') { // NOTE: |unit| may be EOF here. ungetCodeUnit(unit); - MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('\\')); + MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == Unit('\\')); return 0; } char16_t v; unit = getCodeUnit(); if (JS7_ISHEX(unit) && this->sourceUnits.matchHexDigits(3, &v)) { *codePoint = (JS7_UNHEX(unit) << 12) | v; return 5; @@ -1578,25 +1578,25 @@ GeneralTokenStreamChars<CharT, AnyCharsA if (unit == '{') { return matchExtendedUnicodeEscape(codePoint); } // NOTE: |unit| may be EOF here, so this ungets either one or two units. ungetCodeUnit(unit); ungetCodeUnit('u'); - MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('\\')); + MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == Unit('\\')); return 0; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> uint32_t -GeneralTokenStreamChars<CharT, AnyCharsAccess>::matchExtendedUnicodeEscape(uint32_t* codePoint) +GeneralTokenStreamChars<Unit, AnyCharsAccess>::matchExtendedUnicodeEscape(uint32_t* codePoint) { - MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('{')); + MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == Unit('{')); int32_t unit = getCodeUnit(); // Skip leading zeroes. uint32_t leadingZeroes = 0; while (unit == '0') { leadingZeroes++; unit = getCodeUnit(); @@ -1617,58 +1617,58 @@ GeneralTokenStreamChars<CharT, AnyCharsA (unit != EOF); // subtract a get if it didn't contribute to length if (unit == '}' && (leadingZeroes > 0 || i > 0) && code <= unicode::NonBMPMax) { *codePoint = code; return gotten; } this->sourceUnits.unskipCodeUnits(gotten); - MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('\\')); + MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == Unit('\\')); return 0; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> uint32_t -GeneralTokenStreamChars<CharT, AnyCharsAccess>::matchUnicodeEscapeIdStart(uint32_t* codePoint) +GeneralTokenStreamChars<Unit, AnyCharsAccess>::matchUnicodeEscapeIdStart(uint32_t* codePoint) { uint32_t length = matchUnicodeEscape(codePoint); if (MOZ_LIKELY(length > 0)) { if (MOZ_LIKELY(unicode::IsIdentifierStart(*codePoint))) { return length; } this->sourceUnits.unskipCodeUnits(length); } - MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('\\')); + MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == Unit('\\')); return 0; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -GeneralTokenStreamChars<CharT, AnyCharsAccess>::matchUnicodeEscapeIdent(uint32_t* codePoint) +GeneralTokenStreamChars<Unit, AnyCharsAccess>::matchUnicodeEscapeIdent(uint32_t* codePoint) { uint32_t length = matchUnicodeEscape(codePoint); if (MOZ_LIKELY(length > 0)) { if (MOZ_LIKELY(unicode::IsIdentifierPart(*codePoint))) { return true; } this->sourceUnits.unskipCodeUnits(length); } - MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('\\')); + MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == Unit('\\')); return false; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::getDirectives(bool isMultiline, - bool shouldWarnDeprecated) +TokenStreamSpecific<Unit, AnyCharsAccess>::getDirectives(bool isMultiline, + bool shouldWarnDeprecated) { // Match directive comments used in debugging, such as "//# sourceURL" and // "//# sourceMappingURL". Use of "//@" instead of "//#" is deprecated. // // To avoid a crashing bug in IE, several JavaScript transpilers wrap single // line comments containing a source mapping URL inside a multiline // comment. To avoid potentially expensive lookahead and backtracking, we // only check for this case if we encounter a '#' code unit. @@ -1693,24 +1693,24 @@ TokenStreamCharsShared::copyCharBufferTo return false; } std::copy(charBuffer.begin(), charBuffer.end(), destination->get()); (*destination)[length] = '\0'; return true; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> MOZ_MUST_USE bool -TokenStreamSpecific<CharT, AnyCharsAccess>::getDirective(bool isMultiline, - bool shouldWarnDeprecated, - const char* directive, - uint8_t directiveLength, - const char* errorMsgPragma, - UniquePtr<char16_t[], JS::FreePolicy>* destination) +TokenStreamSpecific<Unit, AnyCharsAccess>::getDirective(bool isMultiline, + bool shouldWarnDeprecated, + const char* directive, + uint8_t directiveLength, + const char* errorMsgPragma, + UniquePtr<char16_t[], JS::FreePolicy>* destination) { // Stop if we don't find |directive|. (Note that |directive| must be // ASCII, so there are no tricky encoding issues to consider in matching // UTF-8/16-agnostically.) if (!this->sourceUnits.matchCodeUnits(directive, directiveLength)) { return true; } @@ -1747,17 +1747,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces return false; } continue; } // This ignores encoding errors: subsequent caller-side code to // handle the remaining source text in the comment will do so. - PeekedCodePoint<CharT> peeked = this->sourceUnits.peekCodePoint(); + PeekedCodePoint<Unit> peeked = this->sourceUnits.peekCodePoint(); if (peeked.isNone() || unicode::IsSpaceOrBOM2(peeked.codePoint())) { break; } MOZ_ASSERT(!IsLineTerminator(peeked.codePoint()), "!IsSpaceOrBOM2 must imply !IsLineTerminator or else we'll " "fail to maintain line-info/flags for EOL"); this->sourceUnits.consumeKnownCodePoint(peeked); @@ -1771,55 +1771,55 @@ TokenStreamSpecific<CharT, AnyCharsAcces // The directive's URL was missing, but comments can contain anything, // so it isn't an error. return true; } return copyCharBufferTo(anyCharsAccess().cx, destination); } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::getDisplayURL(bool isMultiline, - bool shouldWarnDeprecated) +TokenStreamSpecific<Unit, AnyCharsAccess>::getDisplayURL(bool isMultiline, + bool shouldWarnDeprecated) { // Match comments of the form "//# sourceURL=<url>" or // "/\* //# sourceURL=<url> *\/" // // Note that while these are labeled "sourceURL" in the source text, // internally we refer to it as a "displayURL" to distinguish what the // developer would like to refer to the source as from the source's actual // URL. static const char sourceURLDirective[] = " sourceURL="; constexpr uint8_t sourceURLDirectiveLength = ArrayLength(sourceURLDirective) - 1; return getDirective(isMultiline, shouldWarnDeprecated, sourceURLDirective, sourceURLDirectiveLength, "sourceURL", &anyCharsAccess().displayURL_); } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::getSourceMappingURL(bool isMultiline, - bool shouldWarnDeprecated) +TokenStreamSpecific<Unit, AnyCharsAccess>::getSourceMappingURL(bool isMultiline, + bool shouldWarnDeprecated) { // Match comments of the form "//# sourceMappingURL=<url>" or // "/\* //# sourceMappingURL=<url> *\/" static const char sourceMappingURLDirective[] = " sourceMappingURL="; constexpr uint8_t sourceMappingURLDirectiveLength = ArrayLength(sourceMappingURLDirective) - 1; return getDirective(isMultiline, shouldWarnDeprecated, sourceMappingURLDirective, sourceMappingURLDirectiveLength, "sourceMappingURL", &anyCharsAccess().sourceMapURL_); } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> MOZ_ALWAYS_INLINE Token* -GeneralTokenStreamChars<CharT, AnyCharsAccess>::newTokenInternal(TokenKind kind, TokenStart start, - TokenKind* out) +GeneralTokenStreamChars<Unit, AnyCharsAccess>::newTokenInternal(TokenKind kind, TokenStart start, + TokenKind* out) { MOZ_ASSERT(kind < TokenKind::Limit); MOZ_ASSERT(kind != TokenKind::Eol, "TokenKind::Eol should never be used in an actual Token, only " "returned by peekTokenSameLine()"); TokenStreamAnyChars& anyChars = anyCharsAccess(); anyChars.flags.isDirtyLine = true; @@ -1832,19 +1832,19 @@ GeneralTokenStreamChars<CharT, AnyCharsA // NOTE: |token->modifier| and |token->modifierException| are set in // |newToken()| so that optimized, non-debug code won't do any work // to pass a modifier-argument that will never be used. return token; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> MOZ_COLD bool -GeneralTokenStreamChars<CharT, AnyCharsAccess>::badToken() +GeneralTokenStreamChars<Unit, AnyCharsAccess>::badToken() { // We didn't get a token, so don't set |flags.isDirtyLine|. anyCharsAccess().flags.hadError = true; // Poisoning sourceUnits on error establishes an invariant: once an // erroneous token has been seen, sourceUnits will not be consulted again. // This is true because the parser will deal with the illegal token by // aborting parsing immediately. @@ -1869,21 +1869,21 @@ TokenStreamCharsShared::appendCodePointT if (numUnits == 1) { return true; } return charBuffer.append(units[1]); } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::putIdentInCharBuffer(const CharT* identStart) +TokenStreamSpecific<Unit, AnyCharsAccess>::putIdentInCharBuffer(const Unit* identStart) { - const CharT* const originalAddress = this->sourceUnits.addressOfNextCodeUnit(); + const Unit* const originalAddress = this->sourceUnits.addressOfNextCodeUnit(); this->sourceUnits.setAddressOfNextCodeUnit(identStart); auto restoreNextRawCharAddress = MakeScopeExit([this, originalAddress]() { this->sourceUnits.setAddressOfNextCodeUnit(originalAddress); }); this->charBuffer.clear(); @@ -1905,17 +1905,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces if (unit != '\\' || !matchUnicodeEscapeIdent(&codePoint)) { break; } } else { // |restoreNextRawCharAddress| undoes all gets, and this function // doesn't update line/column info. char32_t cp; - if (!getNonAsciiCodePointDontNormalize(toCharT(unit), &cp)) { + if (!getNonAsciiCodePointDontNormalize(toUnit(unit), &cp)) { return false; } codePoint = cp; if (!unicode::IsIdentifierPart(codePoint)) { break; } } @@ -1923,22 +1923,22 @@ TokenStreamSpecific<CharT, AnyCharsAcces if (!appendCodePointToCharBuffer(codePoint)) { return false; } } while (true); return true; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> MOZ_MUST_USE bool -TokenStreamSpecific<CharT, AnyCharsAccess>::identifierName(TokenStart start, - const CharT* identStart, - IdentifierEscapes escaping, - Modifier modifier, TokenKind* out) +TokenStreamSpecific<Unit, AnyCharsAccess>::identifierName(TokenStart start, + const Unit* identStart, + IdentifierEscapes escaping, + 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(); }); // We've already consumed an initial code point in the identifer, to *know* @@ -1963,17 +1963,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces break; } escaping = IdentifierEscapes::SawUnicodeEscape; } } else { // This ignores encoding errors: subsequent caller-side code to // handle source text after the IdentifierName will do so. - PeekedCodePoint<CharT> peeked = this->sourceUnits.peekCodePoint(); + PeekedCodePoint<Unit> peeked = this->sourceUnits.peekCodePoint(); if (peeked.isNone() || !unicode::IsIdentifierPart(peeked.codePoint())) { break; } MOZ_ASSERT(!IsLineTerminator(peeked.codePoint()), "IdentifierPart must guarantee !IsLineTerminator or " "else we'll fail to maintain line-info/flags for EOL"); @@ -1987,17 +1987,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces // tokenbuf before atomizing. if (!putIdentInCharBuffer(identStart)) { return false; } atom = drainCharBufferIntoAtom(anyCharsAccess().cx); } else { // Escape-free identifiers can be created directly from sourceUnits. - const CharT* chars = identStart; + const Unit* chars = identStart; size_t length = this->sourceUnits.addressOfNextCodeUnit() - identStart; // Represent reserved words lacking escapes as reserved word tokens. if (const ReservedWordInfo* rw = FindReservedWord(chars, length)) { noteBadToken.release(); newSimpleToken(rw->tokentype, start, modifier, out); return true; } @@ -2136,21 +2136,21 @@ SourceUnits<Utf8Unit>::consumeRestOfSing if (MOZ_UNLIKELY(c == unicode::LINE_SEPARATOR || c == unicode::PARA_SEPARATOR)) { return; } consumeKnownCodePoint(peeked); } } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> MOZ_MUST_USE bool -TokenStreamSpecific<CharT, AnyCharsAccess>::decimalNumber(int32_t unit, TokenStart start, - const CharT* numStart, - Modifier modifier, TokenKind* out) +TokenStreamSpecific<Unit, AnyCharsAccess>::decimalNumber(int32_t unit, TokenStart start, + const Unit* 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. @@ -2220,42 +2220,42 @@ TokenStreamSpecific<CharT, AnyCharsAcces if (MOZ_LIKELY(isAsciiCodePoint(unit))) { if (unicode::IsIdentifierStart(char16_t(unit))) { error(JSMSG_IDSTART_AFTER_NUMBER); return false; } } else { // This ignores encoding errors: subsequent caller-side code to // handle source text after the number will do so. - PeekedCodePoint<CharT> peeked = this->sourceUnits.peekCodePoint(); + PeekedCodePoint<Unit> peeked = this->sourceUnits.peekCodePoint(); if (!peeked.isNone() && unicode::IsIdentifierStart(peeked.codePoint())) { error(JSMSG_IDSTART_AFTER_NUMBER); return false; } } } noteBadToken.release(); newNumberToken(dval, decimalPoint, start, modifier, out); return true; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> MOZ_MUST_USE bool -TokenStreamSpecific<CharT, AnyCharsAccess>::regexpLiteral(TokenStart start, TokenKind* out) +TokenStreamSpecific<Unit, AnyCharsAccess>::regexpLiteral(TokenStart start, TokenKind* out) { - MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('/')); + MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == Unit('/')); this->charBuffer.clear(); auto ProcessNonAsciiCodePoint = [this](int32_t lead) { MOZ_ASSERT(lead != EOF); MOZ_ASSERT(!this->isAsciiCodePoint(lead)); char32_t codePoint; - if (!this->getNonAsciiCodePointDontNormalize(this->toCharT(lead), &codePoint)) { + if (!this->getNonAsciiCodePointDontNormalize(this->toUnit(lead), &codePoint)) { return false; } if (MOZ_UNLIKELY(codePoint == unicode::LINE_SEPARATOR || codePoint == unicode::PARA_SEPARATOR)) { this->sourceUnits.ungetLineOrParagraphSeparator(); this->reportError(JSMSG_UNTERMINATED_REGEXP); @@ -2359,20 +2359,20 @@ TokenStreamSpecific<CharT, AnyCharsAcces reflags = RegExpFlag(reflags | flag); } ungetCodeUnit(unit); newRegExpToken(reflags, start, out); return true; } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> MOZ_MUST_USE bool -TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* const ttp, - const Modifier modifier) +TokenStreamSpecific<Unit, AnyCharsAccess>::getTokenInternal(TokenKind* const ttp, + const Modifier modifier) { // Assume we'll fail: success cases will overwrite this. #ifdef DEBUG *ttp = TokenKind::Limit; #endif MOZ_MAKE_MEM_UNDEFINED(ttp, sizeof(*ttp)); // Check if in the middle of a template string. Have to get this out of @@ -2396,19 +2396,19 @@ TokenStreamSpecific<CharT, AnyCharsAcces 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(this->sourceUnits, 0); - const CharT* identStart = this->sourceUnits.addressOfNextCodeUnit(); - - PeekedCodePoint<CharT> peeked = this->sourceUnits.peekCodePoint(); + const Unit* identStart = this->sourceUnits.addressOfNextCodeUnit(); + + PeekedCodePoint<Unit> peeked = this->sourceUnits.peekCodePoint(); if (peeked.isNone()) { int32_t bad; MOZ_ALWAYS_FALSE(getCodePoint(&bad)); return badToken(); } char32_t cp = peeked.codePoint(); if (unicode::IsSpaceOrBOM2(cp)) { @@ -2491,17 +2491,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces return identifierName(start, this->sourceUnits.addressOfNextCodeUnit() - 1, IdentifierEscapes::None, modifier, ttp); } // Look for a decimal number. // if (c1kind == Dec) { TokenStart start(this->sourceUnits, -1); - const CharT* numStart = this->sourceUnits.addressOfNextCodeUnit() - 1; + const Unit* numStart = this->sourceUnits.addressOfNextCodeUnit() - 1; return decimalNumber(unit, start, numStart, modifier, ttp); } // Look for a string or a template string. // if (c1kind == String) { return getStringOrTemplateToken(static_cast<char>(unit), modifier, ttp); } @@ -2524,17 +2524,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces // From a '0', look for a hexadecimal, binary, octal, or "noctal" (a // number starting with '0' that contains '8' or '9' and is treated as // decimal) number. // if (c1kind == ZeroDigit) { TokenStart start(this->sourceUnits, -1); int radix; - const CharT* numStart; + const Unit* numStart; unit = getCodeUnit(); if (unit == 'x' || unit == 'X') { radix = 16; unit = getCodeUnit(); if (!JS7_ISHEX(unit)) { // NOTE: |unit| may be EOF here. ungetCodeUnit(unit); error(JSMSG_MISSING_HEXDIGITS); @@ -2623,17 +2623,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces if (MOZ_LIKELY(isAsciiCodePoint(unit))) { if (unicode::IsIdentifierStart(char16_t(unit))) { error(JSMSG_IDSTART_AFTER_NUMBER); return badToken(); } } else if (MOZ_LIKELY(unit != EOF)) { // This ignores encoding errors: subsequent caller-side code to // handle source text after the number will do so. - PeekedCodePoint<CharT> peeked = this->sourceUnits.peekCodePoint(); + PeekedCodePoint<Unit> peeked = this->sourceUnits.peekCodePoint(); if (!peeked.isNone() && unicode::IsIdentifierStart(peeked.codePoint())) { error(JSMSG_IDSTART_AFTER_NUMBER); return badToken(); } } double dval; if (!GetFullInteger(anyCharsAccess().cx, numStart, @@ -2655,17 +2655,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces TokenStart start(this->sourceUnits, -1); TokenKind simpleKind; #ifdef DEBUG simpleKind = TokenKind::Limit; // sentinel value for code after switch #endif // The block a ways above eliminated all non-ASCII, so cast to the // smallest type possible to assist the C++ compiler. - switch (AssertedCast<uint8_t>(CodeUnitValue(toCharT(unit)))) { + switch (AssertedCast<uint8_t>(CodeUnitValue(toUnit(unit)))) { case '.': unit = getCodeUnit(); if (IsAsciiDigit(unit)) { return decimalNumber('.', start, this->sourceUnits.addressOfNextCodeUnit() - 2, modifier, ttp); } if (unit == '.') { @@ -2879,32 +2879,32 @@ TokenStreamSpecific<CharT, AnyCharsAcces break; default: // 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 (AssertedCast<uint8_t>(CodeUnitValue(toCharT(unit)))) + } // switch (AssertedCast<uint8_t>(CodeUnitValue(toUnit(unit)))) MOZ_ASSERT(simpleKind != TokenKind::Limit, "switch-statement should have set |simpleKind| before " "breaking"); newSimpleToken(simpleKind, start, modifier, ttp); return true; } while (true); } -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> bool -TokenStreamSpecific<CharT, AnyCharsAccess>::getStringOrTemplateToken(char untilChar, - Modifier modifier, - TokenKind* out) +TokenStreamSpecific<Unit, AnyCharsAccess>::getStringOrTemplateToken(char untilChar, + Modifier modifier, + TokenKind* out) { MOZ_ASSERT(untilChar == '\'' || untilChar == '"' || untilChar == '`', "unexpected string/template literal delimiter"); bool parsingTemplate = (untilChar == '`'); bool templateHead = false; TokenStart start(this->sourceUnits, -1); @@ -2915,18 +2915,18 @@ TokenStreamSpecific<CharT, AnyCharsAcces 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() == CharT('\r') || - this->sourceUnits.peekCodeUnit() == CharT('\n'), + this->sourceUnits.peekCodeUnit() == Unit('\r') || + this->sourceUnits.peekCodeUnit() == Unit('\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; @@ -2945,17 +2945,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces // 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-ASCII case early for readability. if (MOZ_UNLIKELY(!isAsciiCodePoint(unit))) { char32_t cp; - if (!getNonAsciiCodePointDontNormalize(toCharT(unit), &cp)) { + if (!getNonAsciiCodePointDontNormalize(toUnit(unit), &cp)) { return false; } if (MOZ_UNLIKELY(cp == unicode::LINE_SEPARATOR || cp == unicode::PARA_SEPARATOR)) { if (!updateLineInfoForEOL()) { return false; } @@ -2999,17 +2999,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces } } continue; } // The block above eliminated all non-ASCII, so cast to the // smallest type possible to assist the C++ compiler. - switch (AssertedCast<uint8_t>(CodeUnitValue(toCharT(unit)))) { + switch (AssertedCast<uint8_t>(CodeUnitValue(toUnit(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': @@ -3202,17 +3202,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces val = save; } } } unit = char16_t(val); break; } // default - } // switch (AssertedCast<uint8_t>(CodeUnitValue(toCharT(unit)))) + } // switch (AssertedCast<uint8_t>(CodeUnitValue(toUnit(unit)))) if (!this->charBuffer.append(unit)) { return false; } continue; } // (unit == '\\')
--- a/js/src/frontend/TokenStream.h +++ b/js/src/frontend/TokenStream.h @@ -17,18 +17,18 @@ /* * [SMDOC] Parser Token Stream * * A token stream exposes the raw tokens -- operators, names, numbers, * keywords, and so on -- of JavaScript source code. * * These are the components of the overall token stream concept: - * TokenStreamShared, TokenStreamAnyChars, TokenStreamCharsBase<CharT>, - * TokenStreamChars<CharT>, and TokenStreamSpecific<CharT, AnyCharsAccess>. + * TokenStreamShared, TokenStreamAnyChars, TokenStreamCharsBase<Unit>, + * TokenStreamChars<Unit>, and TokenStreamSpecific<Unit, AnyCharsAccess>. * * == TokenStreamShared → ∅ == * * Certain aspects of tokenizing are used everywhere: * * * modifiers (used to select which context-sensitive interpretation of a * character should be used to decide what token it is), modifier * exceptions, and modifier assertion handling; @@ -48,17 +48,17 @@ * current and next tokens (is the token of the given type? what name or * number is contained in the token? and other queries), and others. * * All this data/functionality *could* be duplicated for both single-byte and * double-byte tokenizing, but there are two problems. First, it's potentially * wasteful if the compiler doesnt recognize it can unify the concepts. (And * if any-character concepts are intermixed with character-specific concepts, * potentially the compiler *can't* unify them because offsets into the - * hypothetical TokenStream<CharT>s would differ.) Second, some of this stuff + * hypothetical TokenStream<Unit>s would differ.) Second, some of this stuff * needs to be accessible in ParserBase, the aspects of JS language parsing * that have meaning independent of the character type of the source text being * parsed. So we need a separate data structure that ParserBase can hold on to * for it. (ParserBase isn't the only instance of this, but it's certainly the * biggest case of it.) Ergo, TokenStreamAnyChars. * * == TokenStreamCharsShared → ∅ == * @@ -67,61 +67,61 @@ * TokenStreamAnyChars, but it makes more sense to live in a separate class * that character-aware token information can simply inherit. * * This class currently exists only to contain a char16_t buffer, transiently * used to accumulate strings in tricky cases that can't just be read directly * from source text. It's not used outside character-aware tokenizing, so it * doesn't make sense in TokenStreamAnyChars. * - * == TokenStreamCharsBase<CharT> → TokenStreamCharsShared == + * == TokenStreamCharsBase<Unit> → TokenStreamCharsShared == * * Certain data structures in tokenizing are character-type-specific: namely, * the various pointers identifying the source text (including current offset * and end). * * Additionally, some functions operating on this data are defined the same way * no matter what character type you have (e.g. current offset in code units * into the source text) or share a common interface regardless of character * type (e.g. consume the next code unit if it has a given value). * - * All such functionality lives in TokenStreamCharsBase<CharT>. + * All such functionality lives in TokenStreamCharsBase<Unit>. * - * == SpecializedTokenStreamCharsBase<CharT> → TokenStreamCharsBase<CharT> == + * == SpecializedTokenStreamCharsBase<Unit> → TokenStreamCharsBase<Unit> == * * Certain tokenizing functionality is specific to a single character type. * For example, JS's UTF-16 encoding recognizes no coding errors, because lone * surrogates are not an error; but a UTF-8 encoding must recognize a variety * of validation errors. Such functionality is defined only in the appropriate * SpecializedTokenStreamCharsBase specialization. * - * == GeneralTokenStreamChars<CharT, AnyCharsAccess> → - * SpecializedTokenStreamCharsBase<CharT> == + * == GeneralTokenStreamChars<Unit, AnyCharsAccess> → + * SpecializedTokenStreamCharsBase<Unit> == * * Some functionality operates differently on different character types, just * as for TokenStreamCharsBase, but additionally requires access to character- * type-agnostic information in TokenStreamAnyChars. For example, getting the * next character performs different steps for different character types and * must access TokenStreamAnyChars to update line break information. * * Such functionality, if it can be defined using the same algorithm for all - * character types, lives in GeneralTokenStreamChars<CharT, AnyCharsAccess>. + * character types, lives in GeneralTokenStreamChars<Unit, AnyCharsAccess>. * The AnyCharsAccess parameter provides a way for a GeneralTokenStreamChars * instance to access its corresponding TokenStreamAnyChars, without inheriting * from it. * - * GeneralTokenStreamChars<CharT, AnyCharsAccess> is just functionality, no + * GeneralTokenStreamChars<Unit, AnyCharsAccess> is just functionality, no * actual member data. * - * Such functionality all lives in TokenStreamChars<CharT, AnyCharsAccess>, a + * Such functionality all lives in TokenStreamChars<Unit, AnyCharsAccess>, a * declared-but-not-defined template class whose specializations have a common * public interface (plus whatever private helper functions are desirable). * - * == TokenStreamChars<CharT, AnyCharsAccess> → - * GeneralTokenStreamChars<CharT, AnyCharsAccess> == + * == TokenStreamChars<Unit, AnyCharsAccess> → + * GeneralTokenStreamChars<Unit, AnyCharsAccess> == * * Some functionality is like that in GeneralTokenStreamChars, *but* it's * defined entirely differently for different character types. * * For example, consider "match a multi-code unit code point" (hypothetically: * we've only implemented two-byte tokenizing right now): * * * For two-byte text, there must be two code units to get, the leading code @@ -132,47 +132,47 @@ * * For single-byte UTF-8 text, the first code unit must have N > 1 of its * highest bits set (and the next unset), and |N - 1| successive code units * must have their high bit set and next-highest bit unset, *and* * concatenating all unconstrained bits together must not produce a code * point value that could have been encoded in fewer code units. * * This functionality can't be implemented as member functions in * GeneralTokenStreamChars because we'd need to *partially specialize* those - * functions -- hold CharT constant while letting AnyCharsAccess vary. But + * functions -- hold Unit constant while letting AnyCharsAccess vary. But * C++ forbids function template partial specialization like this: either you * fix *all* parameters or you fix none of them. * * Fortunately, C++ *does* allow *class* template partial specialization. So - * TokenStreamChars is a template class with one specialization per CharT. + * TokenStreamChars is a template class with one specialization per Unit. * Functions can be defined differently in the different specializations, * because AnyCharsAccess as the only template parameter on member functions * *can* vary. * - * All TokenStreamChars<CharT, AnyCharsAccess> specializations, one per CharT, + * All TokenStreamChars<Unit, AnyCharsAccess> specializations, one per Unit, * are just functionality, no actual member data. * - * == TokenStreamSpecific<CharT, AnyCharsAccess> → - * TokenStreamChars<CharT, AnyCharsAccess>, TokenStreamShared == + * == TokenStreamSpecific<Unit, AnyCharsAccess> → + * TokenStreamChars<Unit, AnyCharsAccess>, TokenStreamShared == * * TokenStreamSpecific is operations that are parametrized on character type * but implement the *general* idea of tokenizing, without being intrinsically * tied to character type. Notably, this includes all operations that can * report warnings or errors at particular offsets, because we include a line * of context with such errors -- and that necessarily accesses the raw * characters of their specific type. * * Much TokenStreamSpecific operation depends on functionality in * TokenStreamAnyChars. The obvious solution is to inherit it -- but this * doesn't work in Parser: its ParserBase base class needs some * TokenStreamAnyChars functionality without knowing character type. * * The AnyCharsAccess type parameter is a class that statically converts from a * TokenStreamSpecific* to its corresponding TokenStreamAnyChars. The - * TokenStreamSpecific in Parser<ParseHandler, CharT> can then specify a class + * TokenStreamSpecific in Parser<ParseHandler, Unit> can then specify a class * that properly converts from TokenStreamSpecific Parser::tokenStream to * TokenStreamAnyChars ParserBase::anyChars. * * Could we hardcode one set of offset calculations for this and eliminate * AnyCharsAccess? No. Offset calculations possibly could be hardcoded if * TokenStreamSpecific were present in Parser before Parser::handler, assuring * the same offsets in all Parser-related cases. But there's still a separate * TokenStream class, that requires different offset calculations. So even if @@ -489,33 +489,33 @@ struct TokenStreamFlags bool hadError:1; // Hit a syntax error, at start or during a // token. TokenStreamFlags() : isEOF(), isDirtyLine(), sawOctalEscape(), hadError() {} }; -template<typename CharT> +template<typename Unit> class TokenStreamPosition; /** * TokenStream types and constants that are used in both TokenStreamAnyChars * and TokenStreamSpecific. Do not add any non-static data members to this * class! */ class TokenStreamShared { protected: static constexpr size_t ntokens = 4; // 1 current + 2 lookahead, rounded // to power of 2 to avoid divmod by 3 static constexpr unsigned ntokensMask = ntokens - 1; - template<typename CharT> friend class TokenStreamPosition; + template<typename Unit> friend class TokenStreamPosition; public: static constexpr unsigned maxLookahead = 2; static constexpr uint32_t NoOffset = UINT32_MAX; using Modifier = Token::Modifier; static constexpr Modifier None = Token::None; @@ -555,65 +555,65 @@ class TokenStreamShared "tokenization non-deterministic"); #endif } }; static_assert(mozilla::IsEmpty<TokenStreamShared>::value, "TokenStreamShared shouldn't bloat classes that inherit from it"); -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> class TokenStreamSpecific; -template<typename CharT> +template<typename Unit> class MOZ_STACK_CLASS TokenStreamPosition final { public: // The JS_HAZ_ROOTED is permissible below because: 1) the only field in // TokenStreamPosition that can keep GC things alive is Token, 2) the only // GC things Token can keep alive are atoms, and 3) the AutoKeepAtoms& // passed to the constructor here represents that collection of atoms // is disabled while atoms in Tokens in this Position are alive. DON'T // ADD NON-ATOM GC THING POINTERS HERE! They would create a rooting // hazard that JS_HAZ_ROOTED will cause to be ignored. template<class AnyCharsAccess> inline TokenStreamPosition(AutoKeepAtoms& keepAtoms, - TokenStreamSpecific<CharT, AnyCharsAccess>& tokenStream); + TokenStreamSpecific<Unit, AnyCharsAccess>& tokenStream); private: TokenStreamPosition(const TokenStreamPosition&) = delete; - // Technically only TokenStreamSpecific<CharT, AnyCharsAccess>::seek with - // CharT constant and AnyCharsAccess varying must be friended, but 1) it's + // Technically only TokenStreamSpecific<Unit, AnyCharsAccess>::seek with + // Unit constant and AnyCharsAccess varying must be friended, but 1) it's // hard to friend one function in template classes, and 2) C++ doesn't // allow partial friend specialization to target just that single class. template<typename Char, class AnyCharsAccess> friend class TokenStreamSpecific; - const CharT* buf; + const Unit* buf; TokenStreamFlags flags; unsigned lineno; size_t linebase; size_t prevLinebase; Token currentToken; unsigned lookahead; Token lookaheadTokens[TokenStreamShared::maxLookahead]; } JS_HAZ_ROOTED; class TokenStreamAnyChars : public TokenStreamShared { public: TokenStreamAnyChars(JSContext* cx, const JS::ReadOnlyCompileOptions& options, StrictModeGetter* smg); - template<typename CharT, class AnyCharsAccess> friend class GeneralTokenStreamChars; - template<typename CharT, class AnyCharsAccess> friend class TokenStreamChars; - template<typename CharT, class AnyCharsAccess> friend class TokenStreamSpecific; - - template<typename CharT> friend class TokenStreamPosition; + template<typename Unit, class AnyCharsAccess> friend class GeneralTokenStreamChars; + template<typename Unit, class AnyCharsAccess> friend class TokenStreamChars; + template<typename Unit, class AnyCharsAccess> friend class TokenStreamSpecific; + + template<typename Unit> friend class TokenStreamPosition; // Accessors. unsigned cursor() const { return cursor_; } unsigned nextCursor() const { return (cursor_ + 1) & ntokensMask; } unsigned aheadCursor(unsigned steps) const { return (cursor_ + steps) & ntokensMask; } const Token& currentToken() const { return tokens[cursor()]; } bool isCurrentTokenType(TokenKind type) const { @@ -957,17 +957,17 @@ CodeUnitValue(char16_t unit) } constexpr uint8_t CodeUnitValue(mozilla::Utf8Unit unit) { return unit.toUint8(); } -template<typename CharT> +template<typename Unit> class TokenStreamCharsBase; template<typename T> inline bool IsLineTerminator(T) = delete; inline bool IsLineTerminator(char32_t codePoint) @@ -980,17 +980,17 @@ IsLineTerminator(char32_t codePoint) inline bool IsLineTerminator(char16_t unit) { // Every LineTerminator fits in char16_t, so this is exact. return IsLineTerminator(static_cast<char32_t>(unit)); } -template<typename CharT> +template<typename Unit> struct SourceUnitTraits; template<> struct SourceUnitTraits<char16_t> { public: static constexpr uint8_t maxUnitsLength = 2; @@ -1022,24 +1022,24 @@ struct SourceUnitTraits<mozilla::Utf8Uni * * If there isn't a valid code point, then |isNone()|. * * But if there *is* a valid code point, then |!isNone()|, the code point has * value |codePoint()| and its length in code units is |lengthInUnits()|. * * Conceptually, this class is |Maybe<struct { char32_t v; uint8_t len; }>|. */ -template<typename CharT> +template<typename Unit> class PeekedCodePoint final { char32_t codePoint_ = 0; uint8_t lengthInUnits_ = 0; private: - using SourceUnitTraits = frontend::SourceUnitTraits<CharT>; + using SourceUnitTraits = frontend::SourceUnitTraits<Unit>; PeekedCodePoint() = default; public: /** * Create a peeked code point with the given value and length in code * units. * @@ -1146,25 +1146,25 @@ IsSingleUnitLineTerminator(mozilla::Utf8 // converting all EOL sequences to '\n', tracking the line number, and setting // |flags.isEOF|. (The "raw" in "raw Unicode code units" refers to the lack of // EOL sequence normalization.) // // buf[0..length-1] often represents a substring of some larger source, // where we have only the substring in memory. The |startOffset| argument // indicates the offset within this larger string at which our string // begins, the offset of |buf[0]|. -template<typename CharT> +template<typename Unit> class SourceUnits { public: - SourceUnits(const CharT* buf, size_t length, size_t startOffset) - : base_(buf), + SourceUnits(const Unit* units, size_t length, size_t startOffset) + : base_(units), startOffset_(startOffset), - limit_(buf + length), - ptr(buf) + limit_(units + length), + ptr(units) { } bool atStart() const { MOZ_ASSERT(ptr, "shouldn't be using if poisoned"); return ptr == base_; } bool atEnd() const { @@ -1180,75 +1180,75 @@ class SourceUnits size_t startOffset() const { return startOffset_; } size_t offset() const { return startOffset_ + mozilla::PointerRangeSize(base_, ptr); } - const CharT* codeUnitPtrAt(size_t offset) const { + const Unit* codeUnitPtrAt(size_t offset) const { MOZ_ASSERT(startOffset_ <= offset); MOZ_ASSERT(offset - startOffset_ <= mozilla::PointerRangeSize(base_, limit_)); return base_ + (offset - startOffset_); } - const CharT* current() const { + const Unit* current() const { return ptr; } - const CharT* limit() const { + const Unit* limit() const { return limit_; } - CharT previousCodeUnit() { + Unit previousCodeUnit() { MOZ_ASSERT(ptr, "can't get previous code unit if poisoned"); MOZ_ASSERT(!atStart(), "must have a previous code unit to get"); return *(ptr - 1); } - CharT getCodeUnit() { + Unit getCodeUnit() { return *ptr++; // this will nullptr-crash if poisoned } - CharT peekCodeUnit() const { + Unit peekCodeUnit() const { return *ptr; // this will nullptr-crash if poisoned } /** * Determine the next code point in source text. The code point is not * normalized: '\r', '\n', '\u2028', and '\u2029' are returned literally. * If there is no next code point because |atEnd()|, or if an encoding * error is encountered, return a |PeekedCodePoint| that |isNone()|. * * This function does not report errors: code that attempts to get the next * code point must report any error. * * If a next code point is found, it may be consumed by passing it to * |consumeKnownCodePoint|. */ - PeekedCodePoint<CharT> peekCodePoint() const { + PeekedCodePoint<Unit> peekCodePoint() const { return PeekCodePoint(ptr, limit_); } private: #ifdef DEBUG - void assertNextCodePoint(const PeekedCodePoint<CharT>& peeked); + void assertNextCodePoint(const PeekedCodePoint<Unit>& peeked); #endif public: /** * Consume a peeked code point that |!isNone()|. * * This call DOES NOT UPDATE LINE-STATUS. You may need to call * |updateLineInfoForEOL()| and |updateFlagsForEOL()| if this consumes a * LineTerminator. Note that if this consumes '\r', you also must consume * an optional '\n' (i.e. a full LineTerminatorSequence) before doing so. */ - void consumeKnownCodePoint(const PeekedCodePoint<CharT>& peeked) { + void consumeKnownCodePoint(const PeekedCodePoint<Unit>& peeked) { MOZ_ASSERT(!peeked.isNone()); MOZ_ASSERT(peeked.lengthInUnits() <= remaining()); #ifdef DEBUG assertNextCodePoint(peeked); #endif ptr += peeked.lengthInUnits(); @@ -1278,20 +1278,20 @@ class SourceUnits } bool matchCodeUnits(const char* chars, uint8_t length) { MOZ_ASSERT(ptr, "shouldn't match into poisoned SourceUnits"); if (length > remaining()) { return false; } - const CharT* start = ptr; - const CharT* end = ptr + length; + const Unit* start = ptr; + const Unit* end = ptr + length; while (ptr < end) { - if (*ptr++ != CharT(*chars++)) { + if (*ptr++ != Unit(*chars++)) { ptr = start; return false; } } return true; } @@ -1305,66 +1305,66 @@ class SourceUnits void unskipCodeUnits(uint32_t n) { MOZ_ASSERT(ptr, "shouldn't use poisoned SourceUnits"); MOZ_ASSERT(n <= mozilla::PointerRangeSize(base_, ptr), "shouldn't unskip beyond start of SourceUnits"); ptr -= n; } private: - friend class TokenStreamCharsBase<CharT>; - - bool internalMatchCodeUnit(CharT c) { + friend class TokenStreamCharsBase<Unit>; + + bool internalMatchCodeUnit(Unit c) { MOZ_ASSERT(ptr, "shouldn't use poisoned SourceUnits"); if (MOZ_LIKELY(!atEnd()) && *ptr == c) { ptr++; return true; } return false; } public: - void consumeKnownCodeUnit(CharT c) { + void consumeKnownCodeUnit(Unit c) { MOZ_ASSERT(ptr, "shouldn't use poisoned SourceUnits"); MOZ_ASSERT(*ptr == c, "consuming the wrong code unit"); ptr++; } /** * Unget the '\n' (CR) that precedes a '\n' (LF), when ungetting a line * terminator that's a full "\r\n" sequence. If the prior code unit isn't * '\r', do nothing. */ void ungetOptionalCRBeforeLF() { MOZ_ASSERT(ptr, "shouldn't unget a '\\r' from poisoned SourceUnits"); - MOZ_ASSERT(*ptr == CharT('\n'), + MOZ_ASSERT(*ptr == Unit('\n'), "function should only be called when a '\\n' was just " "ungotten, and any '\\r' preceding it must also be " "ungotten"); - if (*(ptr - 1) == CharT('\r')) { + if (*(ptr - 1) == Unit('\r')) { ptr--; } } /** Unget U+2028 LINE SEPARATOR or U+2029 PARAGRAPH SEPARATOR. */ inline void ungetLineOrParagraphSeparator(); void ungetCodeUnit() { MOZ_ASSERT(!atStart(), "can't unget if currently at start"); MOZ_ASSERT(ptr); // make sure it hasn't been poisoned ptr--; } - const CharT* addressOfNextCodeUnit(bool allowPoisoned = false) const { + const Unit* addressOfNextCodeUnit(bool allowPoisoned = false) const { MOZ_ASSERT_IF(!allowPoisoned, ptr); // make sure it hasn't been poisoned return ptr; } // Use this with caution! - void setAddressOfNextCodeUnit(const CharT* a, bool allowPoisoned = false) { + void setAddressOfNextCodeUnit(const Unit* a, bool allowPoisoned = false) { MOZ_ASSERT_IF(!allowPoisoned, a); ptr = a; } // Poison the SourceUnits so they can't be accessed again. void poisonInDebug() { #ifdef DEBUG ptr = nullptr; @@ -1418,26 +1418,26 @@ class SourceUnits * text, no further than |WindowRadius| code units away from |offset|, such * that all code units from |offset| to that offset are valid, * non-LineTerminator code points. */ size_t findWindowEnd(size_t offset) const; private: /** Base of buffer. */ - const CharT* base_; + const Unit* base_; /** Offset of base_[0]. */ uint32_t startOffset_; /** Limit for quick bounds check. */ - const CharT* limit_; + const Unit* limit_; /** Next char to get. */ - const CharT* ptr; + const Unit* ptr; }; template<> inline void SourceUnits<char16_t>::ungetLineOrParagraphSeparator() { #ifdef DEBUG char16_t prev = previousCodeUnit(); @@ -1459,17 +1459,17 @@ SourceUnits<mozilla::Utf8Unit>::ungetLin #ifdef DEBUG uint8_t last = ptr[2].toUint8(); #endif MOZ_ASSERT(last == 0xA8 || last == 0xA9); } class TokenStreamCharsShared { - // Using char16_t (not CharT) is a simplifying decision that hopefully + // Using char16_t (not Unit) is a simplifying decision that hopefully // eliminates the need for a UTF-8 regular expression parser and makes // |copyCharBufferTo| markedly simpler. using CharBuffer = Vector<char16_t, 32>; protected: /** * Buffer transiently used to store sequences of identifier or string code * points when such can't be directly processed from the original source @@ -1521,85 +1521,85 @@ ToCharSpan(mozilla::Span<const mozilla:: // // Second, Utf8Unit *contains* a |char|. Examining that memory as |char| // is simply, per C++11 [basic.lval]p10, to access the memory according to // the dynamic type of the object: essentially trivially safe. return mozilla::MakeSpan(reinterpret_cast<const char*>(codeUnits.data()), codeUnits.size()); } -template<typename CharT> +template<typename Unit> class TokenStreamCharsBase : public TokenStreamCharsShared { protected: - TokenStreamCharsBase(JSContext* cx, const CharT* chars, size_t length, size_t startOffset); + TokenStreamCharsBase(JSContext* cx, const Unit* units, size_t length, size_t startOffset); /** * Convert a non-EOF code unit returned by |getCodeUnit()| or - * |peekCodeUnit()| to a CharT code unit. + * |peekCodeUnit()| to a Unit code unit. */ - inline CharT toCharT(int32_t codeUnitValue); + inline Unit toUnit(int32_t codeUnitValue); void ungetCodeUnit(int32_t c) { if (c == EOF) { return; } sourceUnits.ungetCodeUnit(); } static MOZ_ALWAYS_INLINE JSAtom* - atomizeSourceChars(JSContext* cx, mozilla::Span<const CharT> units); - - using SourceUnits = frontend::SourceUnits<CharT>; + atomizeSourceChars(JSContext* cx, mozilla::Span<const Unit> units); + + using SourceUnits = frontend::SourceUnits<Unit>; /** * Try to match a non-LineTerminator ASCII code point. Return true iff it * was matched. */ bool matchCodeUnit(char expect) { MOZ_ASSERT(mozilla::IsAscii(expect)); MOZ_ASSERT(expect != '\r'); MOZ_ASSERT(expect != '\n'); - return this->sourceUnits.internalMatchCodeUnit(CharT(expect)); + return this->sourceUnits.internalMatchCodeUnit(Unit(expect)); } /** * Try to match an ASCII LineTerminator code point. Return true iff it was * matched. */ bool matchLineTerminator(char expect) { MOZ_ASSERT(expect == '\r' || expect == '\n'); - return this->sourceUnits.internalMatchCodeUnit(CharT(expect)); + return this->sourceUnits.internalMatchCodeUnit(Unit(expect)); } template<typename T> bool matchCodeUnit(T) = delete; template<typename T> bool matchLineTerminator(T) = delete; int32_t peekCodeUnit() { return MOZ_LIKELY(!sourceUnits.atEnd()) ? CodeUnitValue(sourceUnits.peekCodeUnit()) : EOF; } /** Consume a known, non-EOF code unit. */ inline void consumeKnownCodeUnit(int32_t unit); // Forbid accidental calls to consumeKnownCodeUnit *not* with the single - // unit-or-EOF type. CharT should use SourceUnits::consumeKnownCodeUnit; - // CodeUnitValue() results should go through toCharT(), or better yet just - // use the original CharT. + // unit-or-EOF type. Unit should use SourceUnits::consumeKnownCodeUnit; + // CodeUnitValue() results should go through toUnit(), or better yet just + // use the original Unit. template<typename T> inline void consumeKnownCodeUnit(T) = delete; /** * Accumulate the provided range of already-validated text (valid UTF-8, or - * anything if CharT is char16_t because JS allows lone surrogates) into + * anything if Unit is char16_t because JS allows lone surrogates) into * |charBuffer|. Normalize '\r', '\n', and "\r\n" into '\n'. */ MOZ_MUST_USE bool - fillCharBufferFromSourceNormalizingAsciiLineBreaks(const CharT* cur, const CharT* end); + fillCharBufferFromSourceNormalizingAsciiLineBreaks(const Unit* cur, const Unit* end); /** * Add a null-terminated line of context to error information, for the line * in |sourceUnits| that contains |offset|. Also record the window's * length and the offset of the error in the window. (Don't bother adding * a line of context if it would be empty.) * * The window will contain no LineTerminators of any kind, and it will not @@ -1613,35 +1613,35 @@ class TokenStreamCharsBase protected: /** Code units in the source code being tokenized. */ SourceUnits sourceUnits; }; template<> inline char16_t -TokenStreamCharsBase<char16_t>::toCharT(int32_t codeUnitValue) +TokenStreamCharsBase<char16_t>::toUnit(int32_t codeUnitValue) { - MOZ_ASSERT(codeUnitValue != EOF, "EOF is not a CharT"); + MOZ_ASSERT(codeUnitValue != EOF, "EOF is not a Unit"); return mozilla::AssertedCast<char16_t>(codeUnitValue); } template<> inline mozilla::Utf8Unit -TokenStreamCharsBase<mozilla::Utf8Unit>::toCharT(int32_t value) +TokenStreamCharsBase<mozilla::Utf8Unit>::toUnit(int32_t value) { - MOZ_ASSERT(value != EOF, "EOF is not a CharT"); - return mozilla::Utf8Unit(static_cast<unsigned char>(value)); + MOZ_ASSERT(value != EOF, "EOF is not a Unit"); + return mozilla::Utf8Unit(mozilla::AssertedCast<unsigned char>(value)); } -template<typename CharT> +template<typename Unit> inline void -TokenStreamCharsBase<CharT>::consumeKnownCodeUnit(int32_t unit) +TokenStreamCharsBase<Unit>::consumeKnownCodeUnit(int32_t unit) { - sourceUnits.consumeKnownCodeUnit(toCharT(unit)); + sourceUnits.consumeKnownCodeUnit(toUnit(unit)); } template<> /* static */ MOZ_ALWAYS_INLINE JSAtom* TokenStreamCharsBase<char16_t>::atomizeSourceChars(JSContext* cx, mozilla::Span<const char16_t> units) { return AtomizeChars(cx, units.data(), units.size()); @@ -1651,17 +1651,17 @@ template<> /* static */ MOZ_ALWAYS_INLINE JSAtom* TokenStreamCharsBase<mozilla::Utf8Unit>::atomizeSourceChars(JSContext* cx, mozilla::Span<const mozilla::Utf8Unit> units) { auto chars = ToCharSpan(units); return AtomizeUTF8Chars(cx, chars.data(), chars.size()); } -template<typename CharT> +template<typename Unit> class SpecializedTokenStreamCharsBase; template<> class SpecializedTokenStreamCharsBase<char16_t> : public TokenStreamCharsBase<char16_t> { using CharsBase = TokenStreamCharsBase<char16_t>; @@ -1693,17 +1693,17 @@ class SpecializedTokenStreamCharsBase<ch } // Otherwise it's a multi-unit code point. return unicode::UTF16Decode(lead, this->sourceUnits.getCodeUnit()); } protected: // These APIs are in both SpecializedTokenStreamCharsBase specializations - // and so are usable in subclasses no matter what CharT is. + // and so are usable in subclasses no matter what Unit is. using CharsBase::CharsBase; }; template<> class SpecializedTokenStreamCharsBase<mozilla::Utf8Unit> : public TokenStreamCharsBase<mozilla::Utf8Unit> { @@ -1794,17 +1794,17 @@ class SpecializedTokenStreamCharsBase<mo /** A sentinel representing the end of |SourceUnits| data. */ class SourceUnitsEnd {}; friend inline size_t operator-(const SourceUnitsEnd& aEnd, const SourceUnitsIterator& aIter); protected: // These APIs are in both SpecializedTokenStreamCharsBase specializations - // and so are usable in subclasses no matter what CharT is. + // and so are usable in subclasses no matter what Unit is. using CharsBase::CharsBase; }; inline size_t operator-(const SpecializedTokenStreamCharsBase<mozilla::Utf8Unit>::SourceUnitsEnd& aEnd, const SpecializedTokenStreamCharsBase<mozilla::Utf8Unit>::SourceUnitsIterator& aIter) { @@ -1827,22 +1827,22 @@ class TokenStart : startOffset_(sourceUnits.offset() + adjust) {} TokenStart(const TokenStart&) = default; uint32_t offset() const { return startOffset_; } }; -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> class GeneralTokenStreamChars - : public SpecializedTokenStreamCharsBase<CharT> + : public SpecializedTokenStreamCharsBase<Unit> { - using CharsBase = TokenStreamCharsBase<CharT>; - using SpecializedCharsBase = SpecializedTokenStreamCharsBase<CharT>; + using CharsBase = TokenStreamCharsBase<Unit>; + using SpecializedCharsBase = SpecializedTokenStreamCharsBase<Unit>; private: Token* newTokenInternal(TokenKind kind, TokenStart start, TokenKind* out); /** * Allocates a new Token from the given offset to the current offset, * ascribes it the given kind, and sets |*out| to that kind. */ @@ -1867,32 +1867,32 @@ class GeneralTokenStreamChars protected: using CharsBase::addLineOfContext; using TokenStreamCharsShared::drainCharBufferIntoAtom; using CharsBase::fillCharBufferFromSourceNormalizingAsciiLineBreaks; using TokenStreamCharsShared::isAsciiCodePoint; using CharsBase::matchLineTerminator; // Deliberately don't |using CharsBase::sourceUnits| because of bug 1472569. :-( - using CharsBase::toCharT; + using CharsBase::toUnit; using typename CharsBase::SourceUnits; protected: using SpecializedCharsBase::SpecializedCharsBase; TokenStreamAnyChars& anyCharsAccess() { return AnyCharsAccess::anyChars(this); } const TokenStreamAnyChars& anyCharsAccess() const { return AnyCharsAccess::anyChars(this); } - using TokenStreamSpecific = frontend::TokenStreamSpecific<CharT, AnyCharsAccess>; + using TokenStreamSpecific = frontend::TokenStreamSpecific<Unit, AnyCharsAccess>; TokenStreamSpecific* asSpecific() { static_assert(mozilla::IsBaseOf<GeneralTokenStreamChars, TokenStreamSpecific>::value, "static_cast below presumes an inheritance relationship"); return static_cast<TokenStreamSpecific*>(this); } @@ -1968,17 +1968,17 @@ class GeneralTokenStreamChars * * If a LineTerminatorSequence was consumed, also update line/column info. * * This may change the current |sourceUnits| offset. */ MOZ_MUST_USE bool getFullAsciiCodePoint(int32_t lead, int32_t* codePoint) { MOZ_ASSERT(isAsciiCodePoint(lead), "non-ASCII code units must be handled separately"); - MOZ_ASSERT(toCharT(lead) == this->sourceUnits.previousCodeUnit(), + MOZ_ASSERT(toUnit(lead) == this->sourceUnits.previousCodeUnit(), "getFullAsciiCodePoint called incorrectly"); if (MOZ_UNLIKELY(lead == '\r')) { matchLineTerminator('\n'); } else if (MOZ_LIKELY(lead != '\n')) { *codePoint = lead; return true; } @@ -2022,18 +2022,18 @@ class GeneralTokenStreamChars } public: JSAtom* getRawTemplateStringAtom() { TokenStreamAnyChars& anyChars = anyCharsAccess(); MOZ_ASSERT(anyChars.currentToken().type == TokenKind::TemplateHead || anyChars.currentToken().type == TokenKind::NoSubsTemplate); - const CharT* cur = this->sourceUnits.codeUnitPtrAt(anyChars.currentToken().pos.begin + 1); - const CharT* end; + const Unit* cur = this->sourceUnits.codeUnitPtrAt(anyChars.currentToken().pos.begin + 1); + const Unit* end; if (anyChars.currentToken().type == TokenKind::TemplateHead) { // Of the form |`...${| or |}...${| end = this->sourceUnits.codeUnitPtrAt(anyChars.currentToken().pos.end - 2); } else { // NO_SUBS_TEMPLATE is of the form |`...`| or |}...`| end = this->sourceUnits.codeUnitPtrAt(anyChars.currentToken().pos.end - 1); } @@ -2043,17 +2043,17 @@ class GeneralTokenStreamChars if (!fillCharBufferFromSourceNormalizingAsciiLineBreaks(cur, end)) { return nullptr; } return drainCharBufferIntoAtom(anyChars.cx); } }; -template<typename CharT, class AnyCharsAccess> class TokenStreamChars; +template<typename Unit, class AnyCharsAccess> class TokenStreamChars; template<class AnyCharsAccess> class TokenStreamChars<char16_t, AnyCharsAccess> : public GeneralTokenStreamChars<char16_t, AnyCharsAccess> { using CharsBase = TokenStreamCharsBase<char16_t>; using SpecializedCharsBase = SpecializedTokenStreamCharsBase<char16_t>; using GeneralCharsBase = GeneralTokenStreamChars<char16_t, AnyCharsAccess>; @@ -2239,17 +2239,17 @@ class TokenStreamChars<mozilla::Utf8Unit * * This function will change the current |sourceUnits| offset. */ MOZ_MUST_USE bool getNonAsciiCodePoint(int32_t lead, int32_t* codePoint); }; // TokenStream is the lexical scanner for JavaScript source text. // -// It takes a buffer of CharT code units (currently only char16_t encoding +// It takes a buffer of Unit code units (currently only char16_t encoding // UTF-16, but we're adding either UTF-8 or Latin-1 single-byte text soon) and // linearly scans it into |Token|s. // // Internally the class uses a four element circular buffer |tokens| of // |Token|s. As an index for |tokens|, the member |cursor_| points to the // current token. Calls to getToken() increase |cursor_| by one and return the // new current token. If a TokenStream was just created, the current token is // uninitialized. It's therefore important that one of the first four member @@ -2278,29 +2278,29 @@ class TokenStreamChars<mozilla::Utf8Unit // this turns out not to be a problem in practice. See the // mozilla.dev.tech.js-engine.internals thread entitled 'Bug in the scanner?' // for more details: // https://groups.google.com/forum/?fromgroups=#!topic/mozilla.dev.tech.js-engine.internals/2JLH5jRcr7E). // // The method seek() allows rescanning from a previously visited location of // the buffer, initially computed by constructing a Position local variable. // -template<typename CharT, class AnyCharsAccess> +template<typename Unit, class AnyCharsAccess> class MOZ_STACK_CLASS TokenStreamSpecific - : public TokenStreamChars<CharT, AnyCharsAccess>, + : public TokenStreamChars<Unit, AnyCharsAccess>, public TokenStreamShared, public ErrorReporter { public: - using CharsBase = TokenStreamCharsBase<CharT>; - using SpecializedCharsBase = SpecializedTokenStreamCharsBase<CharT>; - using GeneralCharsBase = GeneralTokenStreamChars<CharT, AnyCharsAccess>; - using SpecializedChars = TokenStreamChars<CharT, AnyCharsAccess>; - - using Position = TokenStreamPosition<CharT>; + using CharsBase = TokenStreamCharsBase<Unit>; + using SpecializedCharsBase = SpecializedTokenStreamCharsBase<Unit>; + using GeneralCharsBase = GeneralTokenStreamChars<Unit, AnyCharsAccess>; + using SpecializedChars = TokenStreamChars<Unit, AnyCharsAccess>; + + using Position = TokenStreamPosition<Unit>; // Anything inherited through a base class whose type depends upon this // class's template parameters can only be accessed through a dependent // name: prefixed with |this|, by explicit qualification, and so on. (This // is so that references to inherited fields are statically distinguishable // from references to names outside of the class.) This is tedious and // onerous. // @@ -2335,25 +2335,25 @@ class MOZ_STACK_CLASS TokenStreamSpecifi using GeneralCharsBase::matchUnicodeEscapeIdStart; using GeneralCharsBase::newAtomToken; using GeneralCharsBase::newNameToken; using GeneralCharsBase::newNumberToken; using GeneralCharsBase::newRegExpToken; using GeneralCharsBase::newSimpleToken; using CharsBase::peekCodeUnit; // Deliberately don't |using| |sourceUnits| because of bug 1472569. :-( - using CharsBase::toCharT; + using CharsBase::toUnit; using GeneralCharsBase::ungetCodeUnit; using GeneralCharsBase::updateLineInfoForEOL; template<typename CharU> friend class TokenStreamPosition; public: TokenStreamSpecific(JSContext* cx, const JS::ReadOnlyCompileOptions& options, - const CharT* base, size_t length); + const Unit* units, size_t length); /** * Get the next code point, converting LineTerminatorSequences to '\n' and * updating internal line-counter state if needed. Return true on success * and store the code point in |*cp|. Return false and leave |*cp| * undefined on failure. */ MOZ_MUST_USE bool getCodePoint(int32_t* cp); @@ -2452,17 +2452,17 @@ class MOZ_STACK_CLASS TokenStreamSpecifi errorAt(offset, JSMSG_UNICODE_OVERFLOW, "escape sequence"); return; case InvalidEscapeType::Octal: errorAt(offset, JSMSG_DEPRECATED_OCTAL); return; } } - MOZ_MUST_USE bool putIdentInCharBuffer(const CharT* identStart); + MOZ_MUST_USE bool putIdentInCharBuffer(const Unit* identStart); /** * Tokenize a decimal number that begins at |numStart| into the provided * token. * * |unit| must be one of these values: * * 1. The first decimal digit in the integral part of a decimal number @@ -2492,17 +2492,17 @@ class MOZ_STACK_CLASS TokenStreamSpecifi * * In this case, the next |getCodeUnit()| returns the code unit after * |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(int32_t unit, TokenStart start, const CharT* numStart, + MOZ_MUST_USE bool decimalNumber(int32_t unit, TokenStart start, const Unit* 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|. @@ -2655,25 +2655,25 @@ class MOZ_STACK_CLASS TokenStreamSpecifi return true; } MOZ_MUST_USE bool advance(size_t position); void seek(const Position& pos); MOZ_MUST_USE bool seek(const Position& pos, const TokenStreamAnyChars& other); - const CharT* codeUnitPtrAt(size_t offset) const { + const Unit* codeUnitPtrAt(size_t offset) const { return this->sourceUnits.codeUnitPtrAt(offset); } - const CharT* rawLimit() const { + const Unit* rawLimit() const { return this->sourceUnits.limit(); } - MOZ_MUST_USE bool identifierName(TokenStart start, const CharT* identStart, + MOZ_MUST_USE bool identifierName(TokenStart start, const Unit* 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); MOZ_MUST_USE bool getDirectives(bool isMultiline, bool shouldWarnDeprecated); @@ -2682,25 +2682,25 @@ class MOZ_STACK_CLASS TokenStreamSpecifi 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); }; // 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 +// (Unit, 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. -template<typename CharT> +template<typename Unit> template<class AnyCharsAccess> inline -TokenStreamPosition<CharT>::TokenStreamPosition(AutoKeepAtoms& keepAtoms, - TokenStreamSpecific<CharT, AnyCharsAccess>& tokenStream) +TokenStreamPosition<Unit>::TokenStreamPosition(AutoKeepAtoms& keepAtoms, + TokenStreamSpecific<Unit, AnyCharsAccess>& tokenStream) { TokenStreamAnyChars& anyChars = tokenStream.anyCharsAccess(); buf = tokenStream.sourceUnits.addressOfNextCodeUnit(/* allowPoisoned = */ true); flags = anyChars.flags; lineno = anyChars.lineno; linebase = anyChars.linebase; prevLinebase = anyChars.prevLinebase; @@ -2720,23 +2720,23 @@ class TokenStreamAnyCharsAccess template<class TokenStreamSpecific> static inline const TokenStreamAnyChars& anyChars(const TokenStreamSpecific* tss); }; class MOZ_STACK_CLASS TokenStream final : public TokenStreamAnyChars, public TokenStreamSpecific<char16_t, TokenStreamAnyCharsAccess> { - using CharT = char16_t; + using Unit = char16_t; public: TokenStream(JSContext* cx, const JS::ReadOnlyCompileOptions& options, - const CharT* base, size_t length, StrictModeGetter* smg) + const Unit* units, size_t length, StrictModeGetter* smg) : TokenStreamAnyChars(cx, options, smg), - TokenStreamSpecific<CharT, TokenStreamAnyCharsAccess>(cx, options, base, length) + TokenStreamSpecific<Unit, TokenStreamAnyCharsAccess>(cx, options, units, length) {} }; template<class TokenStreamSpecific> /* static */ inline TokenStreamAnyChars& TokenStreamAnyCharsAccess::anyChars(TokenStreamSpecific* tss) { auto* ts = static_cast<TokenStream*>(tss);
--- a/js/src/vm/JSFunction.cpp +++ b/js/src/vm/JSFunction.cpp @@ -1782,36 +1782,36 @@ JSFunction::createScriptForLazilyInterpr } else { MOZ_ASSERT(lazy->scriptSource()->hasSourceText()); // Parse and compile the script from source. UncompressedSourceCache::AutoHoldEntry holder; if (lazy->scriptSource()->hasSourceType<Utf8Unit>()) { // UTF-8 source text. - ScriptSource::PinnedChars<Utf8Unit> chars(cx, lazy->scriptSource(), holder, + ScriptSource::PinnedUnits<Utf8Unit> units(cx, lazy->scriptSource(), holder, lazy->sourceStart(), lazyLength); - if (!chars.get()) { + if (!units.get()) { return false; } // XXX There are no UTF-8 ScriptSources now, so just crash so this // gets filled in later. MOZ_CRASH("UTF-8 lazy function compilation not implemented yet"); } else { MOZ_ASSERT(lazy->scriptSource()->hasSourceType<char16_t>()); // UTF-16 source text. - ScriptSource::PinnedChars<char16_t> chars(cx, lazy->scriptSource(), holder, + ScriptSource::PinnedUnits<char16_t> units(cx, lazy->scriptSource(), holder, lazy->sourceStart(), lazyLength); - if (!chars.get()) { + if (!units.get()) { return false; } - if (!frontend::CompileLazyFunction(cx, lazy, chars.get(), lazyLength)) { + if (!frontend::CompileLazyFunction(cx, lazy, units.get(), lazyLength)) { // The frontend shouldn't fail after linking the function and the // non-lazy script together. MOZ_ASSERT(fun->isInterpretedLazy()); MOZ_ASSERT(fun->lazyScript() == lazy); MOZ_ASSERT(!lazy->hasScript()); return false; } }
--- a/js/src/vm/JSScript.cpp +++ b/js/src/vm/JSScript.cpp @@ -1568,17 +1568,17 @@ JSScript::loadSource(JSContext* cx, Scri return false; } if (!src) { return true; } // XXX On-demand source is currently only UTF-16. Perhaps it should be // changed to UTF-8, or UTF-8 be allowed in addition to UTF-16? - if (!ss->setSource(cx, EntryChars<char16_t>(src), length)) { + if (!ss->setSource(cx, EntryUnits<char16_t>(src), length)) { return false; } *worked = true; return true; } /* static */ JSFlatString* @@ -1605,30 +1605,30 @@ UncompressedSourceCache::holdEntry(AutoH void UncompressedSourceCache::releaseEntry(AutoHoldEntry& holder) { MOZ_ASSERT(holder_ == &holder); holder_ = nullptr; } -template<typename CharT> -const CharT* +template<typename Unit> +const Unit* UncompressedSourceCache::lookup(const ScriptSourceChunk& ssc, AutoHoldEntry& holder) { MOZ_ASSERT(!holder_); - MOZ_ASSERT(ssc.ss->compressedSourceIs<CharT>()); + MOZ_ASSERT(ssc.ss->compressedSourceIs<Unit>()); if (!map_) { return nullptr; } if (Map::Ptr p = map_->lookup(ssc)) { holdEntry(holder, ssc); - return static_cast<const CharT*>(p->value().get()); + return static_cast<const Unit*>(p->value().get()); } return nullptr; } bool UncompressedSourceCache::put(const ScriptSourceChunk& ssc, SourceData data, AutoHoldEntry& holder) { @@ -1674,318 +1674,318 @@ UncompressedSourceCache::sizeOfExcluding n += map_->shallowSizeOfIncludingThis(mallocSizeOf); for (Map::Range r = map_->all(); !r.empty(); r.popFront()) { n += mallocSizeOf(r.front().value().get()); } } return n; } -template<typename CharT> -const CharT* -ScriptSource::chunkChars(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& holder, +template<typename Unit> +const Unit* +ScriptSource::chunkUnits(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& holder, size_t chunk) { - const Compressed<CharT>& c = data.as<Compressed<CharT>>(); + const Compressed<Unit>& c = data.as<Compressed<Unit>>(); ScriptSourceChunk ssc(this, chunk); - if (const CharT* decompressed = cx->caches().uncompressedSourceCache.lookup<CharT>(ssc, holder)) { + if (const Unit* decompressed = cx->caches().uncompressedSourceCache.lookup<Unit>(ssc, holder)) { return decompressed; } - size_t totalLengthInBytes = length() * sizeof(CharT); + size_t totalLengthInBytes = length() * sizeof(Unit); size_t chunkBytes = Compressor::chunkSize(totalLengthInBytes, chunk); - MOZ_ASSERT((chunkBytes % sizeof(CharT)) == 0); - const size_t lengthWithNull = (chunkBytes / sizeof(CharT)) + 1; - EntryChars<CharT> decompressed(js_pod_malloc<CharT>(lengthWithNull)); + MOZ_ASSERT((chunkBytes % sizeof(Unit)) == 0); + const size_t lengthWithNull = (chunkBytes / sizeof(Unit)) + 1; + EntryUnits<Unit> decompressed(js_pod_malloc<Unit>(lengthWithNull)); if (!decompressed) { JS_ReportOutOfMemory(cx); return nullptr; } // Compression treats input and output memory as plain ol' bytes. These // reinterpret_cast<>s accord exactly with that. if (!DecompressStringChunk(reinterpret_cast<const unsigned char*>(c.raw.chars()), chunk, reinterpret_cast<unsigned char*>(decompressed.get()), chunkBytes)) { JS_ReportOutOfMemory(cx); return nullptr; } - decompressed[lengthWithNull - 1] = CharT('\0'); - - const CharT* ret = decompressed.get(); + decompressed[lengthWithNull - 1] = Unit('\0'); + + const Unit* ret = decompressed.get(); if (!cx->caches().uncompressedSourceCache.put(ssc, ToSourceData(std::move(decompressed)), holder)) { JS_ReportOutOfMemory(cx); return nullptr; } return ret; } -template<typename CharT> +template<typename Unit> void ScriptSource::movePendingCompressedSource() { if (pendingCompressed_.empty()) { return; } - Compressed<CharT>& pending = pendingCompressed_.ref<Compressed<CharT>>(); + Compressed<Unit>& pending = pendingCompressed_.ref<Compressed<Unit>>(); MOZ_ASSERT(!hasCompressedSource()); MOZ_ASSERT_IF(hasUncompressedSource(), pending.uncompressedLength == length()); data = SourceType(std::move(pending)); pendingCompressed_.destroy(); } -template<typename CharT> -ScriptSource::PinnedChars<CharT>::~PinnedChars() +template<typename Unit> +ScriptSource::PinnedUnits<Unit>::~PinnedUnits() { - if (chars_) { + if (units_) { MOZ_ASSERT(*stack_ == this); *stack_ = prev_; if (!prev_) { - source_->movePendingCompressedSource<CharT>(); + source_->movePendingCompressedSource<Unit>(); } } } -template<typename CharT> -const CharT* -ScriptSource::chars(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& holder, +template<typename Unit> +const Unit* +ScriptSource::units(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& holder, size_t begin, size_t len) { MOZ_ASSERT(begin <= length()); MOZ_ASSERT(begin + len <= length()); - if (data.is<Uncompressed<CharT>>()) { - const CharT* chars = data.as<Uncompressed<CharT>>().chars(); - if (!chars) { + if (data.is<Uncompressed<Unit>>()) { + const Unit* units = data.as<Uncompressed<Unit>>().units(); + if (!units) { return nullptr; } - return chars + begin; + return units + begin; } if (data.is<Missing>()) { - MOZ_CRASH("ScriptSource::chars() on ScriptSource with SourceType = Missing"); - } - - MOZ_ASSERT(data.is<Compressed<CharT>>()); + MOZ_CRASH("ScriptSource::units() on ScriptSource with SourceType = Missing"); + } + + MOZ_ASSERT(data.is<Compressed<Unit>>()); // Determine which chunk(s) we are interested in, and the offsets within // these chunks. size_t firstChunk, lastChunk; size_t firstChunkOffset, lastChunkOffset; MOZ_ASSERT(len > 0); - Compressor::toChunkOffset(begin * sizeof(CharT), &firstChunk, &firstChunkOffset); - Compressor::toChunkOffset((begin + len - 1) * sizeof(CharT), &lastChunk, &lastChunkOffset); - - MOZ_ASSERT(firstChunkOffset % sizeof(CharT) == 0); - size_t firstChar = firstChunkOffset / sizeof(CharT); + Compressor::toChunkOffset(begin * sizeof(Unit), &firstChunk, &firstChunkOffset); + Compressor::toChunkOffset((begin + len - 1) * sizeof(Unit), &lastChunk, &lastChunkOffset); + + MOZ_ASSERT(firstChunkOffset % sizeof(Unit) == 0); + size_t firstUnit = firstChunkOffset / sizeof(Unit); if (firstChunk == lastChunk) { - const CharT* chars = chunkChars<CharT>(cx, holder, firstChunk); - if (!chars) { + const Unit* units = chunkUnits<Unit>(cx, holder, firstChunk); + if (!units) { return nullptr; } - return chars + firstChar; + return units + firstUnit; } // We need multiple chunks. Allocate a (null-terminated) buffer to hold - // |len| chars and copy uncompressed chars from the chunks into it. We use - // chunkChars() so we benefit from chunk caching by UncompressedSourceCache. + // |len| units and copy uncompressed units from the chunks into it. We use + // chunkUnits() so we benefit from chunk caching by UncompressedSourceCache. MOZ_ASSERT(firstChunk < lastChunk); size_t lengthWithNull = len + 1; - EntryChars<CharT> decompressed(js_pod_malloc<CharT>(lengthWithNull)); + EntryUnits<Unit> decompressed(js_pod_malloc<Unit>(lengthWithNull)); if (!decompressed) { JS_ReportOutOfMemory(cx); return nullptr; } - size_t totalLengthInBytes = length() * sizeof(CharT); - CharT* cursor = decompressed.get(); + size_t totalLengthInBytes = length() * sizeof(Unit); + Unit* cursor = decompressed.get(); for (size_t i = firstChunk; i <= lastChunk; i++) { UncompressedSourceCache::AutoHoldEntry chunkHolder; - const CharT* chars = chunkChars<CharT>(cx, chunkHolder, i); - if (!chars) { + const Unit* units = chunkUnits<Unit>(cx, chunkHolder, i); + if (!units) { return nullptr; } - size_t numChars = Compressor::chunkSize(totalLengthInBytes, i) / sizeof(CharT); + size_t numUnits = Compressor::chunkSize(totalLengthInBytes, i) / sizeof(Unit); if (i == firstChunk) { - MOZ_ASSERT(firstChar < numChars); - chars += firstChar; - numChars -= firstChar; + MOZ_ASSERT(firstUnit < numUnits); + units += firstUnit; + numUnits -= firstUnit; } else if (i == lastChunk) { - size_t numCharsNew = lastChunkOffset / sizeof(CharT) + 1; - MOZ_ASSERT(numCharsNew <= numChars); - numChars = numCharsNew; + size_t numUnitsNew = lastChunkOffset / sizeof(Unit) + 1; + MOZ_ASSERT(numUnitsNew <= numUnits); + numUnits = numUnitsNew; } - mozilla::PodCopy(cursor, chars, numChars); - cursor += numChars; + mozilla::PodCopy(cursor, units, numUnits); + cursor += numUnits; } // XXX Bug 1499192: can we remove the null-termination? It's unclear if // anyone uses chunk implicit null-termination, chunks can contain // nulls anyway, and the extra character risks size-class goofs. - *cursor++ = CharT('\0'); + *cursor++ = Unit('\0'); MOZ_ASSERT(PointerRangeSize(decompressed.get(), cursor) == lengthWithNull); // Transfer ownership to |holder|. - const CharT* ret = decompressed.get(); - holder.holdChars(std::move(decompressed)); + const Unit* ret = decompressed.get(); + holder.holdUnits(std::move(decompressed)); return ret; } -template<typename CharT> -ScriptSource::PinnedChars<CharT>::PinnedChars(JSContext* cx, ScriptSource* source, - UncompressedSourceCache::AutoHoldEntry& holder, - size_t begin, size_t len) - : PinnedCharsBase(source) +template<typename Unit> +ScriptSource::PinnedUnits<Unit>::PinnedUnits(JSContext* cx, ScriptSource* source, + UncompressedSourceCache::AutoHoldEntry& holder, + size_t begin, size_t len) + : PinnedUnitsBase(source) { - MOZ_ASSERT(source->hasSourceType<CharT>(), - "must pin chars of source's type"); - - chars_ = source->chars<CharT>(cx, holder, begin, len); - if (chars_) { - stack_ = &source->pinnedCharsStack_; + MOZ_ASSERT(source->hasSourceType<Unit>(), + "must pin units of source's type"); + + units_ = source->units<Unit>(cx, holder, begin, len); + if (units_) { + stack_ = &source->pinnedUnitsStack_; prev_ = *stack_; *stack_ = this; } } -template class ScriptSource::PinnedChars<Utf8Unit>; -template class ScriptSource::PinnedChars<char16_t>; +template class ScriptSource::PinnedUnits<Utf8Unit>; +template class ScriptSource::PinnedUnits<char16_t>; JSFlatString* ScriptSource::substring(JSContext* cx, size_t start, size_t stop) { MOZ_ASSERT(start <= stop); size_t len = stop - start; UncompressedSourceCache::AutoHoldEntry holder; // UTF-8 source text. if (hasSourceType<Utf8Unit>()) { - PinnedChars<Utf8Unit> chars(cx, this, holder, start, len); - if (!chars.get()) { + PinnedUnits<Utf8Unit> units(cx, this, holder, start, len); + if (!units.asChars()) { return nullptr; } - char* str = SourceTypeTraits<Utf8Unit>::toString(chars.get()); + const char* str = units.asChars(); return NewStringCopyUTF8N<CanGC>(cx, JS::UTF8Chars(str, len)); } // UTF-16 source text. - PinnedChars<char16_t> chars(cx, this, holder, start, len); - if (!chars.get()) { + PinnedUnits<char16_t> units(cx, this, holder, start, len); + if (!units.asChars()) { return nullptr; } - return NewStringCopyN<CanGC>(cx, chars.get(), len); + return NewStringCopyN<CanGC>(cx, units.asChars(), len); } JSFlatString* ScriptSource::substringDontDeflate(JSContext* cx, size_t start, size_t stop) { MOZ_ASSERT(start <= stop); size_t len = stop - start; UncompressedSourceCache::AutoHoldEntry holder; // UTF-8 source text. if (hasSourceType<Utf8Unit>()) { - PinnedChars<Utf8Unit> chars(cx, this, holder, start, len); - if (!chars.get()) { + PinnedUnits<Utf8Unit> units(cx, this, holder, start, len); + if (!units.asChars()) { return nullptr; } - char* str = SourceTypeTraits<Utf8Unit>::toString(chars.get()); + const char* str = units.asChars(); // There doesn't appear to be a non-deflating UTF-8 string creation // function -- but then again, it's not entirely clear how current // callers benefit from non-deflation. return NewStringCopyUTF8N<CanGC>(cx, JS::UTF8Chars(str, len)); } // UTF-16 source text. - PinnedChars<char16_t> chars(cx, this, holder, start, len); - if (!chars.get()) { + PinnedUnits<char16_t> units(cx, this, holder, start, len); + if (!units.asChars()) { return nullptr; } - return NewStringCopyNDontDeflate<CanGC>(cx, chars.get(), len); + return NewStringCopyNDontDeflate<CanGC>(cx, units.asChars(), len); } bool ScriptSource::appendSubstring(JSContext* cx, StringBuffer& buf, size_t start, size_t stop) { MOZ_ASSERT(start <= stop); size_t len = stop - start; UncompressedSourceCache::AutoHoldEntry holder; if (hasSourceType<Utf8Unit>()) { MOZ_CRASH("for now"); return false; } else { - PinnedChars<char16_t> chars(cx, this, holder, start, len); - if (!chars.get()) { + PinnedUnits<char16_t> units(cx, this, holder, start, len); + if (!units.asChars()) { return false; } if (len > SourceDeflateLimit && !buf.ensureTwoByteChars()) { return false; } - return buf.append(chars.get(), len); + return buf.append(units.asChars(), len); } } JSFlatString* ScriptSource::functionBodyString(JSContext* cx) { MOZ_ASSERT(isFunctionBody()); size_t start = parameterListEnd_ + (sizeof(FunctionConstructorMedialSigils) - 1); size_t stop = length() - (sizeof(FunctionConstructorFinalBrace) - 1); return substring(cx, start, stop); } -template<typename CharT> +template<typename Unit> void -ScriptSource::setSource(typename SourceTypeTraits<CharT>::SharedImmutableString uncompressed) +ScriptSource::setSource(typename SourceTypeTraits<Unit>::SharedImmutableString uncompressed) { MOZ_ASSERT(data.is<Missing>()); - data = SourceType(Uncompressed<CharT>(std::move(uncompressed))); + data = SourceType(Uncompressed<Unit>(std::move(uncompressed))); } -template<typename CharT> +template<typename Unit> MOZ_MUST_USE bool -ScriptSource::setSource(JSContext* cx, EntryChars<CharT>&& source, size_t length) +ScriptSource::setSource(JSContext* cx, EntryUnits<Unit>&& source, size_t length) { auto& cache = cx->zone()->runtimeFromAnyThread()->sharedImmutableStrings(); - auto uniqueChars = SourceTypeTraits<CharT>::toCacheable(std::move(source)); + auto uniqueChars = SourceTypeTraits<Unit>::toCacheable(std::move(source)); auto deduped = cache.getOrCreate(std::move(uniqueChars), length); if (!deduped) { ReportOutOfMemory(cx); return false; } - setSource<CharT>(std::move(*deduped)); + setSource<Unit>(std::move(*deduped)); return true; } #if defined(JS_BUILD_BINAST) MOZ_MUST_USE bool ScriptSource::setBinASTSourceCopy(JSContext* cx, const uint8_t* buf, size_t len) { @@ -2066,46 +2066,46 @@ ScriptSource::tryCompressOffThread(JSCon auto task = MakeUnique<SourceCompressionTask>(cx->runtime(), this); if (!task) { ReportOutOfMemory(cx); return false; } return EnqueueOffThreadCompression(cx, std::move(task)); } -template<typename CharT> +template<typename Unit> void ScriptSource::setCompressedSource(SharedImmutableString raw, size_t uncompressedLength) { MOZ_ASSERT(data.is<Missing>() || hasUncompressedSource()); MOZ_ASSERT_IF(hasUncompressedSource(), length() == uncompressedLength); - if (pinnedCharsStack_) { + if (pinnedUnitsStack_) { MOZ_ASSERT(pendingCompressed_.empty()); - pendingCompressed_.construct<Compressed<CharT>>(std::move(raw), uncompressedLength); + pendingCompressed_.construct<Compressed<Unit>>(std::move(raw), uncompressedLength); } else { - data = SourceType(Compressed<CharT>(std::move(raw), uncompressedLength)); + data = SourceType(Compressed<Unit>(std::move(raw), uncompressedLength)); } } -template<typename CharT> +template<typename Unit> MOZ_MUST_USE bool ScriptSource::setCompressedSource(JSContext* cx, UniqueChars&& compressed, size_t rawLength, size_t sourceLength) { MOZ_ASSERT(compressed); auto& cache = cx->zone()->runtimeFromAnyThread()->sharedImmutableStrings(); auto deduped = cache.getOrCreate(std::move(compressed), rawLength); if (!deduped) { ReportOutOfMemory(cx); return false; } - setCompressedSource<CharT>(std::move(*deduped), sourceLength); + setCompressedSource<Unit>(std::move(*deduped), sourceLength); return true; } bool ScriptSource::setSourceCopy(JSContext* cx, SourceBufferHolder& srcBuf) { MOZ_ASSERT(!hasSourceText()); @@ -2146,33 +2146,33 @@ reallocUniquePtr(UniqueChars& unique, si } // Since the realloc succeeded, unique is now holding a freed pointer. mozilla::Unused << unique.release(); unique.reset(newPtr); return true; } -template<typename CharT> +template<typename Unit> void SourceCompressionTask::workEncodingSpecific() { ScriptSource* source = sourceHolder_.get(); - MOZ_ASSERT(source->data.is<ScriptSource::Uncompressed<CharT>>()); + MOZ_ASSERT(source->data.is<ScriptSource::Uncompressed<Unit>>()); // Try to keep the maximum memory usage down by only allocating half the // size of the string, first. - size_t inputBytes = source->length() * sizeof(CharT); + size_t inputBytes = source->length() * sizeof(Unit); size_t firstSize = inputBytes / 2; UniqueChars compressed(js_pod_malloc<char>(firstSize)); if (!compressed) { return; } - const CharT* chars = source->data.as<ScriptSource::Uncompressed<CharT>>().chars(); + const Unit* chars = source->data.as<ScriptSource::Uncompressed<Unit>>().units(); Compressor comp(reinterpret_cast<const unsigned char*>(chars), inputBytes); if (!comp.init()) { return; } comp.setOutput(reinterpret_cast<unsigned char*>(compressed.get()), firstSize); bool cont = true; bool reallocated = false; @@ -2228,19 +2228,19 @@ SourceCompressionTask::workEncodingSpeci struct SourceCompressionTask::PerformTaskWork { SourceCompressionTask* const task_; explicit PerformTaskWork(SourceCompressionTask* task) : task_(task) {} - template<typename CharT> - void match(const ScriptSource::Uncompressed<CharT>&) { - task_->workEncodingSpecific<CharT>(); + template<typename Unit> + void match(const ScriptSource::Uncompressed<Unit>&) { + task_->workEncodingSpecific<Unit>(); } template<typename T> void match (const T&) { MOZ_CRASH("why are we compressing missing, already-compressed, or " "BinAST source?"); } }; @@ -2360,41 +2360,41 @@ ScriptSource::xdrFinalizeEncoder(JS::Tra auto cleanup = mozilla::MakeScopeExit([&] { xdrEncoder_.reset(nullptr); }); XDRResult res = xdrEncoder_->linearize(buffer); return res.isOk(); } -template<typename CharT> +template<typename Unit> struct SourceDecoder { XDRState<XDR_DECODE>* const xdr_; ScriptSource* const scriptSource_; const uint32_t uncompressedLength_; public: SourceDecoder(XDRState<XDR_DECODE>* xdr, ScriptSource* scriptSource, uint32_t uncompressedLength) : xdr_(xdr), scriptSource_(scriptSource), uncompressedLength_(uncompressedLength) {} XDRResult decode() { - auto sourceChars = - xdr_->cx()->make_pod_array<CharT>(Max<size_t>(uncompressedLength_, 1)); - if (!sourceChars) { + auto sourceUnits = + xdr_->cx()->make_pod_array<Unit>(Max<size_t>(uncompressedLength_, 1)); + if (!sourceUnits) { return xdr_->fail(JS::TranscodeResult_Throw); } - MOZ_TRY(xdr_->codeChars(sourceChars.get(), uncompressedLength_)); - - if (!scriptSource_->setSource(xdr_->cx(), std::move(sourceChars), + MOZ_TRY(xdr_->codeChars(sourceUnits.get(), uncompressedLength_)); + + if (!scriptSource_->setSource(xdr_->cx(), std::move(sourceUnits), uncompressedLength_)) { return xdr_->fail(JS::TranscodeResult_Throw); } return Ok(); } }; @@ -2415,33 +2415,33 @@ ScriptSource::xdrUncompressedSource<XDR_ } SourceDecoder<char16_t> decoder(xdr, this, uncompressedLength); return decoder.decode(); } } // namespace js -template<typename CharT> +template<typename Unit> struct SourceEncoder { XDRState<XDR_ENCODE>* const xdr_; ScriptSource* const source_; const uint32_t uncompressedLength_; SourceEncoder(XDRState<XDR_ENCODE>* xdr, ScriptSource* source, uint32_t uncompressedLength) : xdr_(xdr), source_(source), uncompressedLength_(uncompressedLength) {} XDRResult encode() { - CharT* sourceChars = const_cast<CharT*>(source_->uncompressedData<CharT>()); - - return xdr_->codeChars(sourceChars, uncompressedLength_); + Unit* sourceUnits = const_cast<Unit*>(source_->uncompressedData<Unit>()); + + return xdr_->codeChars(sourceUnits, uncompressedLength_); } }; namespace js { template<> XDRResult ScriptSource::xdrUncompressedSource<XDR_ENCODE>(XDRState<XDR_ENCODE>* xdr, @@ -2687,30 +2687,30 @@ ScriptSource::performXDR(XDRState<mode>* if (mode == XDR_DECODE && hasSourceText() && mozilla::recordreplay::IsRecordingOrReplaying()) { UncompressedSourceCache::AutoHoldEntry holder; if (hasSourceType<Utf8Unit>()) { // UTF-8 source text. - ScriptSource::PinnedChars<Utf8Unit> chars(xdr->cx(), this, holder, 0, length()); - if (!chars.get()) { + ScriptSource::PinnedUnits<Utf8Unit> units(xdr->cx(), this, holder, 0, length()); + if (!units.get()) { return xdr->fail(JS::TranscodeResult_Throw); } mozilla::recordreplay::NoteContentParse8(this, filename(), "application/javascript", - chars.get(), length()); + units.get(), length()); } else { // UTF-16 source text. - ScriptSource::PinnedChars<char16_t> chars(xdr->cx(), this, holder, 0, length()); - if (!chars.get()) { + ScriptSource::PinnedUnits<char16_t> units(xdr->cx(), this, holder, 0, length()); + if (!units.get()) { return xdr->fail(JS::TranscodeResult_Throw); } mozilla::recordreplay::NoteContentParse16(this, filename(), "application/javascript", - chars.get(), length()); + units.get(), length()); } } } return Ok(); } // Format and return a cx->pod_malloc'ed URL for a generated script like:
--- a/js/src/vm/JSScript.h +++ b/js/src/vm/JSScript.h @@ -327,32 +327,32 @@ struct ScriptSourceChunkHasher static HashNumber hash(const ScriptSourceChunk& ssc) { return mozilla::AddToHash(DefaultHasher<ScriptSource*>::hash(ssc.ss), ssc.chunk); } static bool match(const ScriptSourceChunk& c1, const ScriptSourceChunk& c2) { return c1 == c2; } }; -template<typename CharT> -using EntryChars = mozilla::UniquePtr<CharT[], JS::FreePolicy>; +template<typename Unit> +using EntryUnits = mozilla::UniquePtr<Unit[], JS::FreePolicy>; // The uncompressed source cache contains *either* UTF-8 source data *or* // UTF-16 source data. ScriptSourceChunk implies a ScriptSource that // contains either UTF-8 data or UTF-16 data, so the nature of the key to // Map below indicates how each SourceData ought to be interpreted. using SourceData = mozilla::UniquePtr<void, JS::FreePolicy>; -template<typename CharT> +template<typename Unit> inline SourceData -ToSourceData(EntryChars<CharT> chars) +ToSourceData(EntryUnits<Unit> chars) { static_assert(std::is_same<SourceData::DeleterType, - typename EntryChars<CharT>::DeleterType>::value, - "EntryChars and SourceData must share the same deleter " + typename EntryUnits<Unit>::DeleterType>::value, + "EntryUnits and SourceData must share the same deleter " "type, that need not know the type of the data being freed, " "for the upcast below to be safe"); return SourceData(chars.release()); } class UncompressedSourceCache { using Map = HashMap<ScriptSourceChunk, @@ -373,23 +373,23 @@ class UncompressedSourceCache ~AutoHoldEntry() { if (cache_) { MOZ_ASSERT(sourceChunk_.valid()); cache_->releaseEntry(*this); } } - template<typename CharT> - void holdChars(EntryChars<CharT> chars) { + template<typename Unit> + void holdUnits(EntryUnits<Unit> units) { MOZ_ASSERT(!cache_); MOZ_ASSERT(!sourceChunk_.valid()); MOZ_ASSERT(!data_); - data_ = ToSourceData(std::move(chars)); + data_ = ToSourceData(std::move(units)); } private: void holdEntry(UncompressedSourceCache* cache, const ScriptSourceChunk& sourceChunk) { // Initialise the holder for a specific cache and script source. // This will hold on to the cached source chars in the event that // the cache is purged. MOZ_ASSERT(!cache_); @@ -420,148 +420,154 @@ class UncompressedSourceCache private: UniquePtr<Map> map_ = nullptr; AutoHoldEntry* holder_ = nullptr; public: UncompressedSourceCache() = default; - template<typename CharT> - const CharT* lookup(const ScriptSourceChunk& ssc, AutoHoldEntry& asp); + template<typename Unit> + const Unit* lookup(const ScriptSourceChunk& ssc, AutoHoldEntry& asp); bool put(const ScriptSourceChunk& ssc, SourceData data, AutoHoldEntry& asp); void purge(); size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf); private: void holdEntry(AutoHoldEntry& holder, const ScriptSourceChunk& ssc); void releaseEntry(AutoHoldEntry& holder); }; -template<typename CharT> +template<typename Unit> struct SourceTypeTraits; template<> struct SourceTypeTraits<mozilla::Utf8Unit> { + using CharT = char; using SharedImmutableString = js::SharedImmutableString; - static const mozilla::Utf8Unit* chars(const SharedImmutableString& string) { + static const mozilla::Utf8Unit* units(const SharedImmutableString& string) { // Casting |char| data to |Utf8Unit| is safe because |Utf8Unit| // contains a |char|. See the long comment in |Utf8Unit|'s definition. return reinterpret_cast<const mozilla::Utf8Unit*>(string.chars()); } static char* toString(const mozilla::Utf8Unit* units) { auto asUnsigned = const_cast<unsigned char*>(mozilla::Utf8AsUnsignedChars(units)); return reinterpret_cast<char*>(asUnsigned); } - static UniqueChars toCacheable(EntryChars<mozilla::Utf8Unit> str) { + static UniqueChars toCacheable(EntryUnits<mozilla::Utf8Unit> str) { // The cache only stores strings of |char| or |char16_t|, and right now // it seems best not to gunk up the cache with |Utf8Unit| too. So // cache |Utf8Unit| strings by interpreting them as |char| strings. char* chars = toString(str.release()); return UniqueChars(chars); } }; template<> struct SourceTypeTraits<char16_t> { + using CharT = char16_t; using SharedImmutableString = js::SharedImmutableTwoByteString; - static const char16_t* chars(const SharedImmutableString& string) { + static const char16_t* units(const SharedImmutableString& string) { return string.chars(); } - static char16_t* toString(char16_t* units) { - return units; + static char16_t* toString(const char16_t* units) { + return const_cast<char16_t*>(units); } - static UniqueTwoByteChars toCacheable(EntryChars<char16_t> str) { + static UniqueTwoByteChars toCacheable(EntryUnits<char16_t> str) { return UniqueTwoByteChars(std::move(str)); } }; class ScriptSource { friend class SourceCompressionTask; - class PinnedCharsBase + class PinnedUnitsBase { protected: - PinnedCharsBase** stack_ = nullptr; - PinnedCharsBase* prev_ = nullptr; + PinnedUnitsBase** stack_ = nullptr; + PinnedUnitsBase* prev_ = nullptr; ScriptSource* source_; - explicit PinnedCharsBase(ScriptSource* source) + explicit PinnedUnitsBase(ScriptSource* source) : source_(source) {} }; public: // Any users that wish to manipulate the char buffer of the ScriptSource - // needs to do so via PinnedChars for GC safety. A GC may compress + // needs to do so via PinnedUnits for GC safety. A GC may compress // ScriptSources. If the source were initially uncompressed, then any raw // pointers to the char buffer would now point to the freed, uncompressed // chars. This is analogous to Rooted. - template<typename CharT> - class PinnedChars : public PinnedCharsBase + template<typename Unit> + class PinnedUnits : public PinnedUnitsBase { - const CharT* chars_; + const Unit* units_; public: - PinnedChars(JSContext* cx, ScriptSource* source, + PinnedUnits(JSContext* cx, ScriptSource* source, UncompressedSourceCache::AutoHoldEntry& holder, size_t begin, size_t len); - ~PinnedChars(); - - const CharT* get() const { - return chars_; + ~PinnedUnits(); + + const Unit* get() const { + return units_; + } + + const typename SourceTypeTraits<Unit>::CharT* asChars() const { + return SourceTypeTraits<Unit>::toString(get()); } }; private: mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire, mozilla::recordreplay::Behavior::DontPreserve> refs; // Note: while ScriptSources may be compressed off thread, they are only // modified by the main thread, and all members are always safe to access // on the main thread. // Indicate which field in the |data| union is active. struct Missing { }; - template<typename CharT> + template<typename Unit> class Uncompressed { - typename SourceTypeTraits<CharT>::SharedImmutableString string_; + typename SourceTypeTraits<Unit>::SharedImmutableString string_; public: - explicit Uncompressed(typename SourceTypeTraits<CharT>::SharedImmutableString str) + explicit Uncompressed(typename SourceTypeTraits<Unit>::SharedImmutableString str) : string_(std::move(str)) {} - const CharT* chars() const { - return SourceTypeTraits<CharT>::chars(string_); + const Unit* units() const { + return SourceTypeTraits<Unit>::units(string_); } size_t length() const { return string_.length(); } }; - template<typename CharT> + template<typename Unit> struct Compressed { // Single-byte compressed text, regardless whether the original text // was single-byte or two-byte. SharedImmutableString raw; size_t uncompressedLength; Compressed(SharedImmutableString raw, size_t uncompressedLength) @@ -580,20 +586,20 @@ class ScriptSource using SourceType = mozilla::Variant<Compressed<mozilla::Utf8Unit>, Uncompressed<mozilla::Utf8Unit>, Compressed<char16_t>, Uncompressed<char16_t>, Missing, BinAST>; SourceType data; - // If the GC attempts to call setCompressedSource with PinnedChars - // present, the first PinnedChars (that is, bottom of the stack) will set + // If the GC attempts to call setCompressedSource with PinnedUnits + // present, the first PinnedUnits (that is, bottom of the stack) will set // the compressed chars upon destruction. - PinnedCharsBase* pinnedCharsStack_; + PinnedUnitsBase* pinnedUnitsStack_; mozilla::MaybeOneOf<Compressed<mozilla::Utf8Unit>, Compressed<char16_t>> pendingCompressed_; // The filename of this script. UniqueChars filename_; UniqueTwoByteChars displayURL_; UniqueTwoByteChars sourceMapURL_; bool mutedErrors_; @@ -650,41 +656,41 @@ class ScriptSource // demand. If sourceRetrievable_ and hasSourceText() are false, it is not // possible to get source at all. bool sourceRetrievable_:1; bool hasIntroductionOffset_:1; bool containsAsmJS_:1; UniquePtr<frontend::BinASTSourceMetadata> binASTMetadata_; - template<typename CharT> - const CharT* chunkChars(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& holder, - size_t chunk); + template<typename Unit> + const Unit* chunkUnits(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& holder, + size_t chunk); // Return a string containing the chars starting at |begin| and ending at // |begin + len|. // // Warning: this is *not* GC-safe! Any chars to be handed out should use - // PinnedChars. See comment below. - template<typename CharT> - const CharT* chars(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& asp, - size_t begin, size_t len); - - template<typename CharT> + // PinnedUnits. See comment below. + template<typename Unit> + const Unit* units(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& asp, + size_t begin, size_t len); + + template<typename Unit> void movePendingCompressedSource(); public: // When creating a JSString* from TwoByte source characters, we don't try to // to deflate to Latin1 for longer strings, because this can be slow. static const size_t SourceDeflateLimit = 100; explicit ScriptSource() : refs(0), data(SourceType(Missing())), - pinnedCharsStack_(nullptr), + pinnedUnitsStack_(nullptr), filename_(nullptr), displayURL_(nullptr), sourceMapURL_(nullptr), mutedErrors_(false), introductionOffset_(0), parameterListEnd_(0), introducerFilename_(nullptr), introductionType_(nullptr), @@ -722,53 +728,53 @@ class ScriptSource frontend::BinASTSourceMetadata* binASTSourceMetadata() const { MOZ_ASSERT(hasBinASTSource()); return binASTMetadata_.get(); } private: struct UncompressedDataMatcher { - template<typename CharT> - const void* match(const Uncompressed<CharT>& u) { - return u.chars(); + template<typename Unit> + const void* match(const Uncompressed<Unit>& u) { + return u.units(); } template<typename T> const void* match(const T&) { MOZ_CRASH("attempting to access uncompressed data in a " "ScriptSource not containing it"); return nullptr; } }; public: - template<typename CharT> - const CharT* uncompressedData() { - return static_cast<const CharT*>(data.match(UncompressedDataMatcher())); + template<typename Unit> + const Unit* uncompressedData() { + return static_cast<const Unit*>(data.match(UncompressedDataMatcher())); } private: struct CompressedDataMatcher { - template<typename CharT> - char* match(const Compressed<CharT>& c) { + template<typename Unit> + char* match(const Compressed<Unit>& c) { return const_cast<char*>(c.raw.chars()); } template<typename T> char* match(const T&) { MOZ_CRASH("attempting to access compressed data in a ScriptSource " "not containing it"); return nullptr; } }; public: - template<typename CharT> + template<typename Unit> char* compressedData() { return data.match(CompressedDataMatcher()); } private: struct BinASTDataMatcher { void* match(const BinAST& b) { @@ -789,103 +795,103 @@ class ScriptSource public: void* binASTData() { return data.match(BinASTDataMatcher()); } private: struct HasUncompressedSource { - template<typename CharT> - bool match(const Uncompressed<CharT>&) { return true; } - - template<typename CharT> - bool match(const Compressed<CharT>&) { return false; } + template<typename Unit> + bool match(const Uncompressed<Unit>&) { return true; } + + template<typename Unit> + bool match(const Compressed<Unit>&) { return false; } bool match(const BinAST&) { return false; } bool match(const Missing&) { return false; } }; public: bool hasUncompressedSource() const { return data.match(HasUncompressedSource()); } - template<typename CharT> + template<typename Unit> bool uncompressedSourceIs() const { MOZ_ASSERT(hasUncompressedSource()); - return data.is<Uncompressed<CharT>>(); + return data.is<Uncompressed<Unit>>(); } private: struct HasCompressedSource { - template<typename CharT> - bool match(const Compressed<CharT>&) { return true; } - - template<typename CharT> - bool match(const Uncompressed<CharT>&) { return false; } + template<typename Unit> + bool match(const Compressed<Unit>&) { return true; } + + template<typename Unit> + bool match(const Uncompressed<Unit>&) { return false; } bool match(const BinAST&) { return false; } bool match(const Missing&) { return false; } }; public: bool hasCompressedSource() const { return data.match(HasCompressedSource()); } - template<typename CharT> + template<typename Unit> bool compressedSourceIs() const { MOZ_ASSERT(hasCompressedSource()); - return data.is<Compressed<CharT>>(); + return data.is<Compressed<Unit>>(); } private: - template<typename CharT> + template<typename Unit> struct SourceTypeMatcher { template<template<typename C> class Data> - bool match(const Data<CharT>&) { + bool match(const Data<Unit>&) { return true; } - template<template<typename C> class Data, typename NotCharT> - bool match(const Data<NotCharT>&) { + template<template<typename C> class Data, typename NotUnit> + bool match(const Data<NotUnit>&) { return false; } bool match(const BinAST&) { MOZ_CRASH("doesn't make sense to ask source type of BinAST data"); return false; } bool match(const Missing&) { MOZ_CRASH("doesn't make sense to ask source type when missing"); return false; } }; public: - template<typename CharT> + template<typename Unit> bool hasSourceType() const { - return data.match(SourceTypeMatcher<CharT>()); + return data.match(SourceTypeMatcher<Unit>()); } private: struct SourceCharSizeMatcher { - template<template<typename C> class Data, typename CharT> - uint8_t match(const Data<CharT>& data) { - static_assert(std::is_same<CharT, mozilla::Utf8Unit>::value || - std::is_same<CharT, char16_t>::value, + template<template<typename C> class Data, typename Unit> + uint8_t match(const Data<Unit>& data) { + static_assert(std::is_same<Unit, mozilla::Utf8Unit>::value || + std::is_same<Unit, char16_t>::value, "should only have UTF-8 or UTF-16 source char"); - return sizeof(CharT); + return sizeof(Unit); } uint8_t match(const BinAST&) { MOZ_CRASH("BinAST source has no source-char size"); return 0; } uint8_t match(const Missing&) { @@ -897,23 +903,23 @@ class ScriptSource public: uint8_t sourceCharSize() const { return data.match(SourceCharSizeMatcher()); } private: struct UncompressedLengthMatcher { - template<typename CharT> - size_t match(const Uncompressed<CharT>& u) { + template<typename Unit> + size_t match(const Uncompressed<Unit>& u) { return u.length(); } - template<typename CharT> - size_t match(const Compressed<CharT>& u) { + template<typename Unit> + size_t match(const Compressed<Unit>& u) { return u.uncompressedLength; } size_t match(const BinAST& b) { return b.string.length(); } size_t match(const Missing& m) { @@ -926,23 +932,23 @@ class ScriptSource size_t length() const { MOZ_ASSERT(hasSourceText() || hasBinASTSource()); return data.match(UncompressedLengthMatcher()); } private: struct CompressedLengthOrZeroMatcher { - template<typename CharT> - size_t match(const Uncompressed<CharT>&) { + template<typename Unit> + size_t match(const Uncompressed<Unit>&) { return 0; } - template<typename CharT> - size_t match(const Compressed<CharT>& c) { + template<typename Unit> + size_t match(const Compressed<Unit>& c) { return c.raw.length(); } size_t match(const BinAST&) { MOZ_CRASH("trying to get compressed length for BinAST data"); return 0; } @@ -965,32 +971,32 @@ class ScriptSource bool isFunctionBody() { return parameterListEnd_ != 0; } JSFlatString* functionBodyString(JSContext* cx); void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ScriptSourceInfo* info) const; - template<typename CharT> + template<typename Unit> MOZ_MUST_USE bool setSource(JSContext* cx, - EntryChars<CharT>&& source, + EntryUnits<Unit>&& source, size_t length); - template<typename CharT> - void setSource(typename SourceTypeTraits<CharT>::SharedImmutableString uncompressed); + template<typename Unit> + void setSource(typename SourceTypeTraits<Unit>::SharedImmutableString uncompressed); MOZ_MUST_USE bool tryCompressOffThread(JSContext* cx); - // The CharT parameter determines which type of compressed source is + // The Unit parameter determines which type of compressed source is // recorded, but raw compressed source is always single-byte. - template<typename CharT> + template<typename Unit> void setCompressedSource(SharedImmutableString compressed, size_t sourceLength); - template<typename CharT> + template<typename Unit> MOZ_MUST_USE bool setCompressedSource(JSContext* cx, UniqueChars&& raw, size_t rawLength, size_t sourceLength); #if defined(JS_BUILD_BINAST) /* * Do not take ownership of the given `buf`. Store the canonical, shared * and de-duplicated version. If there is no extant shared version of @@ -1016,23 +1022,23 @@ class ScriptSource ScriptSource* const source_; SharedImmutableString& compressed_; SetCompressedSourceFromTask(ScriptSource* source, SharedImmutableString& compressed) : source_(source), compressed_(compressed) {} - template<typename CharT> - void match(const Uncompressed<CharT>&) { - source_->setCompressedSource<CharT>(std::move(compressed_), source_->length()); + template<typename Unit> + void match(const Uncompressed<Unit>&) { + source_->setCompressedSource<Unit>(std::move(compressed_), source_->length()); } - template<typename CharT> - void match(const Compressed<CharT>&) { + template<typename Unit> + void match(const Compressed<Unit>&) { MOZ_CRASH("can't set compressed source when source is already " "compressed -- ScriptSource::tryCompressOffThread " "shouldn't have queued up this task?"); } void match(const BinAST&) { MOZ_CRASH("doesn't make sense to set compressed source for BinAST " "data"); @@ -1048,21 +1054,21 @@ class ScriptSource void setCompressedSourceFromTask(SharedImmutableString compressed); public: // XDR handling template <XDRMode mode> MOZ_MUST_USE XDRResult performXDR(XDRState<mode>* xdr); private: - // It'd be better to make this function take <XDRMode, CharT>, as both - // specializations of this function contain nested CharT-parametrized + // It'd be better to make this function take <XDRMode, Unit>, as both + // specializations of this function contain nested Unit-parametrized // helper classes that do everything the function needs to do. But then // we'd need template function partial specialization to hold XDRMode - // constant while varying CharT, so that idea's no dice. + // constant while varying Unit, so that idea's no dice. template <XDRMode mode> MOZ_MUST_USE XDRResult xdrUncompressedSource(XDRState<mode>* xdr, uint8_t sourceCharSize, uint32_t uncompressedLength); public: MOZ_MUST_USE bool setFilename(JSContext* cx, const char* filename); const char* introducerFilename() const { return introducerFilename_ ? introducerFilename_.get() : filename_.get();
--- a/modules/libpref/init/StaticPrefList.h +++ b/modules/libpref/init/StaticPrefList.h @@ -218,17 +218,17 @@ VARCACHE_PREF( ) // If true. then the service worker interception and the ServiceWorkerManager // will live in the parent process. This only takes effect on browser start. // Note, this is not currently safe to use for normal browsing yet. PREF("dom.serviceWorkers.parent_intercept", bool, false) // Enable PaymentRequest API -#ifdef NIGHTLY_BUILD +#if defined(NIGHTLY_BUILD) && (defined(XP_WIN) || defined(XP_MACOSX)) # define PREF_VALUE true #else # define PREF_VALUE false #endif VARCACHE_PREF( "dom.payments.request.enabled", dom_payments_request_enabled, bool, PREF_VALUE
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -5842,18 +5842,17 @@ pref("dom.IntersectionObserver.enabled", // Whether module scripts (<script type="module">) are enabled for content. pref("dom.moduleScripts.enabled", true); // Maximum amount of time in milliseconds consecutive setTimeout()/setInterval() // callback are allowed to run before yielding the event loop. pref("dom.timeout.max_consecutive_callbacks_ms", 4); -// Use this preference to house "Payment Request API" during development -pref("dom.payments.request.enabled", false); +// Payment Request API preferences pref("dom.payments.loglevel", "Warn"); pref("dom.payments.defaults.saveCreditCard", false); pref("dom.payments.defaults.saveAddress", true); #ifdef MOZ_ASAN_REPORTER pref("asanreporter.apiurl", "https://anf1.fuzzing.mozilla.org/crashproxy/submit/"); pref("asanreporter.clientid", "unknown"); pref("toolkit.telemetry.overrideUpdateChannel", "nightly-asan");
--- a/security/nss/automation/taskcluster/graph/src/extend.js +++ b/security/nss/automation/taskcluster/graph/src/extend.js @@ -147,23 +147,23 @@ queue.map(task => { }); /*****************************************************************************/ export default async function main() { await scheduleLinux("Linux 32 (opt)", { platform: "linux32", image: LINUX_IMAGE - }, "-m32 --opt"); + }, "-t ia32 --opt"); await scheduleLinux("Linux 32 (debug)", { platform: "linux32", collection: "debug", image: LINUX_IMAGE - }, "-m32"); + }, "-t ia32"); await scheduleLinux("Linux 64 (opt)", { platform: "linux64", image: LINUX_IMAGE }, "--opt"); await scheduleLinux("Linux 64 (debug)", { platform: "linux64", @@ -243,22 +243,22 @@ export default async function main() { await scheduleWindows("Windows 2012 64 (debug)", { platform: "windows2012-64", collection: "debug" }, "build_gyp.sh"); await scheduleWindows("Windows 2012 32 (opt)", { platform: "windows2012-32", - }, "build_gyp.sh --opt -m32"); + }, "build_gyp.sh --opt -t ia32"); await scheduleWindows("Windows 2012 32 (debug)", { platform: "windows2012-32", collection: "debug" - }, "build_gyp.sh -m32"); + }, "build_gyp.sh -t ia32"); await scheduleFuzzing(); await scheduleFuzzing32(); await scheduleTools(); let aarch64_base = { image: "franziskus/nss-aarch64-ci", @@ -674,17 +674,17 @@ async function scheduleFuzzing32() { }; // Build base definition. let build_base = merge(base, { command: [ "/bin/bash", "-c", "bin/checkout.sh && " + - "nss/automation/taskcluster/scripts/build_gyp.sh -g -v --fuzz -m32" + "nss/automation/taskcluster/scripts/build_gyp.sh -g -v --fuzz -t ia32" ], artifacts: { public: { expires: 24 * 7, type: "directory", path: "/home/worker/artifacts" } }, @@ -701,17 +701,17 @@ async function scheduleFuzzing32() { let task_build_tls = queue.scheduleTask(merge(build_base, { name: "Linux 32 (debug, TLS fuzz)", symbol: "B", group: "TLS", command: [ "/bin/bash", "-c", "bin/checkout.sh && " + - "nss/automation/taskcluster/scripts/build_gyp.sh -g -v --fuzz=tls -m32" + "nss/automation/taskcluster/scripts/build_gyp.sh -g -v --fuzz=tls -t ia32" ], })); // Schedule tests. queue.scheduleTask(merge(base, { parent: task_build_tls, name: "Gtests", command: [ @@ -1100,17 +1100,17 @@ async function scheduleTools() { expires: 24 * 7, type: "directory", path: "/home/worker/artifacts" } }, command: [ "/bin/bash", "-c", - "bin/checkout.sh && nss/automation/taskcluster/scripts/build_gyp.sh --disable-tests --emit-llvm -m32" + "bin/checkout.sh && nss/automation/taskcluster/scripts/build_gyp.sh --disable-tests --emit-llvm -t ia32" ] })); queue.scheduleTask(merge(base, { parent: task_saw, symbol: "bmul", group: "SAW", name: "bmul.saw",
--- a/security/nss/automation/taskcluster/windows/build.sh +++ b/security/nss/automation/taskcluster/windows/build.sh @@ -1,18 +1,18 @@ #!/usr/bin/env bash set -v -e -x -# Set up the toolchain. -if [ "$USE_64" = 1 ]; then - source $(dirname $0)/setup64.sh +if [[ "$USE_64" == 1 ]]; then + m=x64 else - source $(dirname $0)/setup32.sh + m=x86 fi +source "$(dirname "$0")/setup.sh" # Clone NSPR. hg_clone https://hg.mozilla.org/projects/nspr nspr default # Build. make -C nss nss_build_all # Package.
--- a/security/nss/automation/taskcluster/windows/build_gyp.sh +++ b/security/nss/automation/taskcluster/windows/build_gyp.sh @@ -1,34 +1,38 @@ #!/usr/bin/env bash set -v -e -x -# Set up the toolchain. -if [[ "$@" == *"-m32"* ]]; then - source $(dirname $0)/setup32.sh -else - source $(dirname $0)/setup64.sh -fi +# Parse for the -t option. +m=x64 +for i in "$@"; do + case "$i" in + -t|--target) m= ;; + --target=*) m="${i#*=}" ;; + *) [[ -z "$m" ]] && m="$i" ;; + esac +done +[[ "$m" == "ia32" ]] && m=x86 +source "$(dirname "$0")/setup.sh" # Install GYP. -cd gyp +pushd gyp python -m virtualenv test-env test-env/Scripts/python setup.py install test-env/Scripts/python -m pip install --upgrade pip test-env/Scripts/pip install --upgrade setuptools -cd .. - -export GYP_MSVS_OVERRIDE_PATH="${VSPATH}" -export GYP_MSVS_VERSION="2015" -export GYP="${PWD}/gyp/test-env/Scripts/gyp" - # Fool GYP. touch "${VSPATH}/VC/vcvarsall.bat" +export GYP_MSVS_OVERRIDE_PATH="${VSPATH}" +export GYP_MSVS_VERSION=2015 +popd + +export PATH="${PATH}:${PWD}/ninja/bin:${PWD}/gyp/test-env/Scripts" # Clone NSPR. hg_clone https://hg.mozilla.org/projects/nspr nspr default # Build with gyp. -GYP=${GYP} ./nss/build.sh -g -v "$@" +./nss/build.sh -g -v "$@" # Package. 7z a public/build/dist.7z dist
--- a/security/nss/automation/taskcluster/windows/setup.sh +++ b/security/nss/automation/taskcluster/windows/setup.sh @@ -1,26 +1,56 @@ #!/usr/bin/env bash set -v -e -x -export VSPATH="$(pwd)/vs2017_15.4.2" -export NINJA_PATH="$(pwd)/ninja/bin" - -export WINDOWSSDKDIR="${VSPATH}/SDK" -export VS90COMNTOOLS="${VSPATH}/VC" -export INCLUDE="${VSPATH}/VC/include:${VSPATH}/SDK/Include/10.0.15063.0/ucrt:${VSPATH}/SDK/Include/10.0.15063.0/shared:${VSPATH}/SDK/Include/10.0.15063.0/um" - # Usage: hg_clone repo dir [revision=@] hg_clone() { repo=$1 dir=$2 rev=${3:-@} for i in 0 2 5; do sleep $i hg clone -r "$rev" "$repo" "$dir" && return rm -rf "$dir" done exit 1 } -hg_clone https://hg.mozilla.org/build/tools tools default -tools/scripts/tooltool/tooltool_wrapper.sh $(dirname $0)/releng.manifest https://tooltool.mozilla-releng.net/ non-existant-file.sh /c/mozilla-build/python/python.exe /c/builds/tooltool.py --authentication-file /c/builds/relengapi.tok -c /c/builds/tooltool_cache +hg_clone https://hg.mozilla.org/build/tools tools b8d7c263dfc3 +tools/scripts/tooltool/tooltool_wrapper.sh \ + $(dirname $0)/releng.manifest https://tooltool.mozilla-releng.net/ \ + non-existant-file.sh /c/mozilla-build/python/python.exe \ + /c/builds/tooltool.py --authentication-file /c/builds/relengapi.tok \ + -c /c/builds/tooltool_cache + +# This needs $m to be set. +[[ -n "$m" ]] + +# Setup MSVC paths. +export VSPATH="${PWD}/vs2017_15.4.2" +UCRTVersion="10.0.15063.0" + +export WINDOWSSDKDIR="${VSPATH}/SDK" +export VS90COMNTOOLS="${VSPATH}/VC" +export WIN32_REDIST_DIR="${VSPATH}/VC/redist/${m}/Microsoft.VC141.CRT" +export WIN_UCRT_REDIST_DIR="${VSPATH}/SDK/Redist/ucrt/DLLs/${m}" + +if [ "$m" == "x86" ]; then + PATH="${PATH}:${VSPATH}/VC/bin/Hostx64/x86" + PATH="${PATH}:${VSPATH}/VC/bin/Hostx64/x64" +fi +PATH="${PATH}:${VSPATH}/VC/bin/Host${m}/${m}" +PATH="${PATH}:${WIN32_REDIST_DIR}" +PATH="${PATH}:${WIN_UCRT_REDIST_DIR}" +PATH="${PATH}:${VSPATH}/SDK/bin/${UCRTVersion}/x64" +export PATH + +LIB="${LIB}:${VSPATH}/VC/lib/${m}" +LIB="${LIB}:${VSPATH}/SDK/lib/${UCRTVersion}/ucrt/${m}" +LIB="${LIB}:${VSPATH}/SDK/lib/${UCRTVersion}/um/${m}" +export LIB + +INCLUDE="${INCLUDE}:${VSPATH}/VC/include" +INCLUDE="${INCLUDE}:${VSPATH}/SDK/Include/${UCRTVersion}/ucrt" +INCLUDE="${INCLUDE}:${VSPATH}/SDK/Include/${UCRTVersion}/shared" +INCLUDE="${INCLUDE}:${VSPATH}/SDK/Include/${UCRTVersion}/um" +export INCLUDE
deleted file mode 100644 --- a/security/nss/automation/taskcluster/windows/setup32.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -v -e -x - -source $(dirname $0)/setup.sh - -export WIN32_REDIST_DIR="${VSPATH}/VC/redist/x86/Microsoft.VC141.CRT" -export WIN_UCRT_REDIST_DIR="${VSPATH}/SDK/Redist/ucrt/DLLs/x86" -export PATH="${NINJA_PATH}:${VSPATH}/VC/bin/Hostx64/x86:${VSPATH}/VC/bin/Hostx64/x64:${VSPATH}/VC/Hostx86/x86:${VSPATH}/SDK/bin/10.0.15063.0/x64:${VSPATH}/VC/redist/x86/Microsoft.VC141.CRT:${VSPATH}/SDK/Redist/ucrt/DLLs/x86:${PATH}" -export LIB="${VSPATH}/VC/lib/x86:${VSPATH}/SDK/lib/10.0.15063.0/ucrt/x86:${VSPATH}/SDK/lib/10.0.15063.0/um/x86"
deleted file mode 100644 --- a/security/nss/automation/taskcluster/windows/setup64.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -v -e -x - -source $(dirname $0)/setup.sh - -export WIN32_REDIST_DIR="${VSPATH}/VC/redist/x64/Microsoft.VC141.CRT" -export WIN_UCRT_REDIST_DIR="${VSPATH}/SDK/Redist/ucrt/DLLs/x64" -export PATH="${NINJA_PATH}:${VSPATH}/VC/bin/Hostx64/x64:${VSPATH}/VC/bin/Hostx86/x86:${VSPATH}/SDK/bin/10.0.15063.0/x64:${VSPATH}/VC/redist/x64/Microsoft.VC141.CRT:${VSPATH}/SDK/Redist/ucrt/DLLs/x64:${PATH}" -export LIB="${VSPATH}/VC/lib/x64:${VSPATH}/SDK/lib/10.0.15063.0/ucrt/x64:${VSPATH}/SDK/lib/10.0.15063.0/um/x64"
--- a/security/nss/build.sh +++ b/security/nss/build.sh @@ -45,86 +45,96 @@ clean=0 rebuild_gyp=0 rebuild_nspr=0 target=Debug verbose=0 fuzz=0 fuzz_tls=0 fuzz_oss=0 no_local_nspr=0 -armhf=0 gyp_params=(--depth="$cwd" --generator-output=".") -nspr_params=() ninja_params=() -# try to guess sensible defaults -arch=$(python "$cwd"/coreconf/detect_host_arch.py) -if [ "$arch" = "x64" -o "$arch" = "aarch64" ]; then - build_64=1 -elif [ "$arch" = "arm" ]; then - armhf=1 +# Assume that the target architecture is the same as the host by default. +host_arch=$(python "$cwd"/coreconf/detect_host_arch.py) +target_arch=$host_arch + +# Assume that MSVC is wanted if this is running on windows. +platform=$(uname -s) +if [ "${platform%-*}" = "MINGW32_NT" -o "${platform%-*}" = "MINGW64_NT" ]; then + msvc=1 fi -# parse command line arguments +# Parse command line arguments. while [ $# -gt 0 ]; do - case $1 in + case "$1" in -c) clean=1 ;; -cc) clean_only=1 ;; - --gyp|-g) rebuild_gyp=1 ;; - --nspr) nspr_clean; rebuild_nspr=1 ;; + -v) ninja_params+=(-v); verbose=1 ;; -j) ninja_params+=(-j "$2"); shift ;; - -v) ninja_params+=(-v); verbose=1 ;; - --test) gyp_params+=(-Dtest_build=1) ;; - --clang) export CC=clang; export CCC=clang++; export CXX=clang++ ;; - --gcc) export CC=gcc; export CCC=g++; export CXX=g++ ;; - --fuzz) fuzz=1 ;; - --fuzz=oss) fuzz=1; fuzz_oss=1 ;; - --fuzz=tls) fuzz=1; fuzz_tls=1 ;; + --gyp|-g) rebuild_gyp=1 ;; + --opt|-o) opt_build=1 ;; + -m32|--m32) target_arch=ia32; echo 'Warning: use -t instead of -m32' 1>&2 ;; + -t|--target) target_arch="$2"; shift ;; + --target=*) target_arch="${1#*=}" ;; + --clang) export CC=clang; export CCC=clang++; export CXX=clang++; msvc=0 ;; + --gcc) export CC=gcc; export CCC=g++; export CXX=g++; msvc=0 ;; + --msvc) msvc=1 ;; --scan-build) enable_scanbuild ;; --scan-build=?*) enable_scanbuild "${1#*=}" ;; - --opt|-o) opt_build=1 ;; - -m32|--m32) build_64=0 ;; + --disable-tests) gyp_params+=(-Ddisable_tests=1) ;; + --pprof) gyp_params+=(-Duse_pprof=1) ;; --asan) enable_sanitizer asan ;; --msan) enable_sanitizer msan ;; --ubsan) enable_ubsan ;; --ubsan=?*) enable_ubsan "${1#*=}" ;; + --fuzz) fuzz=1 ;; + --fuzz=oss) fuzz=1; fuzz_oss=1 ;; + --fuzz=tls) fuzz=1; fuzz_tls=1 ;; --sancov) enable_sancov ;; --sancov=?*) enable_sancov "${1#*=}" ;; - --pprof) gyp_params+=(-Duse_pprof=1) ;; + --emit-llvm) gyp_params+=(-Demit_llvm=1 -Dsign_libs=0) ;; + --no-zdefs) gyp_params+=(-Dno_zdefs=1) ;; + --test) gyp_params+=(-Dtest_build=1) ;; --ct-verif) gyp_params+=(-Dct_verif=1) ;; - --emit-llvm) gyp_params+=(-Demit_llvm=1 -Dsign_libs=0) ;; - --disable-tests) gyp_params+=(-Ddisable_tests=1) ;; - --no-zdefs) gyp_params+=(-Dno_zdefs=1) ;; - --system-sqlite) gyp_params+=(-Duse_system_sqlite=1) ;; + --nspr) nspr_clean; rebuild_nspr=1 ;; --with-nspr=?*) set_nspr_path "${1#*=}"; no_local_nspr=1 ;; --system-nspr) set_nspr_path "/usr/include/nspr/:"; no_local_nspr=1 ;; + --system-sqlite) gyp_params+=(-Duse_system_sqlite=1) ;; + --enable-fips) gyp_params+=(-Ddisable_fips=0) ;; --enable-libpkix) gyp_params+=(-Ddisable_libpkix=0) ;; - --enable-fips) gyp_params+=(-Ddisable_fips=0) ;; --mozpkix-only) gyp_params+=(-Dmozpkix_only=1 -Ddisable_tests=1 -Dsign_libs=0) ;; *) show_help; exit 2 ;; esac shift done +# Set the target architecture and build type. +gyp_params+=(-Dtarget_arch="$target_arch") if [ "$opt_build" = 1 ]; then target=Release else target=Debug fi -if [ "$build_64" = 1 ]; then - nspr_params+=(--enable-64bit) -elif [ ! "$armhf" = 1 ]; then - gyp_params+=(-Dtarget_arch=ia32) -fi + +# Do special setup. if [ "$fuzz" = 1 ]; then source "$cwd"/coreconf/fuzz.sh fi +nspr_set_flags $sanitizer_flags +if [ ! -z "$sanitizer_flags" ]; then + gyp_params+=(-Dsanitizer_flags="$sanitizer_flags") +fi -# set paths +if [ "$msvc" = 1 ]; then + source "$cwd"/coreconf/msvc.sh +fi + +# Setup build paths. target_dir="$cwd"/out/$target mkdir -p "$target_dir" dist_dir="$cwd"/../dist dist_dir=$(mkdir -p "$dist_dir"; cd "$dist_dir"; pwd -P) gyp_params+=(-Dnss_dist_dir="$dist_dir") # -c = clean first if [ "$clean" = 1 -o "$clean_only" = 1 ]; then @@ -145,61 +155,58 @@ fi check_config() { local newconf="$1".new oldconf="$1" shift mkdir -p $(dirname "$newconf") echo CC="$CC" >"$newconf" echo CCC="$CCC" >>"$newconf" echo CXX="$CXX" >>"$newconf" + echo target_arch="$target_arch" >>"$newconf" for i in "$@"; do echo $i; done | sort >>"$newconf" # Note: The following diff fails if $oldconf isn't there as well, which # happens if we don't have a previous successful build. ! diff -q "$newconf" "$oldconf" >/dev/null 2>&1 } gyp_config="$cwd"/out/gyp_config nspr_config="$cwd"/out/$target/nspr_config +# Now check what needs to be rebuilt. # If we don't have a build directory make sure that we rebuild. if [ ! -d "$target_dir" ]; then rebuild_nspr=1 rebuild_gyp=1 elif [ ! -d "$dist_dir"/$target ]; then rebuild_nspr=1 fi -# Update NSPR ${C,CXX,LD}FLAGS. -nspr_set_flags $sanitizer_flags - -if check_config "$nspr_config" "${nspr_params[@]}" \ +if check_config "$nspr_config" \ nspr_cflags="$nspr_cflags" \ nspr_cxxflags="$nspr_cxxflags" \ nspr_ldflags="$nspr_ldflags"; then rebuild_nspr=1 fi -# Forward sanitizer flags. -if [ ! -z "$sanitizer_flags" ]; then - gyp_params+=(-Dsanitizer_flags="$sanitizer_flags") -fi - if check_config "$gyp_config" "${gyp_params[@]}"; then rebuild_gyp=1 fi -# save the chosen target +# Save the chosen target. mkdir -p "$dist_dir" echo $target > "$dist_dir"/latest +# Build. +# NSPR. if [[ "$rebuild_nspr" = 1 && "$no_local_nspr" = 0 ]]; then - nspr_build "${nspr_params[@]}" + nspr_build mv -f "$nspr_config".new "$nspr_config" fi +# gyp. if [ "$rebuild_gyp" = 1 ]; then if ! hash ${GYP} 2> /dev/null; then echo "Please install gyp" 1>&2 exit 1 fi # These extra arguments aren't used in determining whether to rebuild. obj_dir="$dist_dir"/$target gyp_params+=(-Dnss_dist_obj_dir=$obj_dir) @@ -207,18 +214,18 @@ if [ "$rebuild_gyp" = 1 ]; then set_nspr_path "$obj_dir/include/nspr:$obj_dir/lib" fi run_verbose run_scanbuild ${GYP} -f ninja "${gyp_params[@]}" "$cwd"/nss.gyp mv -f "$gyp_config".new "$gyp_config" fi -# Run ninja. -if hash ninja 2>/dev/null; then +# ninja. +if hash ninja-build 2>/dev/null; then + ninja=ninja-build +elif hash ninja 2>/dev/null; then ninja=ninja -elif hash ninja-build 2>/dev/null; then - ninja=ninja-build else echo "Please install ninja" 1>&2 exit 1 fi run_scanbuild $ninja -C "$target_dir" "${ninja_params[@]}"
--- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -5,8 +5,9 @@ /* * A dummy header file that is a dependency for all the object files. * Used to force a full recompilation of NSS in Mozilla's Tinderbox * depend builds. See comments in rules.mk. */ #error "Do not include this header file." +
--- a/security/nss/coreconf/fuzz.sh +++ b/security/nss/coreconf/fuzz.sh @@ -1,17 +1,16 @@ #!/usr/bin/env bash # This file is used by build.sh to setup fuzzing. set +e # Default to clang if CC is not set. if [ -z "$CC" ]; then - command -v clang &> /dev/null 2>&1 - if [ $? != 0 ]; then + if ! command -v clang &> /dev/null 2>&1; then echo "Fuzzing requires clang!" exit 1 fi export CC=clang export CCC=clang++ export CXX=clang++ fi @@ -19,18 +18,18 @@ gyp_params+=(-Dtest_build=1 -Dfuzz=1 -Ds # Add debug symbols even for opt builds. nspr_params+=(--enable-debug-symbols) if [ "$fuzz_oss" = 1 ]; then gyp_params+=(-Dno_zdefs=1 -Dfuzz_oss=1) else enable_sanitizer asan - # Ubsan doesn't build on 32-bit at the moment. Disable it. - if [ "$build_64" = 1 ]; then + # Ubsan only builds on x64 for the moment. + if [ "$target_arch" = "x64" ]; then enable_ubsan fi enable_sancov fi if [ "$fuzz_tls" = 1 ]; then gyp_params+=(-Dfuzz_tls=1) fi
new file mode 100644 --- /dev/null +++ b/security/nss/coreconf/msvc.sh @@ -0,0 +1,106 @@ +#!/bin/bash +# This configures the environment for running MSVC. It uses vswhere, the +# registry, and a little knowledge of how MSVC is laid out. + +if ! hash vswhere 2>/dev/null; then + echo "Can't find vswhere on the path, aborting" 1>&2 + exit 1 +fi + +if ! hash reg 2>/dev/null; then + echo "Can't find reg on the path, aborting" 1>&2 + exit 1 +fi + +# Turn a unix-y path into a windows one. +fixpath() { + if hash cygpath 2>/dev/null; then + cygpath --unix "$1" + else # haxx + echo "$1" | sed -e 's,\\,/,g;s,^\(.\):,/\L\1,;s,/$,,' + fi +} + +# Query the registry. This takes $1 and tags that on the end of several +# different paths, looking for a value called $2 at that location. +# e.g., +# regquery Microsoft\Microsoft SDKs\Windows\v10.0 ProductVersion +# looks for a REG_SZ value called ProductVersion at +# HKLM\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0 +# HKLU\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0 +# etc... +regquery() { + search=("HKLM\\SOFTWARE\\Wow6432Node" \ + "HKCU\\SOFTWARE\\Wow6432Node" \ + "HKLM\\SOFTWARE" \ + "HKCU\\SOFTWARE") + for i in "${search[@]}"; do + r=$(reg query "${i}\\${1}" -v "$2" | sed -e 's/ *'"$2"' *REG_SZ *//;t;d') + if [ -n "$r" ]; then + echo "$r" + return 0 + fi + done + return 1 +} + +VSCOMPONENT=Microsoft.VisualStudio.Component.VC.Tools.x86.x64 +vsinstall=$(vswhere -latest -requires "$VSCOMPONENT" -property installationPath) + +# Attempt to setup paths if vswhere returns something and VSPATH isn't set. +# Otherwise, assume that the env is setup. +if [[ -n "$vsinstall" && -z "$VSPATH" ]]; then + + case "$target_arch" in + ia32) m=x86 ;; + x64) m="$target_arch" ;; + *) + echo "No support for target '$target_arch' with MSVC." 1>&2 + exit 1 + esac + + export VSPATH=$(fixpath "$vsinstall") + export WINDOWSSDKDIR="${VSPATH}/SDK" + export VCINSTALLDIR="${VSPATH}/VC" + + CRTREG="Microsoft\\Microsoft SDKs\\Windows\\v10.0" + UniversalCRTSdkDir=$(regquery "$CRTREG" InstallationFolder) + UniversalCRTSdkDir=$(fixpath "$UniversalCRTSdkDir") + UCRTVersion=$(regquery "$CRTREG" ProductVersion) + UCRTVersion=$(cd "${UniversalCRTSdkDir}/include"; ls -d "${UCRTVersion}"* | tail -1) + + VCVER=$(cat "${VCINSTALLDIR}/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt") + REDISTVER=$(cat "${VCINSTALLDIR}/Auxiliary/Build/Microsoft.VCRedistVersion.default.txt") + export WIN32_REDIST_DIR="${VCINSTALLDIR}/Redist/MSVC/${REDISTVER}/${m}/Microsoft.VC141.CRT" + export WIN_UCRT_REDIST_DIR="${UniversalCRTSdkDir}/Redist/ucrt/DLLs/${m}" + + if [ "$m" == "x86" ]; then + PATH="${PATH}:${VCINSTALLDIR}/Tools/MSVC/${VCVER}/bin/Hostx64/x64" + PATH="${PATH}:${VCINSTALLDIR}/Tools/MSVC/${VCVER}/bin/Hostx64/x86" + fi + PATH="${PATH}:${VCINSTALLDIR}/Tools/MSVC/${VCVER}/bin/Host${m}/${m}" + PATH="${PATH}:${UniversalCRTSdkDir}/bin/${UCRTVersion}/${m}" + PATH="${PATH}:${WIN32_REDIST_DIR}" + export PATH + + INCLUDE="${VCINSTALLDIR}/Tools/MSVC/${VCVER}/ATLMFC/include" + INCLUDE="${INCLUDE}:${VCINSTALLDIR}/Tools/MSVC/${VCVER}/include" + INCLUDE="${INCLUDE}:${UniversalCRTSdkDir}/include/${UCRTVersion}/ucrt" + INCLUDE="${INCLUDE}:${UniversalCRTSdkDir}/include/${UCRTVersion}/shared" + INCLUDE="${INCLUDE}:${UniversalCRTSdkDir}/include/${UCRTVersion}/um" + INCLUDE="${INCLUDE}:${UniversalCRTSdkDir}/include/${UCRTVersion}/winrt" + INCLUDE="${INCLUDE}:${UniversalCRTSdkDir}/include/${UCRTVersion}/cppwinrt" + export INCLUDE + + LIB="${VCINSTALLDIR}/lib/${m}" + LIB="${VCINSTALLDIR}/Tools/MSVC/${VCVER}/lib/${m}" + LIB="${LIB}:${UniversalCRTSdkDir}/lib/${UCRTVersion}/ucrt/${m}" + LIB="${LIB}:${UniversalCRTSdkDir}/lib/${UCRTVersion}/um/${m}" + export LIB + + export GYP_MSVS_OVERRIDE_PATH="${VSPATH}" + export GYP_MSVS_VERSION=$(vswhere -latest -requires "$VSCOMPONENT" -property catalog_productLineVersion) +else + echo Assuming env setup is already done. + echo VSPATH=$VSPATH +fi
--- a/security/nss/coreconf/nspr.sh +++ b/security/nss/coreconf/nspr.sh @@ -27,16 +27,19 @@ nspr_build() mkdir -p "$nspr_dir" # These NSPR options are directory-specific, so they don't need to be # included in nspr_opt and changing them doesn't force a rebuild of NSPR. extra_params=(--prefix="$dist_dir"/$target) if [ "$opt_build" = 1 ]; then extra_params+=(--disable-debug --enable-optimize) fi + if [ "$target_arch" = "x64" ]; then + extra_params+=(--enable-64bit) + fi echo "NSPR [1/3] configure ..." pushd "$nspr_dir" >/dev/null CFLAGS="$nspr_cflags" CXXFLAGS="$nspr_cxxflags" \ LDFLAGS="$nspr_ldflags" CC="$CC" CXX="$CCC" \ run_verbose ../configure "${extra_params[@]}" "$@" popd >/dev/null echo "NSPR [2/3] make ..."
--- a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc @@ -941,16 +941,46 @@ TEST_F(TlsConnectDatagram13, SendSession ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); Connect(); EXPECT_EQ(SECFailure, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0)) << "no extra tickets in DTLS until we have Ack support"; EXPECT_EQ(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION, PORT_GetError()); } +TEST_F(TlsConnectStreamTls13, ExternalResumptionUseSecondTicket) { + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); + + struct ResumptionTicketState { + std::vector<uint8_t> ticket; + size_t invoked = 0; + } ticket_state; + auto cb = [](PRFileDesc* fd, const PRUint8* ticket, unsigned int ticket_len, + void* arg) -> SECStatus { + auto state = reinterpret_cast<ResumptionTicketState*>(arg); + state->ticket.assign(ticket, ticket + ticket_len); + state->invoked++; + return SECSuccess; + }; + SSL_SetResumptionTokenCallback(client_->ssl_fd(), cb, &ticket_state); + + Connect(); + EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), nullptr, 0)); + SendReceive(); + EXPECT_EQ(2U, ticket_state.invoked); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + client_->SetResumptionToken(ticket_state.ticket); + ExpectResumption(RESUME_TICKET); + Connect(); + SendReceive(); +} + TEST_F(TlsConnectTest, TestTls13ResumptionDowngrade) { ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); Connect(); SendReceive(); // Need to read so that we absorb the session tickets. CheckKeys();
--- a/security/nss/gtests/ssl_gtest/tls_esni_unittest.cc +++ b/security/nss/gtests/ssl_gtest/tls_esni_unittest.cc @@ -445,9 +445,26 @@ TEST_P(TlsConnectTls13, ConnectBogusEsni const uint8_t bogusNonceBuf[16] = {0}; DataBuffer bogusNonce(bogusNonceBuf, sizeof(bogusNonceBuf)); auto filter = MakeTlsFilter<TlsExtensionReplacer>( server_, ssl_tls13_encrypted_sni_xtn, bogusNonce); filter->EnableDecryption(); ConnectExpectAlert(client_, illegal_parameter); client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_ESNI_EXTENSION); } + +// ESNI is a commitment to doing TLS 1.3 or above. +// The TLS 1.2 server ignores ESNI and processes the dummy SNI. +// The client then aborts when it sees the server did TLS 1.2. +TEST_P(TlsConnectTls13, EsniButTLS12Server) { + EnsureTlsSetup(); + SetupEsni(client_, server_); + client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_3); + server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_2); + ConnectExpectAlert(client_, kTlsAlertProtocolVersion); + client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION); + server_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT); + ASSERT_FALSE(SSLInt_ExtensionNegotiated(server_->ssl_fd(), + ssl_tls13_encrypted_sni_xtn)); } +}
--- a/security/nss/help.txt +++ b/security/nss/help.txt @@ -1,52 +1,53 @@ -Usage: build.sh [-hcv] [-cc] [-j <n>] [--nspr] [--gyp|-g] [--opt|-o] [-m32] - [--test] [--pprof] [--scan-build[=output]] [--ct-verif] - [--asan] [--ubsan] [--msan] [--sancov[=edge|bb|func|...]] - [--disable-tests] [--fuzz[=tls|oss]] [--system-sqlite] - [--no-zdefs] [--with-nspr] [--system-nspr] [--enable-libpkix] - [--enable-fips] [--mozpkix-only] +Usage: build.sh [-h] [-c|-cc] [-v] [-j <n>] [--gyp|-g] [--opt|-o] + [-t <x64|x86|...>|--target=<x64|x86|...>] + [--clang|--gcc|--msvc] [--scan-build[=dir]] [--disable-tests] + [--pprof] [--asan] [--msan] [--ubsan[=bool,shift,...] + [--fuzz[=tls|oss]] [--sancov[=edge|bb|func|...]] + [--emit-llvm] [--no-zdefs] [--test] [--ct-verif] + [--nspr|--with-nspr=<include>:<lib>|--system-nspr] + [--system-sqlite] [--enable-fips] [--enable-libpkix] + [--mozpkix-only] This script builds NSS with gyp and ninja. -This build system is still under development. It does not yet support all -the features or platforms that NSS supports. - NSS build tool options: -h display this help and exit -c clean before build -cc clean without building -v verbose build -j <n> run at most <n> concurrent jobs - --nspr force a rebuild of NSPR --gyp|-g force a rerun of gyp --opt|-o do an opt build - -m32 do a 32-bit build on a 64-bit system + --target|-t specify target architecture (e.g., x86, x64, aarch64) --clang build with clang and clang++ --gcc build with gcc and g++ - --test ignore map files and export everything we have + --msvc build with MSVC + --scan-build run the build with scan-build + --scan-build=<dir> sets the output path for scan-build + --disable-tests don't build tests and corresponding cmdline utils + --pprof build with gperftool support + --asan enable address sanitizer + --msan enable memory sanitizer + --ubsan enable undefined behavior sanitizer + --ubsan=bool,shift,... sets specific UB sanitizers --fuzz build fuzzing targets (this always enables test builds) --fuzz=tls to enable TLS fuzzing mode --fuzz=oss to build for OSS-Fuzz - --pprof build with gperftool support - --ct-verif build with valgrind for ct-verif - --scan-build run the build with scan-build (scan-build has to be in the path) - --scan-build=/out/path sets the output path for scan-build - --asan do an asan build - --ubsan do an ubsan build - --ubsan=bool,shift,... sets specific UB sanitizers - --msan do an msan build --sancov do sanitize coverage builds --sancov=func sets coverage to function level for example --emit-llvm emit LLVM bitcode while building (requires the gold linker, use clang-3.8 for SAW) - --disable-tests don't build tests and corresponding cmdline utils + --no-zdefs don't set -Wl,-z,defs + --test ignore map files and export everything we have + --ct-verif build with valgrind for ct-verif + --nspr force a rebuild of NSPR + --with-nspr use the NSPR build at the given locations + --with-nspr=<include>:<lib> sets include and lib paths + --system-nspr attempt to use system nspr + shorthand for --with-nspr=/usr/include/nspr: --system-sqlite use system sqlite - --no-zdefs don't set -Wl,-z,defs - --with-nspr don't build NSPR but use the one at the given location, e.g. - --with-nspr=/path/to/nspr/include:/path/to/nspr/lib - --system-nspr use system nspr. This requires an installation of NSPR and - might not work on all systems. - --enable-libpkix make libpkix part of the build. - --enable-fips don't disable FIPS checks. - --mozpkix-only build only static mozpkix and mozpkix-test libraries. - Note that support for this build option is limited. + --enable-fips enable FIPS checks + --enable-libpkix make libpkix part of the build + --mozpkix-only build only static mozpkix and mozpkix-test libraries + support for this build option is limited
--- a/security/nss/lib/nss/nss.h +++ b/security/nss/lib/nss/nss.h @@ -17,22 +17,22 @@ /* * NSS's major version, minor version, patch level, build number, and whether * this is a beta release. * * The format of the version string should be * "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]" */ -#define NSS_VERSION "3.40" _NSS_CUSTOMIZED " Beta" +#define NSS_VERSION "3.40" _NSS_CUSTOMIZED #define NSS_VMAJOR 3 #define NSS_VMINOR 40 #define NSS_VPATCH 0 #define NSS_VBUILD 0 -#define NSS_BETA PR_TRUE +#define NSS_BETA PR_FALSE #ifndef RC_INVOKED #include "seccomon.h" typedef struct NSSInitParametersStr NSSInitParameters; /*
--- a/security/nss/lib/softoken/softkver.h +++ b/security/nss/lib/softoken/softkver.h @@ -12,16 +12,16 @@ /* * Softoken's major version, minor version, patch level, build number, * and whether this is a beta release. * * The format of the version string should be * "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]" */ -#define SOFTOKEN_VERSION "3.40" SOFTOKEN_ECC_STRING " Beta" +#define SOFTOKEN_VERSION "3.40" SOFTOKEN_ECC_STRING #define SOFTOKEN_VMAJOR 3 #define SOFTOKEN_VMINOR 40 #define SOFTOKEN_VPATCH 0 #define SOFTOKEN_VBUILD 0 -#define SOFTOKEN_BETA PR_TRUE +#define SOFTOKEN_BETA PR_FALSE #endif /* _SOFTKVER_H_ */
--- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -6558,19 +6558,30 @@ ssl3_HandleServerHello(sslSocket *ss, PR if (isHelloRetry && ss->ssl3.hs.helloRetry) { SSL_TRC(3, ("%d: SSL3[%d]: received a second hello_retry_request", SSL_GETPID(), ss->fd)); desc = unexpected_message; errCode = SSL_ERROR_RX_UNEXPECTED_HELLO_RETRY_REQUEST; goto alert_loser; } - /* The server didn't pick 1.3 although we either received a - * HelloRetryRequest, or we prepared to send early app data. */ + /* There are three situations in which the server must pick + * TLS 1.3. + * + * 1. We offered ESNI. + * 2. We received HRR + * 3. We sent early app data. + * + */ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { + if (ss->xtnData.esniPrivateKey) { + desc = protocol_version; + errCode = SSL_ERROR_UNSUPPORTED_VERSION; + goto alert_loser; + } if (isHelloRetry || ss->ssl3.hs.helloRetry) { /* SSL3_SendAlert() will uncache the SID. */ desc = illegal_parameter; errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO; goto alert_loser; } if (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent) { /* SSL3_SendAlert() will uncache the SID. */
--- a/security/nss/lib/ssl/sslnonce.c +++ b/security/nss/lib/ssl/sslnonce.c @@ -1088,20 +1088,22 @@ ssl_CacheExternalToken(sslSocket *ss) if (ssl_EncodeResumptionToken(sid, &encodedToken) != SECSuccess) { SSL_TRC(3, ("SSL [%d]: encoding resumption token failed", ss->fd)); return; } PORT_Assert(SSL_BUFFER_LEN(&encodedToken) > 0); PRINT_BUF(40, (ss, "SSL: encoded resumption token", SSL_BUFFER_BASE(&encodedToken), SSL_BUFFER_LEN(&encodedToken))); - ss->resumptionTokenCallback(ss->fd, SSL_BUFFER_BASE(&encodedToken), - SSL_BUFFER_LEN(&encodedToken), - ss->resumptionTokenContext); - + SECStatus rv = ss->resumptionTokenCallback( + ss->fd, SSL_BUFFER_BASE(&encodedToken), SSL_BUFFER_LEN(&encodedToken), + ss->resumptionTokenContext); + if (rv == SECSuccess) { + sid->cached = in_external_cache; + } sslBuffer_Clear(&encodedToken); } void ssl_CacheSessionID(sslSocket *ss) { sslSecurityInfo *sec = &ss->sec; PORT_Assert(sec); @@ -1195,27 +1197,33 @@ void ssl3_SetSIDSessionTicket(sslSessionID *sid, /*in/out*/ NewSessionTicket *newSessionTicket) { PORT_Assert(sid); PORT_Assert(newSessionTicket); PORT_Assert(newSessionTicket->ticket.data); PORT_Assert(newSessionTicket->ticket.len != 0); - /* if sid->u.ssl3.lock, we are updating an existing entry that is already - * cached or was once cached, so we need to acquire and release the write - * lock. Otherwise, this is a new session that isn't shared with anything - * yet, so no locking is needed. + /* If this is in the client cache, we are updating an existing entry that is + * already cached or was once cached, so we need to acquire and release the + * write lock. Otherwise, this is a new session that isn't shared with + * anything yet, so no locking is needed. */ if (sid->u.ssl3.lock) { + PORT_Assert(sid->cached == in_client_cache); PR_RWLock_Wlock(sid->u.ssl3.lock); - if (sid->u.ssl3.locked.sessionTicket.ticket.data) { - SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, - PR_FALSE); - } + } + /* If this was in the client cache, then we might have to free the old + * ticket. In TLS 1.3, we might get a replacement ticket if the server + * sends more than one ticket. */ + if (sid->u.ssl3.locked.sessionTicket.ticket.data) { + PORT_Assert(sid->cached == in_client_cache || + sid->version >= SSL_LIBRARY_VERSION_TLS_1_3); + SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket, + PR_FALSE); } PORT_Assert(!sid->u.ssl3.locked.sessionTicket.ticket.data); /* Do a shallow copy, moving the ticket data. */ sid->u.ssl3.locked.sessionTicket = *newSessionTicket; newSessionTicket->ticket.data = NULL; newSessionTicket->ticket.len = 0;
--- a/security/nss/lib/ssl/tls13con.c +++ b/security/nss/lib/ssl/tls13con.c @@ -4722,17 +4722,18 @@ tls13_HandleNewSessionTicket(sslSocket * return SECFailure; } PRINT_BUF(50, (ss, "Caching session ticket", ticket.ticket.data, ticket.ticket.len)); /* Replace a previous session ticket when * we receive a second NewSessionTicket message. */ - if (ss->sec.ci.sid->cached == in_client_cache) { + if (ss->sec.ci.sid->cached == in_client_cache || + ss->sec.ci.sid->cached == in_external_cache) { /* Create a new session ID. */ sslSessionID *sid = ssl3_NewSessionID(ss, PR_FALSE); if (!sid) { return SECFailure; } /* Copy over the peerCert. */ PORT_Assert(ss->sec.ci.sid->peerCert);
--- a/security/nss/lib/util/nssutil.h +++ b/security/nss/lib/util/nssutil.h @@ -14,22 +14,22 @@ /* * NSS utilities's major version, minor version, patch level, build number, * and whether this is a beta release. * * The format of the version string should be * "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]" */ -#define NSSUTIL_VERSION "3.40 Beta" +#define NSSUTIL_VERSION "3.40" #define NSSUTIL_VMAJOR 3 #define NSSUTIL_VMINOR 40 #define NSSUTIL_VPATCH 0 #define NSSUTIL_VBUILD 0 -#define NSSUTIL_BETA PR_TRUE +#define NSSUTIL_BETA PR_FALSE SEC_BEGIN_PROTOS /* * Returns a const string of the UTIL library version. */ extern const char *NSSUTIL_GetVersion(void);
--- a/taskcluster/taskgraph/actions/backfill.py +++ b/taskcluster/taskgraph/actions/backfill.py @@ -113,27 +113,24 @@ def backfill_action(parameters, graph_co if task.label != label: return task if input.get('addGeckoProfile'): cmd = task.task['payload']['command'] task.task['payload']['command'] = add_args_to_command(cmd, ['--geckoProfile']) task.task['extra']['treeherder']['symbol'] += '-p' if input.get('testPath', ''): - tp = input.get('testPath', '') is_wpttest = 'web-platform' in task.task['metadata']['name'] is_android = 'android' in task.task['metadata']['name'] gpu_required = False - # TODO: this has a high chance of getting out of date if (not is_wpttest) and \ ('gpu' in task.task['metadata']['name'] or 'webgl' in task.task['metadata']['name'] or - 'canvas' in tp or - 'gfx/tests' in tp or - ('reftest' in tp and 'jsreftest' not in tp)): + ('reftest' in task.task['metadata']['name'] and + 'jsreftest' not in task.task['metadata']['name'])): gpu_required = True # Create new cmd that runs a test-verify type job preamble_length = 3 verify_args = ['--e10s', '--verify', '--total-chunk=1', '--this-chunk=1']
new file mode 100644 --- /dev/null +++ b/testing/web-platform/meta/payment-handler/__dir__.ini @@ -0,0 +1,3 @@ +prefs: [dom.payments.request.enabled:true] +disabled: + if not nightly_build: https://bugzilla.mozilla.org/show_bug.cgi?id=1495301
--- a/testing/web-platform/meta/payment-handler/can-make-payment-event.https.html.ini +++ b/testing/web-platform/meta/payment-handler/can-make-payment-event.https.html.ini @@ -13,17 +13,18 @@ [If CanMakePaymentEvent.respondWith(Promise.resolve(true)) is called, then the payment method is supported.] expected: FAIL [If CanMakePaymentEvent.respondWith(Promise.reject(error)) is called, then the payment method is not supported.] expected: FAIL [If an app supports "basic-card" in general and that's what merchant requests as well, then capability filtering should make the app available for use. CanMakePaymentEvent should not be fired for "basic-card".] - expected: FAIL + expected: + if not e10s: FAIL [If an app has less specific "basic-card" capabilites than merchant's request, capability filtering should not make the app available for use. CanMakePaymentEvent should not be fired for "basic-card". ] expected: FAIL [If an app has the exact "basic-card" capabilities that a merchant requested, capability filtering should make the app available for use. CanMakePaymentEvent should not be fired for "basic-card".] expected: FAIL [If an app has more specific "basic-card" capabilities than merchant's request, capability filtering should make the app available for use. CanMakePaymentEvent should not be fired for "basic-card".]
new file mode 100644 --- /dev/null +++ b/testing/web-platform/meta/payment-method-basic-card/__dir__.ini @@ -0,0 +1,3 @@ +prefs: [dom.payments.request.enabled:true] +disabled: + if not nightly_build: https://bugzilla.mozilla.org/show_bug.cgi?id=1495301
--- a/testing/web-platform/meta/payment-method-basic-card/payment-request-canmakepayment-method.https.html.ini +++ b/testing/web-platform/meta/payment-method-basic-card/payment-request-canmakepayment-method.https.html.ini @@ -1,10 +1,11 @@ [payment-request-canmakepayment-method.https.html] [Must return false when the PMI is not supported at by the user agent.] - expected: FAIL + expected: + if not e10s: FAIL [Must return true when basic-card is amongst unsupported PMIs.] expected: FAIL [If basic-card is supported, then return a promise that resolves to true.] - expected: FAIL - + expected: + if not e10s: FAIL
new file mode 100644 --- /dev/null +++ b/testing/web-platform/meta/payment-method-id/__dir__.ini @@ -0,0 +1,3 @@ +prefs: [dom.payments.request.enabled:true] +disabled: + if not nightly_build: https://bugzilla.mozilla.org/show_bug.cgi?id=1495301
--- a/testing/web-platform/meta/payment-method-id/payment-request-ctor-pmi-handling.https.html.ini +++ b/testing/web-platform/meta/payment-method-id/payment-request-ctor-pmi-handling.https.html.ini @@ -1,13 +1,16 @@ [payment-request-ctor-pmi-handling.https.html] [Must not throw on syntactically valid standardized payment method identifiers, even if they are not supported] - expected: FAIL + expected: + if not e10s: FAIL [Must support valid standard URL PMIs] - expected: FAIL + expected: + if not e10s: FAIL [Must throw on syntactically invalid standardized payment method identifiers] - expected: FAIL + expected: + if not e10s: FAIL [Constructor MUST throw if given an invalid URL-based payment method identifier] - expected: FAIL - + expected: + if not e10s: FAIL
--- a/toolkit/components/antitracking/AntiTrackingCommon.cpp +++ b/toolkit/components/antitracking/AntiTrackingCommon.cpp @@ -31,17 +31,16 @@ #include "nsNetUtil.h" #include "nsPIDOMWindow.h" #include "nsPrintfCString.h" #include "nsScriptSecurityManager.h" #include "nsSandboxFlags.h" #include "prtime.h" #define ANTITRACKING_PERM_KEY "3rdPartyStorage" -#define USER_INTERACTION_PERM "storageAccessAPI" using namespace mozilla; using mozilla::dom::ContentChild; static LazyLogModule gAntiTrackingLog("AntiTracking"); static const nsCString::size_type sMaxSpecLength = 128; #define LOG(format) MOZ_LOG(gAntiTrackingLog, mozilla::LogLevel::Debug, format)
--- a/toolkit/components/antitracking/AntiTrackingCommon.h +++ b/toolkit/components/antitracking/AntiTrackingCommon.h @@ -6,16 +6,18 @@ #ifndef mozilla_antitrackingservice_h #define mozilla_antitrackingservice_h #include "nsString.h" #include "mozilla/MozPromise.h" #include "mozilla/RefPtr.h" +#define USER_INTERACTION_PERM "storageAccessAPI" + class nsIChannel; class nsIHttpChannel; class nsIPermission; class nsIPrincipal; class nsIURI; class nsPIDOMWindowInner; namespace mozilla {