Compare commits

...
71 Commits
Author SHA1 Message Date
wolfbeast 39a3d75915 Merge branch 'release' into Basilisk-release 2020-02-15 13:24:38 +01:00
Simon Giesecke 9600e2dc87 [IndexedDB] Ensure that strong references to newly created cursors are
kept until the DOM Binding is created.

This fixes random crashes on websites that use IndexedDB cursors.
See also BZ bug 1599420
2020-02-15 13:23:18 +01:00
Henri Sivonen 32de0e3ccc [Parser] Move setting context to null to the correct location. 2020-02-15 13:23:03 +01:00
wolfbeast ceb9d0ad92 Issue #1441 - Guard appomni/greomni with UXP_CUSTOM_OMNI env var.
This adds an addition to the environment set up for child processes
(plugin container) so that it may still be able to pass the omni
parameters there as-needed.
2020-02-15 13:20:36 +01:00
sotaro f16336a10d [Layers] Clear WrappingTextureSourceYCbCrBasic::mTexture correctly 2020-02-15 13:20:18 +01:00
wolfbeast 582949cd30 [CSP] Allow not having a Port for RessourceURI if the Scheme has no
Default Port
2020-02-15 13:19:25 +01:00
wolfbeast 1a6fa0b095 [SSUAO] Update YouTube overrides to switch to polymer v1 2020-02-06 18:05:29 +00:00
wolfbeast 3dca4ce612 Merge remote-tracking branch 'origin/release' into Basilisk-release 2020-02-06 18:01:15 +00:00
Matt A. Tobin a48dabbcba Issue #1377 - Fix porting typo in mailnews/base/search/content/searchWidgets.xml
MailNews Core being historically comm tended to avoid defining shorthand for Components.interfaces
2020-02-02 02:17:37 +01:00
athenian200 f0aaab86a1 Fix whitespace. 2020-01-27 11:02:39 +01:00
athenian200 77f2d7f720 Issue #1349 - Stop 2xx FTP responses from causing browser to hang.
LIST and RETR still appear to work as intended on ftp:// URLs after my changes. I wasn't able to test STOR because the browser doesn't appear to support FTP uploads at this time (although our FTP implementation appears perfectly capable of doing an FTP upload.)

If I understood the issue correctly, though, what we're doing is ensuring that we receive a preliminary 100 response from the FTP server for a given action before jumping to the 200 code describing what we do if the action was completed. Even though it makes no logical sense for a server to say an action was completed before it was initiated, someone could write a really annoying FTP server that takes advantage of this fact to crash the browser if they wanted.
2020-01-27 11:02:21 +01:00
Matt A. Tobin 5002c657a2 Issue #1358 - Default to SSL/TLS when using the Account Wizard 2020-01-20 12:02:13 +01:00
wolfbeast ea51616e31 Issue #1362 - Revert "Implement regular expression lookbehind"
This reverts commit fa473930f4.
2020-01-19 14:44:48 +01:00
wolfbeast 35dc8e5abb Issue #1362 - Revert "Update js/src/builtin/TestingFunctions.cpp for
regex lookbehind changes"

This reverts commit e79607a7a6.
2020-01-19 14:44:35 +01:00
wolfbeast 329d35ab57 Merge branch 'release' into Basilisk-release 2020-01-11 22:41:59 +01:00
wolfbeast cffb44547a Simplify some alias sets in IonMonkey. 2020-01-11 13:50:23 +01:00
wolfbeast 81f3185e0e Prefer file extension as-provided over default extension for mimetype to
look up default applications on Windows
2020-01-11 13:50:08 +01:00
wolfbeast e01d499617 Update GTK clipboard handling
- Store the clipboard even if it was set in a GTK dialog.
- Fix a GtkTargetList leak.
- Notify GTK that the data is no longer available for
clipboard_get_cb(), so that GTK will no longer advertise nor attempt to
store the data.
2020-01-11 13:49:49 +01:00
wolfbeast 38b0041414 Handle missing base64 challenge in NegotiateAuth and NTLMAuth. 2020-01-11 13:46:18 +01:00
Yaron Tausky d62795c868 Make copy of list before iterating over it. 2020-01-11 13:46:03 +01:00
wolfbeast d0256e1afc Be more consistent about decoding IP addresses in PSM. 2020-01-11 13:45:47 +01:00
wolfbeast 19939f17f0 Simplify value setting.
This gets rid of unused boolean return values on setters and a level of
indirection for calls to set values.
2020-01-11 13:45:34 +01:00
wolfbeast 00b8ab8be2 Issue #1348 - Part 3: Set IS_PRIVATE input scope in private browsing.
Microsoft IME on Windows 10 20H1 (build 19025+) supports IME private
mode by input scope. Although previous Windows versions use an
undocumented API for Edge and IE only, the next Windows 10 release will
use a public API for it.
We pre-empt this potential privacy concern by setting the IS_PRIVATE
flag when in PB mode.
2020-01-11 13:45:17 +01:00
wolfbeast e338d99699 Issue #1348 - Part 2: Teach IMEState about Private Browsing mode. 2020-01-11 13:45:02 +01:00
Makoto Kato f61a99e5ed Issue #1348 - Part 1: Clean up input scope support for IMM32.
Use AutoTArray to set input scope.
2020-01-11 13:44:49 +01:00
wolfbeast f0e7aec5da Reject sample rates that are out-of-range for libsoundtouch.
We never reach this with our normal use of this lib but adding the
sanity check just in case. (ported from upstream)
2020-01-11 13:44:33 +01:00
Gaming4JC c7fbaa67c6 Bug 1599054 - allow callers to ommit sending OAuth2 client_secret parameter. 2020-01-11 13:43:26 +01:00
Gaming4JC c5b7a8f476 Bug 1597933 - Use URLSearchParams for setting params for OAuth2 authorization request. 2020-01-11 13:43:26 +01:00
Gaming4JC 686415ad89 Bug 1597933 - use fetch + URLSearchParms instead of Http.jsm to request OAuth2 access token. 2020-01-11 13:43:25 +01:00
Gaming4JC 925fd54115 Bug 1597933 - don't pass string constants to determine OAuth refresh token or not. 2020-01-11 13:43:25 +01:00
Gaming4JC c33ae6a656 Bug 1597933 - improve OAuth2 params parsing. 2020-01-11 13:43:24 +01:00
Gaming4JC 135098e064 Bug 1597933 - clean up OAuth2 code: remove responseType which is always code.
Response type token is part of the OAuth 2.0 Implicit Flow which is not used in Mail Applications, but also discouraged by the OAuth Working Group: https://developer.okta.com/blog/2019/05/01/is-the-oauth-implicit-flow-dead
2020-01-11 13:43:23 +01:00
Gaming4JC 1eb19e2309 Bug 1453643 - Enable proper retry on oauth2 authenication failure.
This prevents mail applications from  attempting to use an unauthenticated connection to mailbox(s) and avoid unexpected deletion of local mbox files and subsequent re-download of mailbox content over imap.
2020-01-11 13:43:23 +01:00
Gaming4JC 798cdc9e47 Bug 1176399 - Multiple requests for master password when GMail OAuth2 is enabled. 2020-01-11 13:43:22 +01:00
wolfbeast 1110944d4b Merge branch 'master' into release 2019-12-09 10:04:08 +01:00
wolfbeast 18159927e8 Merge branch 'master' into release 2019-12-07 08:47:22 +01:00
wolfbeast d0da27ef57 Merge branch 'release' into Basilisk-release 2019-10-30 18:42:38 +01:00
wolfbeast 0f7f961e88 Merge branch 'master' into Basilisk-release 2019-09-06 10:31:35 +02:00
Matt A. Tobin dba27e6f63 [MCP Applications] Add %WIDGET_TOOLKIT% to the AUS update url for Pale Moon and Basilisk
Also removes the redundant branding version of app.update.url in Pale Moon that was missed when many prefs were merged back into application preferences
2019-09-03 13:37:37 +02:00
wolfbeast 202296d02a Pull Basilisk-release forward. 2019-08-18 16:26:16 +02:00
wolfbeast 1530f48c27 Improve origin-clean algorithm based on our previous changes.
- Instead of trying the failing refactored Mozilla way, simply add a
check where needed building on what was put in place previously.
2019-06-08 19:32:47 +02:00
wolfbeast 684778cb22 Revert "Improve origin-clean algorithm"
This reverts commit e69b3f567c.
2019-06-08 19:31:36 +02:00
wolfbeast dee00a8a79 Merge branch 'master' into Basilisk-release 2019-06-04 18:21:04 +02:00
wolfbeast 851cfd198b Simplify some alias sets in IonMonkey. 2019-03-26 18:42:38 +01:00
wolfbeast 1e1525c44c Merge commit 'eb77e289bbe056b58051db0fa868e95da803aa0a' into Basilisk-release 2019-03-26 18:41:32 +01:00
wolfbeast e25ad54395 Merge branch 'master' into Basilisk-release 2019-03-06 12:30:20 +01:00
wolfbeast 74533a8432 Expose TLS 1.3 cipher suite prefs. 2019-02-10 09:00:44 +01:00
wolfbeast 7715472ae4 Merge branch 'master' into Basilisk-release 2019-02-08 13:21:03 +01:00
wolfbeast 2b3b0e053e Merge branch 'master' into Basilisk-release 2019-02-07 23:03:00 +01:00
wolfbeast e66dd9ee75 Merge branch 'master' into Basilisk-release 2019-02-07 22:18:49 +01:00
wolfbeast 0dca00b282 Merge branch 'master' into Basilisk-release 2019-02-07 16:32:52 +01:00
wolfbeast 76fe52eb81 Merge branch 'master' into Basilisk-release 2018-12-18 11:39:00 +01:00
wolfbeast 63635e38ff Merge branch 'master' into Basilisk-release 2018-11-07 06:01:03 +01:00
wolfbeast 1626b5d704 Merge branch 'master' into Basilisk-release 2018-11-03 09:06:25 +01:00
wolfbeast 314fb761d1 Merge branch 'master' into Basilisk-release 2018-09-27 09:07:52 +02:00
wolfbeast fbaab39c94 Merge branch 'master' into Basilisk-release 2018-09-27 09:05:25 +02:00
wolfbeast 580084e9e1 Merge branch 'master' into Basilisk-release 2018-09-04 20:53:31 +02:00
wolfbeast fc61780b35 Merge commit '50d3e596bbe89c95615f96eb71f6bc5be737a1db' into Basilisk-release
# Conflicts:
#	browser/app/profile/firefox.js
#	browser/components/preferences/jar.mn
2018-07-18 08:24:24 +02:00
wolfbeast 69f7f9e5f1 Pre-process blocklists.js 2018-06-01 00:46:44 +02:00
wolfbeast 2d4ff8df91 Merge branch 'master' into Basilisk-release 2018-05-31 09:45:25 +02:00
wolfbeast f4b8be889c Merge branch 'master' into Basilisk-release 2018-05-14 12:21:38 +02:00
wolfbeast e9dd029f5d Merge branch 'master' into Basilisk-release 2018-05-14 10:50:01 +02:00
wolfbeast 9d6a7ae25d Merge branch 'master' into Basilisk-release 2018-04-27 01:28:11 +02:00
wolfbeast 42f8488a5f Merge branch 'master' into Basilisk-release 2018-04-25 23:08:37 +02:00
wolfbeast 681c39a0ec Hard-code the version number for Mozilla's version checker for add-ons. 2018-04-23 17:21:17 +02:00
wolfbeast 55eb2832f5 Set preferences for release. 2018-04-22 20:41:43 +02:00
wolfbeast 003273327d Make sure to keep the safebrowsing entities valid. 2018-04-22 18:17:19 +02:00
wolfbeast 650371311d Update about:rights legal text. 2018-04-22 14:59:26 +02:00
wolfbeast 1fccd9d8ee Remove undesired system add-ons (all except PDFjs) 2018-04-22 13:19:49 +02:00
wolfbeast f2f6f7e8b0 Disable Mozilla health report service. 2018-04-22 13:16:44 +02:00
wolfbeast e73929a782 Remove NPAPI deprecation statement from about:plugins. 2018-04-22 13:08:18 +02:00
55 changed files with 748 additions and 760 deletions

No files matched your search

@@ -41,8 +41,7 @@ pref("app.update.url.details", "https://@BRANDING_SITEURL@/@BRANDING_RELNOTESPAT
pref("general.useragent.compatMode.firefox",true);
pref("general.useragent.compatMode.gecko",true);
// Switch Application Updates off for now
pref("app.update.enabled", false);
pref("app.update.enabled", true);
// Shared User Agent Overrides
#include ../../shared/uaoverrides.inc
@@ -24,8 +24,8 @@ pref("@GUAO_PREF@.accounts.firefox.com", "Mozilla/5.0 (@OS_SLICE@ rv:@GK_VERSION
pref("@GUAO_PREF@.addons.mozilla.org", "Mozilla/5.0 (@OS_SLICE@ rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@");
// Required for domains that have proven unresponsive to requests from users
pref("@GUAO_PREF@.youtube.com","Mozilla/5.0 (@OS_SLICE@ rv:42.0) @GK_SLICE@ Firefox/42.0 @APP_SLICE@");
pref("@GUAO_PREF@.gaming.youtube.com","Mozilla/5.0 (@OS_SLICE@ rv:42.0) @GK_SLICE@ Firefox/42.0");
pref("@GUAO_PREF@.youtube.com","Mozilla/5.0 (@OS_SLICE@ rv:62.0) @GK_SLICE@ Firefox/62.0 @APP_SLICE@");
pref("@GUAO_PREF@.gaming.youtube.com","Mozilla/5.0 (@OS_SLICE@ rv:62.0) @GK_SLICE@ Firefox/62.0");
pref("@GUAO_PREF@.netflix.com","Mozilla/5.0 (@OS_SLICE@ rv:42.0) @GK_SLICE@ Firefox/42.0 @APP_SLICE@");
// The never-ending Facebook debacle...
+2 -1
View File
@@ -68,7 +68,8 @@ StreamControl::CloseAllReadStreams()
{
AssertOwningThread();
ReadStreamList::ForwardIterator iter(mReadStreamList);
auto readStreamList = mReadStreamList;
ReadStreamList::ForwardIterator iter(readStreamList);
while (iter.HasMore()) {
iter.GetNext()->CloseStream();
}
+16 -8
View File
@@ -297,7 +297,7 @@ IMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
IMEState newState = GetNewIMEState(sPresContext, nullptr);
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::LOST_FOCUS);
SetIMEState(newState, nullptr, sWidget, action);
SetIMEState(newState, nullptr, nullptr, sWidget, action);
}
sWidget = nullptr;
sContent = nullptr;
@@ -352,7 +352,7 @@ IMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
IMEState newState = GetNewIMEState(sPresContext, nullptr);
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::LOST_FOCUS);
SetIMEState(newState, nullptr, sWidget, action);
SetIMEState(newState, aPresContext, nullptr, sWidget, action);
}
sWidget = nullptr;
@@ -542,7 +542,7 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
}
// Update IME state for new focus widget
SetIMEState(newState, aContent, newWidget, aAction);
SetIMEState(newState, aPresContext, aContent, newWidget, aAction);
}
sActiveTabParent = newTabParent;
@@ -704,7 +704,7 @@ IMEStateManager::OnClickInEditor(nsPresContext* aPresContext,
InputContextAction action(cause, InputContextAction::FOCUS_NOT_CHANGED);
IMEState newState = GetNewIMEState(aPresContext, aContent);
SetIMEState(newState, aContent, widget, action);
SetIMEState(newState, aPresContext, aContent, widget, action);
}
// static
@@ -912,7 +912,7 @@ IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
if (updateIMEState) {
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
InputContextAction::FOCUS_NOT_CHANGED);
SetIMEState(aNewIMEState, aContent, widget, action);
SetIMEState(aNewIMEState, sPresContext, aContent, widget, action);
if (NS_WARN_IF(widget->Destroyed())) {
MOZ_LOG(sISMLog, LogLevel::Error,
(" UpdateIMEState(), widget has gone during setting input context"));
@@ -1022,8 +1022,8 @@ IMEStateManager::SetInputContextForChildProcess(
MOZ_LOG(sISMLog, LogLevel::Info,
("SetInputContextForChildProcess(aTabParent=0x%p, "
"aInputContext={ mIMEState={ mEnabled=%s, mOpen=%s }, "
"mHTMLInputType=\"%s\", mHTMLInputInputmode=\"%s\", mActionHint=\"%s\" }, "
"aAction={ mCause=%s, mAction=%s }), "
"mHTMLInputType=\"%s\", mHTMLInputInputmode=\"%s\", mActionHint=\"%s\", "
"mInPrivateBrowsing=%s }, aAction={ mCause=%s, mAction=%s }), "
"sPresContext=0x%p (available: %s), sWidget=0x%p (available: %s), "
"sActiveTabParent=0x%p",
aTabParent, GetIMEStateEnabledName(aInputContext.mIMEState.mEnabled),
@@ -1031,6 +1031,7 @@ IMEStateManager::SetInputContextForChildProcess(
NS_ConvertUTF16toUTF8(aInputContext.mHTMLInputType).get(),
NS_ConvertUTF16toUTF8(aInputContext.mHTMLInputInputmode).get(),
NS_ConvertUTF16toUTF8(aInputContext.mActionHint).get(),
GetBoolName(aInputContext.mInPrivateBrowsing),
GetActionCauseName(aAction.mCause),
GetActionFocusChangeName(aAction.mFocusChange),
sPresContext.get(), GetBoolName(CanHandleWith(sPresContext)),
@@ -1070,6 +1071,7 @@ IMEStateManager::SetInputContextForChildProcess(
// static
void
IMEStateManager::SetIMEState(const IMEState& aState,
nsPresContext* aPresContext,
nsIContent* aContent,
nsIWidget* aWidget,
InputContextAction aAction)
@@ -1090,6 +1092,10 @@ IMEStateManager::SetIMEState(const IMEState& aState,
context.mIMEState = aState;
context.mMayBeIMEUnaware = context.mIMEState.IsEditable() &&
sCheckForIMEUnawareWebApps && MayBeIMEUnawareWebApp(aContent);
context.mInPrivateBrowsing =
aPresContext &&
nsContentUtils::IsInPrivateBrowsing(aPresContext->Document());
if (aContent &&
aContent->IsAnyOfHTMLElements(nsGkAtoms::input, nsGkAtoms::textarea)) {
@@ -1175,7 +1181,8 @@ IMEStateManager::SetInputContext(nsIWidget* aWidget,
MOZ_LOG(sISMLog, LogLevel::Info,
("SetInputContext(aWidget=0x%p, aInputContext={ "
"mIMEState={ mEnabled=%s, mOpen=%s }, mHTMLInputType=\"%s\", "
"mHTMLInputInputmode=\"%s\", mActionHint=\"%s\" }, "
"mHTMLInputInputmode=\"%s\", mActionHint=\"%s\", "
"mInPrivateBrowsing=%s }, "
"aAction={ mCause=%s, mAction=%s }), sActiveTabParent=0x%p",
aWidget,
GetIMEStateEnabledName(aInputContext.mIMEState.mEnabled),
@@ -1183,6 +1190,7 @@ IMEStateManager::SetInputContext(nsIWidget* aWidget,
NS_ConvertUTF16toUTF8(aInputContext.mHTMLInputType).get(),
NS_ConvertUTF16toUTF8(aInputContext.mHTMLInputInputmode).get(),
NS_ConvertUTF16toUTF8(aInputContext.mActionHint).get(),
GetBoolName(aInputContext.mInPrivateBrowsing),
GetActionCauseName(aAction.mCause),
GetActionFocusChangeName(aAction.mFocusChange),
sActiveTabParent.get()));
+1
View File
@@ -247,6 +247,7 @@ protected:
nsIContent* aContent,
InputContextAction aAction);
static void SetIMEState(const IMEState &aState,
nsPresContext* aPresContext,
nsIContent* aContent,
nsIWidget* aWidget,
InputContextAction aAction);
+4 -2
View File
@@ -3291,6 +3291,10 @@ BackgroundCursorChild::HandleResponse(
auto& responses =
const_cast<nsTArray<ObjectStoreCursorResponse>&>(aResponses);
// If a new cursor is created, we need to keep a reference to it until the
// ResultHelper creates a DOM Binding.
RefPtr<IDBCursor> newCursor;
for (ObjectStoreCursorResponse& response : responses) {
StructuredCloneReadInfo cloneReadInfo(Move(response.cloneInfo()));
cloneReadInfo.mDatabase = mTransaction->Database();
@@ -3300,8 +3304,6 @@ BackgroundCursorChild::HandleResponse(
nullptr,
cloneReadInfo.mFiles);
RefPtr<IDBCursor> newCursor;
if (mCursor) {
mCursor->Reset(Move(response.key()), Move(cloneReadInfo));
} else {
+15 -1
View File
@@ -555,7 +555,21 @@ permitsPort(const nsAString& aEnforcementScheme,
int32_t resourcePort;
nsresult rv = aResourceURI->GetPort(&resourcePort);
NS_ENSURE_SUCCESS(rv, false);
if (NS_FAILED(rv) && aEnforcementPort.IsEmpty()) {
// If we cannot get a Port (e.g. because of an Custom Protocol handler)
// we need to check if a default port is associated with the Scheme
if (aEnforcementScheme.IsEmpty()) {
return false;
}
int defaultPortforScheme =
NS_GetDefaultPort(NS_ConvertUTF16toUTF8(aEnforcementScheme).get());
// If there is no default port associated with the Scheme (
// defaultPortforScheme == -1) or it is an externally handled protocol (
// defaultPortforScheme == 0 ) and the csp does not enforce a port - we can
// allow not having a port
return (defaultPortforScheme == -1 || defaultPortforScheme == 0);
}
// Avoid unnecessary string creation/manipulation and don't block the
// load if the resource to be loaded uses the default port for that
+4 -1
View File
@@ -530,8 +530,11 @@ nsHttpNegotiateAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChanne
challenge++;
len = strlen(challenge);
if (!len)
return NS_ERROR_UNEXPECTED;
// strip off any padding (see bug 230351)
while (challenge[len - 1] == '=')
while (len && challenge[len - 1] == '=')
len--;
//
+8
View File
@@ -555,6 +555,14 @@ void
BufferTextureHost::DeallocateDeviceData()
{
if (mFirstSource && mFirstSource->NumCompositableRefs() > 0) {
// WrappingTextureSourceYCbCrBasic wraps YUV format BufferTextureHost.
// When BufferTextureHost is destroyed, data of
// WrappingTextureSourceYCbCrBasic becomes invalid.
if (mFirstSource->AsWrappingTextureSourceYCbCrBasic() &&
mFirstSource->IsOwnedBy(this)) {
mFirstSource->SetOwner(nullptr);
mFirstSource->DeallocateDeviceData();
}
return;
}
+1
View File
@@ -712,6 +712,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
if (Omnijar::IsInitialized()) {
// Make sure that child processes can find the omnijar
// See XRE_InitCommandLine in nsAppRunner.cpp
newEnvVars["UXP_CUSTOM_OMNI"] = 1;
nsAutoCString path;
nsCOMPtr<nsIFile> file = Omnijar::GetPath(Omnijar::GRE);
if (file && NS_SUCCEEDED(file->GetNativePath(path))) {
+7 -7
View File
@@ -274,6 +274,12 @@ class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase<T>
T* unsafeGet() { return &ptr; }
void set(const T& newPtr) {
T tmp = ptr;
ptr = newPtr;
post(tmp, ptr);
}
explicit operator bool() const {
return bool(js::BarrierMethods<T>::asGCThingOrNull(ptr));
}
@@ -287,12 +293,6 @@ class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase<T>
post(GCPolicy<T>::initial(), ptr);
}
void set(const T& newPtr) {
T tmp = ptr;
ptr = newPtr;
post(tmp, ptr);
}
void post(const T& prev, const T& next) {
js::BarrierMethods<T>::postBarrier(&ptr, prev, next);
}
@@ -1172,13 +1172,13 @@ class PersistentRooted : public js::PersistentRootedBase<T>,
return ptr;
}
private:
template <typename U>
void set(U&& value) {
MOZ_ASSERT(initialized());
ptr = mozilla::Forward<U>(value);
}
private:
// See the comment above Rooted::ptr.
using MaybeWrapped = typename mozilla::Conditional<
MapTypeToRootKind<T>::kind == JS::RootKind::Traceable,
+32 -59
View File
@@ -399,25 +399,21 @@ class MOZ_NON_PARAM alignas(8) Value
data.asBits = bitsFromTagAndPayload(JSVAL_TAG_MAGIC, payload);
}
bool setNumber(uint32_t ui) {
void setNumber(uint32_t ui) {
if (ui > JSVAL_INT_MAX) {
setDouble((double)ui);
return false;
} else {
setInt32((int32_t)ui);
return true;
}
}
bool setNumber(double d) {
void setNumber(double d) {
int32_t i;
if (mozilla::NumberIsInt32(d, &i)) {
setInt32(i);
return true;
} else {
setDouble(d);
}
setDouble(d);
return false;
}
void setObjectOrNull(JSObject* arg) {
@@ -1406,25 +1402,29 @@ class ValueOperations
template <class Outer>
class MutableValueOperations : public ValueOperations<Outer>
{
JS::Value& value() { return static_cast<Outer*>(this)->get(); }
protected:
void set(const JS::Value& v) {
// Call Outer::set to trigger any barriers.
static_cast<Outer*>(this)->set(v);
}
public:
void setNull() { value().setNull(); }
void setUndefined() { value().setUndefined(); }
void setInt32(int32_t i) { value().setInt32(i); }
void setDouble(double d) { value().setDouble(d); }
void setNull() { set(JS::NullValue()); }
void setUndefined() { set(JS::UndefinedValue()); }
void setInt32(int32_t i) { set(JS::Int32Value(i)); }
void setDouble(double d) { set(JS::DoubleValue(d)); }
void setNaN() { setDouble(JS::GenericNaN()); }
void setBoolean(bool b) { value().setBoolean(b); }
void setMagic(JSWhyMagic why) { value().setMagic(why); }
bool setNumber(uint32_t ui) { return value().setNumber(ui); }
bool setNumber(double d) { return value().setNumber(d); }
void setString(JSString* str) { this->value().setString(str); }
void setSymbol(JS::Symbol* sym) { this->value().setSymbol(sym); }
void setObject(JSObject& obj) { this->value().setObject(obj); }
void setObjectOrNull(JSObject* arg) { this->value().setObjectOrNull(arg); }
void setPrivate(void* ptr) { this->value().setPrivate(ptr); }
void setPrivateUint32(uint32_t ui) { this->value().setPrivateUint32(ui); }
void setPrivateGCThing(js::gc::Cell* cell) { this->value().setPrivateGCThing(cell); }
void setBoolean(bool b) { set(JS::BooleanValue(b)); }
void setMagic(JSWhyMagic why) { set(JS::MagicValue(why)); }
void setNumber(uint32_t ui) { set(JS::NumberValue(ui)); }
void setNumber(double d) { set(JS::NumberValue(d)); }
void setString(JSString* str) { set(JS::StringValue(str)); }
void setSymbol(JS::Symbol* sym) { set(JS::SymbolValue(sym)); }
void setObject(JSObject& obj) { set(JS::ObjectValue(obj)); }
void setObjectOrNull(JSObject* arg) { set(JS::ObjectOrNullValue(arg)); }
void setPrivate(void* ptr) { set(JS::PrivateValue(ptr)); }
void setPrivateUint32(uint32_t ui) { set(JS::PrivateUint32Value(ui)); }
void setPrivateGCThing(js::gc::Cell* cell) { set(JS::PrivateGCThingValue(cell)); }
};
/*
@@ -1432,55 +1432,28 @@ class MutableValueOperations : public ValueOperations<Outer>
* type-querying, value-extracting, and mutating operations.
*/
template <>
class HeapBase<JS::Value> : public ValueOperations<JS::Heap<JS::Value> >
class HeapBase<JS::Value> : public MutableValueOperations<JS::Heap<JS::Value> >
{
typedef JS::Heap<JS::Value> Outer;
friend class ValueOperations<Outer>;
void setBarriered(const JS::Value& v) {
*static_cast<JS::Heap<JS::Value>*>(this) = v;
}
public:
void setNull() { setBarriered(JS::NullValue()); }
void setUndefined() { setBarriered(JS::UndefinedValue()); }
void setInt32(int32_t i) { setBarriered(JS::Int32Value(i)); }
void setDouble(double d) { setBarriered(JS::DoubleValue(d)); }
void setNaN() { setDouble(JS::GenericNaN()); }
void setBoolean(bool b) { setBarriered(JS::BooleanValue(b)); }
void setMagic(JSWhyMagic why) { setBarriered(JS::MagicValue(why)); }
void setString(JSString* str) { setBarriered(JS::StringValue(str)); }
void setSymbol(JS::Symbol* sym) { setBarriered(JS::SymbolValue(sym)); }
void setObject(JSObject& obj) { setBarriered(JS::ObjectValue(obj)); }
void setPrivateGCThing(js::gc::Cell* cell) { setBarriered(JS::PrivateGCThingValue(cell)); }
bool setNumber(uint32_t ui) {
void setNumber(uint32_t ui) {
if (ui > JSVAL_INT_MAX) {
setDouble((double)ui);
return false;
this->setDouble((double)ui);
} else {
setInt32((int32_t)ui);
return true;
this->setInt32((int32_t)ui);
}
}
bool setNumber(double d) {
void setNumber(double d) {
int32_t i;
if (mozilla::NumberIsInt32(d, &i)) {
setInt32(i);
return true;
this->setInt32(i);
} else {
this->setDouble(d);
}
setDouble(d);
return false;
}
void setObjectOrNull(JSObject* arg) {
if (arg)
setObject(*arg);
else
setNull();
}
};
+3 -3
View File
@@ -3900,10 +3900,10 @@ ConvertRegExpTreeToObject(JSContext* cx, irregexp::RegExpTree* tree)
return nullptr;
return obj;
}
if (tree->IsLookaround()) {
if (!StringProp(cx, obj, "type", "Lookaround"))
if (tree->IsLookahead()) {
if (!StringProp(cx, obj, "type", "Lookahead"))
return nullptr;
irregexp::RegExpLookaround* t = tree->AsLookaround();
irregexp::RegExpLookahead* t = tree->AsLookahead();
if (!BooleanProp(cx, obj, "is_positive", t->is_positive()))
return nullptr;
if (!TreeProp(cx, obj, "body", t->body()))
@@ -582,7 +582,7 @@ NativeRegExpMacroAssembler::CheckAtStart(Label* on_at_start)
}
void
NativeRegExpMacroAssembler::CheckNotAtStart(int cp_offset, Label* on_not_at_start)
NativeRegExpMacroAssembler::CheckNotAtStart(Label* on_not_at_start)
{
JitSpew(SPEW_PREFIX "CheckNotAtStart");
@@ -673,7 +673,7 @@ NativeRegExpMacroAssembler::CheckGreedyLoop(Label* on_tos_equals_current_positio
}
void
NativeRegExpMacroAssembler::CheckNotBackReference(int start_reg, bool read_backward, Label* on_no_match)
NativeRegExpMacroAssembler::CheckNotBackReference(int start_reg, Label* on_no_match)
{
JitSpew(SPEW_PREFIX "CheckNotBackReference(%d)", start_reg);
@@ -744,8 +744,8 @@ NativeRegExpMacroAssembler::CheckNotBackReference(int start_reg, bool read_backw
}
void
NativeRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(int start_reg, bool read_backward,
Label* on_no_match, bool unicode)
NativeRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(int start_reg, Label* on_no_match,
bool unicode)
{
JitSpew(SPEW_PREFIX "CheckNotBackReferenceIgnoreCase(%d, %d)", start_reg, unicode);
+3 -4
View File
@@ -105,10 +105,9 @@ class MOZ_STACK_CLASS NativeRegExpMacroAssembler final : public RegExpMacroAssem
void CheckCharacterGT(char16_t limit, jit::Label* on_greater);
void CheckCharacterLT(char16_t limit, jit::Label* on_less);
void CheckGreedyLoop(jit::Label* on_tos_equals_current_position);
void CheckNotAtStart(int cp_offset, jit::Label* on_not_at_start);
void CheckNotBackReference(int start_reg, bool read_backward, jit::Label* on_no_match);
void CheckNotBackReferenceIgnoreCase(int start_reg, bool read_backward,
jit::Label* on_no_match, bool unicode);
void CheckNotAtStart(jit::Label* on_not_at_start);
void CheckNotBackReference(int start_reg, jit::Label* on_no_match);
void CheckNotBackReferenceIgnoreCase(int start_reg, jit::Label* on_no_match, bool unicode);
void CheckNotCharacter(unsigned c, jit::Label* on_not_equal);
void CheckNotCharacterAfterAnd(unsigned c, unsigned and_with, jit::Label* on_not_equal);
void CheckNotCharacterAfterMinusAnd(char16_t c, char16_t minus, char16_t and_with,
+4 -4
View File
@@ -250,16 +250,16 @@ RegExpCapture::CaptureRegisters()
}
// ----------------------------------------------------------------------------
// RegExpLookaround
// RegExpLookahead
Interval
RegExpLookaround::CaptureRegisters()
RegExpLookahead::CaptureRegisters()
{
return body()->CaptureRegisters();
}
bool
RegExpLookaround::IsAnchoredAtStart()
RegExpLookahead::IsAnchoredAtStart()
{
return is_positive() && type() == LOOKAHEAD && body()->IsAnchoredAtStart();
return is_positive() && body()->IsAnchoredAtStart();
}
+10 -23
View File
@@ -360,7 +360,6 @@ class RegExpCapture : public RegExpTree
virtual int min_match() { return body_->min_match(); }
virtual int max_match() { return body_->max_match(); }
RegExpTree* body() { return body_; }
void set_body(RegExpTree* body) { body_ = body; }
int index() { return index_; }
static int StartRegister(int index) { return index * 2; }
static int EndRegister(int index) { return index * 2 + 1; }
@@ -370,29 +369,25 @@ class RegExpCapture : public RegExpTree
int index_;
};
class RegExpLookaround : public RegExpTree
class RegExpLookahead : public RegExpTree
{
public:
enum Type { LOOKAHEAD, LOOKBEHIND };
RegExpLookaround(RegExpTree* body,
bool is_positive,
int capture_count,
int capture_from,
Type type)
RegExpLookahead(RegExpTree* body,
bool is_positive,
int capture_count,
int capture_from)
: body_(body),
is_positive_(is_positive),
capture_count_(capture_count),
capture_from_(capture_from),
type_(type)
capture_from_(capture_from)
{}
virtual void* Accept(RegExpVisitor* visitor, void* data);
virtual RegExpNode* ToNode(RegExpCompiler* compiler,
RegExpNode* on_success);
virtual RegExpLookaround* AsLookaround();
virtual RegExpLookahead* AsLookahead();
virtual Interval CaptureRegisters();
virtual bool IsLookaround();
virtual bool IsLookahead();
virtual bool IsAnchoredAtStart();
virtual int min_match() { return 0; }
virtual int max_match() { return 0; }
@@ -400,14 +395,12 @@ class RegExpLookaround : public RegExpTree
bool is_positive() { return is_positive_; }
int capture_count() { return capture_count_; }
int capture_from() { return capture_from_; }
Type type() { return type_; }
private:
RegExpTree* body_;
bool is_positive_;
int capture_count_;
int capture_from_;
Type type_;
};
typedef InfallibleVector<RegExpCapture*, 1> RegExpCaptureVector;
@@ -424,14 +417,8 @@ class RegExpBackReference : public RegExpTree
RegExpNode* on_success);
virtual RegExpBackReference* AsBackReference();
virtual bool IsBackReference();
virtual int min_match() override { return 0; }
// The capture may not be completely parsed yet, if the reference occurs
// before the capture. In the ordinary case, nothing has been captured yet,
// so the back reference must have the length 0. If the back reference is
// inside a lookbehind, effectively making it a forward reference, we return
virtual int max_match() override {
return capture_->body() ? capture_->max_match() : 0;
}
virtual int min_match() { return 0; }
virtual int max_match() { return capture_->max_match(); }
int index() { return capture_->index(); }
RegExpCapture* capture() { return capture_; }
private:
+10 -13
View File
@@ -82,19 +82,16 @@ V(CHECK_LT, 35, 8) /* bc8 pad8 uc16 addr32 */ \
V(CHECK_GT, 36, 8) /* bc8 pad8 uc16 addr32 */ \
V(CHECK_NOT_BACK_REF, 37, 8) /* bc8 reg_idx24 addr32 */ \
V(CHECK_NOT_BACK_REF_NO_CASE, 38, 8) /* bc8 reg_idx24 addr32 */ \
V(CHECK_NOT_BACK_REF_BACKWARD, 39, 8) /* bc8 reg_idx24 addr32 */ \
V(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD, 40, 8) /* bc8 reg_idx24 addr32 */ \
V(CHECK_NOT_REGS_EQUAL, 41, 12) /* bc8 regidx24 reg_idx32 addr32 */ \
V(CHECK_REGISTER_LT, 42, 12) /* bc8 reg_idx24 value32 addr32 */ \
V(CHECK_REGISTER_GE, 43, 12) /* bc8 reg_idx24 value32 addr32 */ \
V(CHECK_REGISTER_EQ_POS, 44, 8) /* bc8 reg_idx24 addr32 */ \
V(CHECK_AT_START, 45, 8) /* bc8 pad24 addr32 */ \
V(CHECK_NOT_AT_START, 46, 8) /* bc8 pad24 addr32 */ \
V(CHECK_GREEDY, 47, 8) /* bc8 pad24 addr32 */ \
V(ADVANCE_CP_AND_GOTO, 48, 8) /* bc8 offset24 addr32 */ \
V(SET_CURRENT_POSITION_FROM_END, 49, 4) /* bc8 idx24 */ \
V(CHECK_NOT_BACK_REF_NO_CASE_UNICODE, 50, 8) /* bc8 reg_idx24 addr32 */ \
V(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_UNICODE, 51, 8) /* bc8 reg_idx24 addr32 */
V(CHECK_NOT_REGS_EQUAL, 39, 12) /* bc8 regidx24 reg_idx32 addr32 */ \
V(CHECK_REGISTER_LT, 40, 12) /* bc8 reg_idx24 value32 addr32 */ \
V(CHECK_REGISTER_GE, 41, 12) /* bc8 reg_idx24 value32 addr32 */ \
V(CHECK_REGISTER_EQ_POS, 42, 8) /* bc8 reg_idx24 addr32 */ \
V(CHECK_AT_START, 43, 8) /* bc8 pad24 addr32 */ \
V(CHECK_NOT_AT_START, 44, 8) /* bc8 pad24 addr32 */ \
V(CHECK_GREEDY, 45, 8) /* bc8 pad24 addr32 */ \
V(ADVANCE_CP_AND_GOTO, 46, 8) /* bc8 offset24 addr32 */ \
V(SET_CURRENT_POSITION_FROM_END, 47, 4) /* bc8 idx24 */ \
V(CHECK_NOT_BACK_REF_NO_CASE_UNICODE, 48, 8) /* bc8 reg_idx24 addr32 */
#define DECLARE_BYTECODES(name, code, length) \
static const int BC_##name = code;
+55 -94
View File
@@ -721,8 +721,6 @@ ActionNode::EmptyMatchCheck(int start_register,
int
TextNode::EatsAtLeast(int still_to_find, int budget, bool not_at_start)
{
if (read_backward())
return 0;
int answer = Length();
if (answer >= still_to_find)
return answer;
@@ -738,7 +736,8 @@ TextNode::EatsAtLeast(int still_to_find, int budget, bool not_at_start)
int
TextNode::GreedyLoopTextLength()
{
return Length();
TextElement elm = elements()[elements().length() - 1];
return elm.cp_offset() + elm.length();
}
RegExpNode*
@@ -888,8 +887,6 @@ AssertionNode::FillInBMInfo(int offset, int budget, BoyerMooreLookahead* bm, boo
int
BackReferenceNode::EatsAtLeast(int still_to_find, int budget, bool not_at_start)
{
if (read_backward())
return 0;
if (budget <= 0)
return 0;
return on_success()->EatsAtLeast(still_to_find, budget - 1, not_at_start);
@@ -1581,9 +1578,6 @@ class irregexp::RegExpCompiler
current_expansion_factor_ = value;
}
bool read_backward() { return read_backward_; }
void set_read_backward(bool value) { read_backward_ = value; }
JSContext* cx() const { return cx_; }
LifoAlloc* alloc() const { return alloc_; }
@@ -1601,7 +1595,6 @@ class irregexp::RegExpCompiler
bool unicode_;
bool reg_exp_too_big_;
int current_expansion_factor_;
bool read_backward_;
FrequencyCollator frequency_collator_;
JSContext* cx_;
LifoAlloc* alloc_;
@@ -1631,7 +1624,6 @@ RegExpCompiler::RegExpCompiler(JSContext* cx, LifoAlloc* alloc, int capture_coun
unicode_(unicode),
reg_exp_too_big_(false),
current_expansion_factor_(1),
read_backward_(false),
frequency_collator_(),
cx_(cx),
alloc_(alloc)
@@ -1755,7 +1747,7 @@ irregexp::CompilePattern(JSContext* cx, RegExpShared* shared, RegExpCompileData*
// at the start of input.
ChoiceNode* first_step_node = alloc.newInfallible<ChoiceNode>(&alloc, 2);
RegExpNode* char_class =
alloc.newInfallible<TextNode>(alloc.newInfallible<RegExpCharacterClass>('*'), false, loop_node);
alloc.newInfallible<TextNode>(alloc.newInfallible<RegExpCharacterClass>('*'), loop_node);
first_step_node->AddAlternative(GuardedAlternative(captured_body));
first_step_node->AddAlternative(GuardedAlternative(char_class));
node = first_step_node;
@@ -1858,19 +1850,19 @@ RegExpAtom::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
TextElementVector* elms =
compiler->alloc()->newInfallible<TextElementVector>(*compiler->alloc());
elms->append(TextElement::Atom(this));
return compiler->alloc()->newInfallible<TextNode>(elms, compiler->read_backward(), on_success);
return compiler->alloc()->newInfallible<TextNode>(elms, on_success);
}
RegExpNode*
RegExpText::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
{
return compiler->alloc()->newInfallible<TextNode>(&elements_, compiler->read_backward(), on_success);
return compiler->alloc()->newInfallible<TextNode>(&elements_, on_success);
}
RegExpNode*
RegExpCharacterClass::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
{
return compiler->alloc()->newInfallible<TextNode>(this, compiler->read_backward(), on_success);
return compiler->alloc()->newInfallible<TextNode>(this, on_success);
}
RegExpNode*
@@ -2011,8 +2003,7 @@ RegExpQuantifier::ToNode(int min,
alternation->AddAlternative(GuardedAlternative(body->ToNode(compiler, answer)));
}
answer = alternation;
if (not_at_start && !compiler->read_backward())
alternation->set_not_at_start();
if (not_at_start) alternation->set_not_at_start();
}
return answer;
}
@@ -2024,9 +2015,8 @@ RegExpQuantifier::ToNode(int min,
int reg_ctr = needs_counter
? compiler->AllocateRegister()
: RegExpCompiler::kNoRegister;
LoopChoiceNode* center = alloc->newInfallible<LoopChoiceNode>(alloc, body->min_match() == 0,
compiler->read_backward());
if (not_at_start && !compiler->read_backward())
LoopChoiceNode* center = alloc->newInfallible<LoopChoiceNode>(alloc, body->min_match() == 0);
if (not_at_start)
center->set_not_at_start();
RegExpNode* loop_return = needs_counter
? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center))
@@ -2102,7 +2092,7 @@ RegExpAssertion::ToNode(RegExpCompiler* compiler,
CharacterRange::AddClassEscape(alloc, 'n', newline_ranges);
RegExpCharacterClass* newline_atom = alloc->newInfallible<RegExpCharacterClass>('n');
TextNode* newline_matcher =
alloc->newInfallible<TextNode>(newline_atom, false,
alloc->newInfallible<TextNode>(newline_atom,
ActionNode::PositiveSubmatchSuccess(stack_pointer_register,
position_register,
0, // No captures inside.
@@ -2134,7 +2124,6 @@ RegExpBackReference::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
{
return compiler->alloc()->newInfallible<BackReferenceNode>(RegExpCapture::StartRegister(index()),
RegExpCapture::EndRegister(index()),
compiler->read_backward(),
on_success);
}
@@ -2145,7 +2134,7 @@ RegExpEmpty::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
}
RegExpNode*
RegExpLookaround::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
RegExpLookahead::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
{
int stack_pointer_register = compiler->AllocateRegister();
int position_register = compiler->AllocateRegister();
@@ -2156,10 +2145,6 @@ RegExpLookaround::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
int register_start =
register_of_first_capture + capture_from_ * registers_per_capture;
RegExpNode* result;
bool was_reading_backward = compiler->read_backward();
compiler->set_read_backward(type() == LOOKBEHIND);
if (is_positive()) {
RegExpNode* bodyNode =
body()->ToNode(compiler,
@@ -2168,39 +2153,37 @@ RegExpLookaround::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
register_count,
register_start,
on_success));
result = ActionNode::BeginSubmatch(stack_pointer_register,
position_register,
bodyNode);
} else {
// We use a ChoiceNode for a negative lookahead because it has most of
// the characteristics we need. It has the body of the lookahead as its
// first alternative and the expression after the lookahead of the second
// alternative. If the first alternative succeeds then the
// NegativeSubmatchSuccess will unwind the stack including everything the
// choice node set up and backtrack. If the first alternative fails then
// the second alternative is tried, which is exactly the desired result
// for a negative lookahead. The NegativeLookaheadChoiceNode is a special
// ChoiceNode that knows to ignore the first exit when calculating quick
// checks.
LifoAlloc* alloc = compiler->alloc();
RegExpNode* success =
alloc->newInfallible<NegativeSubmatchSuccess>(alloc,
stack_pointer_register,
position_register,
register_count,
register_start);
GuardedAlternative body_alt(body()->ToNode(compiler, success));
ChoiceNode* choice_node =
alloc->newInfallible<NegativeLookaheadChoiceNode>(alloc, body_alt, GuardedAlternative(on_success));
result = ActionNode::BeginSubmatch(stack_pointer_register,
return ActionNode::BeginSubmatch(stack_pointer_register,
position_register,
choice_node);
bodyNode);
}
compiler->set_read_backward(was_reading_backward);
return result;
// We use a ChoiceNode for a negative lookahead because it has most of
// the characteristics we need. It has the body of the lookahead as its
// first alternative and the expression after the lookahead of the second
// alternative. If the first alternative succeeds then the
// NegativeSubmatchSuccess will unwind the stack including everything the
// choice node set up and backtrack. If the first alternative fails then
// the second alternative is tried, which is exactly the desired result
// for a negative lookahead. The NegativeLookaheadChoiceNode is a special
// ChoiceNode that knows to ignore the first exit when calculating quick
// checks.
LifoAlloc* alloc = compiler->alloc();
RegExpNode* success =
alloc->newInfallible<NegativeSubmatchSuccess>(alloc,
stack_pointer_register,
position_register,
register_count,
register_start);
GuardedAlternative body_alt(body()->ToNode(compiler, success));
ChoiceNode* choice_node =
alloc->newInfallible<NegativeLookaheadChoiceNode>(alloc, body_alt, GuardedAlternative(on_success));
return ActionNode::BeginSubmatch(stack_pointer_register,
position_register,
choice_node);
}
RegExpNode*
@@ -2215,14 +2198,8 @@ RegExpCapture::ToNode(RegExpTree* body,
RegExpCompiler* compiler,
RegExpNode* on_success)
{
MOZ_ASSERT(body);
int start_reg = RegExpCapture::StartRegister(index);
int end_reg = RegExpCapture::EndRegister(index);
if (compiler->read_backward()) {
// std::swap(start_reg, end_reg);
start_reg = RegExpCapture::EndRegister(index);
end_reg = RegExpCapture::StartRegister(index);
}
RegExpNode* store_end = ActionNode::StorePosition(end_reg, true, on_success);
RegExpNode* body_node = body->ToNode(compiler, store_end);
return ActionNode::StorePosition(start_reg, true, body_node);
@@ -2233,15 +2210,8 @@ RegExpAlternative::ToNode(RegExpCompiler* compiler, RegExpNode* on_success)
{
const RegExpTreeVector& children = nodes();
RegExpNode* current = on_success;
if (compiler->read_backward()) {
for (int i = 0; i < children.length(); i++) {
current = children[i]->ToNode(compiler, current);
}
} else {
for (int i = children.length() - 1; i >= 0; i--) {
current = children[i]->ToNode(compiler, current);
}
}
for (int i = children.length() - 1; i >= 0; i--)
current = children[i]->ToNode(compiler, current);
return current;
}
@@ -2794,6 +2764,7 @@ Trace::InvalidateCurrentCharacter()
void
Trace::AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler)
{
MOZ_ASSERT(by > 0);
// We don't have an instruction for shifting the current character register
// down or for using a shifted value for anything so lets just forget that
// we preloaded any characters into it.
@@ -3138,9 +3109,9 @@ AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace)
return;
}
if (trace->at_start() == Trace::UNKNOWN) {
assembler->CheckNotAtStart(trace->cp_offset(), trace->backtrack());
assembler->CheckNotAtStart(trace->backtrack());
Trace at_start_trace = *trace;
at_start_trace.set_at_start(Trace::TRUE_VALUE);
at_start_trace.set_at_start(true);
on_success()->Emit(compiler, &at_start_trace);
return;
}
@@ -3843,10 +3814,9 @@ TextNode::TextEmitPass(RegExpCompiler* compiler,
jit::Label* backtrack = trace->backtrack();
QuickCheckDetails* quick_check = trace->quick_check_performed();
int element_count = elements().length();
int backward_offset = read_backward() ? -Length() : 0;
for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) {
TextElement elm = elements()[i];
int cp_offset = trace->cp_offset() + elm.cp_offset() + backward_offset;
int cp_offset = trace->cp_offset() + elm.cp_offset();
if (elm.text_type() == TextElement::ATOM) {
const CharacterVector& quarks = elm.atom()->data();
for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) {
@@ -3874,12 +3844,11 @@ TextNode::TextEmitPass(RegExpCompiler* compiler,
break;
}
if (emit_function != nullptr) {
bool bounds_check = *checked_up_to < cp_offset + j || read_backward();
bool bound_checked = emit_function(compiler,
quarks[j],
backtrack,
cp_offset + j,
bounds_check,
*checked_up_to < cp_offset + j,
preloaded);
if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to);
}
@@ -3890,14 +3859,13 @@ TextNode::TextEmitPass(RegExpCompiler* compiler,
if (first_element_checked && i == 0) continue;
if (DeterminedAlready(quick_check, elm.cp_offset())) continue;
RegExpCharacterClass* cc = elm.char_class();
bool bounds_check = *checked_up_to < cp_offset || read_backward();
EmitCharClass(alloc(),
assembler,
cc,
ascii,
backtrack,
cp_offset,
bounds_check,
*checked_up_to < cp_offset,
preloaded);
UpdateBoundsCheck(cp_offset, checked_up_to);
}
@@ -3977,11 +3945,8 @@ TextNode::Emit(RegExpCompiler* compiler, Trace* trace)
}
Trace successor_trace(*trace);
// If we advance backward, we may end up at the start.
successor_trace.AdvanceCurrentPositionInTrace(
read_backward() ? -Length() : Length(), compiler);
successor_trace.set_at_start(read_backward() ? Trace::UNKNOWN
: Trace::FALSE_VALUE);
successor_trace.set_at_start(false);
successor_trace.AdvanceCurrentPositionInTrace(Length(), compiler);
RecursionCheck rc(compiler);
on_success()->Emit(compiler, &successor_trace);
}
@@ -4153,8 +4118,6 @@ ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler, int eats_at_lea
RegExpNode*
TextNode::GetSuccessorOfOmnivorousTextNode(RegExpCompiler* compiler)
{
if (read_backward()) return NULL;
if (elements().length() != 1)
return nullptr;
@@ -4202,7 +4165,7 @@ ChoiceNode::GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative)
SeqRegExpNode* seq_node = static_cast<SeqRegExpNode*>(node);
node = seq_node->on_success();
}
return read_backward() ? -length : length;
return length;
}
// Creates a list of AlternativeGenerations. If the list has a reasonable
@@ -4277,7 +4240,7 @@ ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace)
jit::Label greedy_loop_label;
Trace counter_backtrack_trace;
counter_backtrack_trace.set_backtrack(&greedy_loop_label);
if (not_at_start()) counter_backtrack_trace.set_at_start(Trace::FALSE_VALUE);
if (not_at_start()) counter_backtrack_trace.set_at_start(false);
if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) {
// Here we have special handling for greedy loops containing only text nodes
@@ -4293,7 +4256,7 @@ ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace)
current_trace = &counter_backtrack_trace;
jit::Label greedy_match_failed;
Trace greedy_match_trace;
if (not_at_start()) greedy_match_trace.set_at_start(Trace::FALSE_VALUE);
if (not_at_start()) greedy_match_trace.set_at_start(false);
greedy_match_trace.set_backtrack(&greedy_match_failed);
jit::Label loop_label;
macro_assembler->Bind(&loop_label);
@@ -4642,14 +4605,11 @@ BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace)
MOZ_ASSERT(start_reg_ + 1 == end_reg_);
if (compiler->ignore_case()) {
assembler->CheckNotBackReferenceIgnoreCase(start_reg_,
read_backward(),
trace->backtrack(),
compiler->unicode());
} else {
assembler->CheckNotBackReference(start_reg_, read_backward(), trace->backtrack());
assembler->CheckNotBackReference(start_reg_, trace->backtrack());
}
// We are going to advance backward, so we may end up at the start.
if (read_backward()) trace->set_at_start(Trace::UNKNOWN);
on_success()->Emit(compiler, trace);
}
@@ -5017,6 +4977,7 @@ QuickCheckDetails::Clear()
void
QuickCheckDetails::Advance(int by, bool ascii)
{
MOZ_ASSERT(by >= 0);
if (by >= characters_) {
Clear();
return;
+8 -23
View File
@@ -119,7 +119,7 @@ InterpretCode(JSContext* cx, const uint8_t* byteCode, const CharT* chars, size_t
VISIT(Atom) \
VISIT(Quantifier) \
VISIT(Capture) \
VISIT(Lookaround) \
VISIT(Lookahead) \
VISIT(BackReference) \
VISIT(Empty) \
VISIT(Text)
@@ -763,19 +763,15 @@ class TextNode : public SeqRegExpNode
{
public:
TextNode(TextElementVector* elements,
bool read_backward,
RegExpNode* on_success)
: SeqRegExpNode(on_success),
elements_(elements),
read_backward_(read_backward)
elements_(elements)
{}
TextNode(RegExpCharacterClass* that,
bool read_backward,
RegExpNode* on_success)
: SeqRegExpNode(on_success),
elements_(alloc()->newInfallible<TextElementVector>(*alloc())),
read_backward_(read_backward)
elements_(alloc()->newInfallible<TextElementVector>(*alloc()))
{
elements_->append(TextElement::CharClass(that));
}
@@ -788,7 +784,6 @@ class TextNode : public SeqRegExpNode
int characters_filled_in,
bool not_at_start);
TextElementVector& elements() { return *elements_; }
bool read_backward() { return read_backward_; }
void MakeCaseIndependent(bool is_ascii, bool unicode);
virtual int GreedyLoopTextLength();
virtual RegExpNode* GetSuccessorOfOmnivorousTextNode(
@@ -819,7 +814,6 @@ class TextNode : public SeqRegExpNode
int* checked_up_to);
int Length();
TextElementVector* elements_;
bool read_backward_;
};
class AssertionNode : public SeqRegExpNode
@@ -888,18 +882,15 @@ class BackReferenceNode : public SeqRegExpNode
public:
BackReferenceNode(int start_reg,
int end_reg,
bool read_backward,
RegExpNode* on_success)
: SeqRegExpNode(on_success),
start_reg_(start_reg),
end_reg_(end_reg),
read_backward_(read_backward)
end_reg_(end_reg)
{}
virtual void Accept(NodeVisitor* visitor);
int start_register() { return start_reg_; }
int end_register() { return end_reg_; }
bool read_backward() { return read_backward_; }
virtual void Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int still_to_find,
int recursion_depth,
@@ -918,7 +909,6 @@ class BackReferenceNode : public SeqRegExpNode
private:
int start_reg_;
int end_reg_;
bool read_backward_;
};
class EndNode : public RegExpNode
@@ -1063,7 +1053,6 @@ class ChoiceNode : public RegExpNode
void set_being_calculated(bool b) { being_calculated_ = b; }
virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; }
virtual RegExpNode* FilterASCII(int depth, bool ignore_case, bool unicode);
virtual bool read_backward() { return false; }
protected:
int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative);
@@ -1122,13 +1111,11 @@ class NegativeLookaheadChoiceNode : public ChoiceNode
class LoopChoiceNode : public ChoiceNode
{
public:
explicit LoopChoiceNode(LifoAlloc* alloc, bool body_can_be_zero_length,
bool read_backward)
explicit LoopChoiceNode(LifoAlloc* alloc, bool body_can_be_zero_length)
: ChoiceNode(alloc, 2),
loop_node_(nullptr),
continue_node_(nullptr),
body_can_be_zero_length_(body_can_be_zero_length),
read_backward_(read_backward)
body_can_be_zero_length_(body_can_be_zero_length)
{}
void AddLoopAlternative(GuardedAlternative alt);
@@ -1146,7 +1133,6 @@ class LoopChoiceNode : public ChoiceNode
RegExpNode* loop_node() { return loop_node_; }
RegExpNode* continue_node() { return continue_node_; }
bool body_can_be_zero_length() { return body_can_be_zero_length_; }
virtual bool read_backward() { return read_backward_; }
virtual void Accept(NodeVisitor* visitor);
virtual RegExpNode* FilterASCII(int depth, bool ignore_case, bool unicode);
@@ -1161,7 +1147,6 @@ class LoopChoiceNode : public ChoiceNode
RegExpNode* loop_node_;
RegExpNode* continue_node_;
bool body_can_be_zero_length_;
bool read_backward_;
};
// Improve the speed that we scan for an initial point where a non-anchored
@@ -1437,8 +1422,8 @@ class Trace
}
TriBool at_start() { return at_start_; }
void set_at_start(TriBool at_start) {
at_start_ = at_start;
void set_at_start(bool at_start) {
at_start_ = at_start ? TRUE_VALUE : FALSE_VALUE;
}
jit::Label* backtrack() { return backtrack_; }
jit::Label* loop_label() { return loop_label_; }
+5 -69
View File
@@ -222,8 +222,8 @@ irregexp::InterpretCode(JSContext* cx, const uint8_t* byteCode, const CharT* cha
}
break;
BYTECODE(LOAD_CURRENT_CHAR) {
int pos = current + (insn >> BYTECODE_SHIFT);
if (pos >= (int)length || pos < 0) {
size_t pos = current + (insn >> BYTECODE_SHIFT);
if (pos >= length) {
pc = byteCode + Load32Aligned(pc + 4);
} else {
current_char = chars[pos];
@@ -238,8 +238,8 @@ irregexp::InterpretCode(JSContext* cx, const uint8_t* byteCode, const CharT* cha
break;
}
BYTECODE(LOAD_2_CURRENT_CHARS) {
int pos = current + (insn >> BYTECODE_SHIFT);
if (pos + 2 > (int)length || pos < 0) {
size_t pos = current + (insn >> BYTECODE_SHIFT);
if (pos + 2 > length) {
pc = byteCode + Load32Aligned(pc + 4);
} else {
CharT next = chars[pos + 1];
@@ -425,30 +425,6 @@ irregexp::InterpretCode(JSContext* cx, const uint8_t* byteCode, const CharT* cha
pc += BC_CHECK_NOT_BACK_REF_LENGTH;
break;
}
BYTECODE(CHECK_NOT_BACK_REF_BACKWARD) {
int from = registers[insn >> BYTECODE_SHIFT];
int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
if (from < 0 || len <= 0) {
pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH;
break;
}
if (int(current) - len < 0) {
pc = byteCode + Load32Aligned(pc + 4);
break;
} else {
int i;
for (i = 0; i < len; i++) {
if (chars[from + i] != chars[int(current) - len + i]) {
pc = byteCode + Load32Aligned(pc + 4);
break;
}
}
if (i < len) break;
current -= len;
}
pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH;
break;
}
BYTECODE(CHECK_NOT_BACK_REF_NO_CASE) {
int from = registers[insn >> BYTECODE_SHIFT];
int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
@@ -489,46 +465,6 @@ irregexp::InterpretCode(JSContext* cx, const uint8_t* byteCode, const CharT* cha
}
break;
}
BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD) {
int from = registers[insn >> BYTECODE_SHIFT];
int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
if (from < 0 || len <= 0) {
pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
break;
}
if (int(current) - len < 0) {
pc = byteCode + Load32Aligned(pc + 4);
break;
}
if (CaseInsensitiveCompareStrings(chars + from, chars + int(current) - len, len * sizeof(CharT))) {
current -= len;
pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
} else {
pc = byteCode + Load32Aligned(pc + 4);
}
break;
}
BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_UNICODE) {
int from = registers[insn >> BYTECODE_SHIFT];
int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
if (from < 0 || len <= 0) {
pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
break;
}
if (int(current) - len < 0) {
pc = byteCode + Load32Aligned(pc + 4);
break;
}
if (CaseInsensitiveCompareUCStrings(chars + from, chars + int(current) - len, len * sizeof(CharT))) {
current -= len;
pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH;
} else {
pc = byteCode + Load32Aligned(pc + 4);
}
break;
}
BYTECODE(CHECK_AT_START)
if (current == 0)
pc = byteCode + Load32Aligned(pc + 4);
@@ -536,7 +472,7 @@ irregexp::InterpretCode(JSContext* cx, const uint8_t* byteCode, const CharT* cha
pc += BC_CHECK_AT_START_LENGTH;
break;
BYTECODE(CHECK_NOT_AT_START)
if (current + (insn >> BYTECODE_SHIFT) == 0)
if (current == 0)
pc += BC_CHECK_NOT_AT_START_LENGTH;
else
pc = byteCode + Load32Aligned(pc + 4);
+6 -11
View File
@@ -226,37 +226,32 @@ InterpretedRegExpMacroAssembler::CheckGreedyLoop(jit::Label* on_tos_equals_curre
}
void
InterpretedRegExpMacroAssembler::CheckNotAtStart(int cp_offset, jit::Label* on_not_at_start)
InterpretedRegExpMacroAssembler::CheckNotAtStart(jit::Label* on_not_at_start)
{
Emit(BC_CHECK_NOT_AT_START, cp_offset);
Emit(BC_CHECK_NOT_AT_START, 0);
EmitOrLink(on_not_at_start);
}
void
InterpretedRegExpMacroAssembler::CheckNotBackReference(int start_reg, bool read_backward,
jit::Label* on_no_match)
InterpretedRegExpMacroAssembler::CheckNotBackReference(int start_reg, jit::Label* on_no_match)
{
MOZ_ASSERT(start_reg >= 0);
MOZ_ASSERT(start_reg <= kMaxRegister);
Emit(read_backward ? BC_CHECK_NOT_BACK_REF_BACKWARD : BC_CHECK_NOT_BACK_REF,
start_reg);
Emit(BC_CHECK_NOT_BACK_REF, start_reg);
EmitOrLink(on_no_match);
}
void
InterpretedRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(int start_reg,
bool read_backward,
jit::Label* on_no_match,
bool unicode)
{
MOZ_ASSERT(start_reg >= 0);
MOZ_ASSERT(start_reg <= kMaxRegister);
if (unicode)
Emit(read_backward ? BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_UNICODE : BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE,
start_reg);
Emit(BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE, start_reg);
else
Emit(read_backward ? BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD : BC_CHECK_NOT_BACK_REF_NO_CASE,
start_reg);
Emit(BC_CHECK_NOT_BACK_REF_NO_CASE, start_reg);
EmitOrLink(on_no_match);
}
+7 -8
View File
@@ -110,10 +110,10 @@ class MOZ_STACK_CLASS RegExpMacroAssembler
virtual void CheckCharacterGT(char16_t limit, jit::Label* on_greater) = 0;
virtual void CheckCharacterLT(char16_t limit, jit::Label* on_less) = 0;
virtual void CheckGreedyLoop(jit::Label* on_tos_equals_current_position) = 0;
virtual void CheckNotAtStart(int cp_offset, jit::Label* on_not_at_start) = 0;
virtual void CheckNotBackReference(int start_reg, bool read_backward, jit::Label* on_no_match) = 0;
virtual void CheckNotBackReferenceIgnoreCase(int start_reg, bool read_backward,
jit::Label* on_no_match, bool unicode) = 0;
virtual void CheckNotAtStart(jit::Label* on_not_at_start) = 0;
virtual void CheckNotBackReference(int start_reg, jit::Label* on_no_match) = 0;
virtual void CheckNotBackReferenceIgnoreCase(int start_reg, jit::Label* on_no_match,
bool unicode) = 0;
// Check the current character for a match with a literal character. If we
// fail to match then goto the on_failure label. End of input always
@@ -245,10 +245,9 @@ class MOZ_STACK_CLASS InterpretedRegExpMacroAssembler final : public RegExpMacro
void CheckCharacterGT(char16_t limit, jit::Label* on_greater);
void CheckCharacterLT(char16_t limit, jit::Label* on_less);
void CheckGreedyLoop(jit::Label* on_tos_equals_current_position);
void CheckNotAtStart(int cp_offset, jit::Label* on_not_at_start);
void CheckNotBackReference(int start_reg, bool read_backward, jit::Label* on_no_match);
void CheckNotBackReferenceIgnoreCase(int start_reg, bool read_backward,
jit::Label* on_no_match, bool unicode);
void CheckNotAtStart(jit::Label* on_not_at_start);
void CheckNotBackReference(int start_reg, jit::Label* on_no_match);
void CheckNotBackReferenceIgnoreCase(int start_reg, jit::Label* on_no_match, bool unicode);
void CheckNotCharacter(unsigned c, jit::Label* on_not_equal);
void CheckNotCharacterAfterAnd(unsigned c, unsigned and_with, jit::Label* on_not_equal);
void CheckNotCharacterAfterMinusAnd(char16_t c, char16_t minus, char16_t and_with,
+41 -89
View File
@@ -227,7 +227,6 @@ RegExpParser<CharT>::RegExpParser(frontend::TokenStream& ts, LifoAlloc* alloc,
alloc(alloc),
captures_(nullptr),
next_pos_(chars),
captures_started_(0),
end_(end),
current_(kEndMarker),
capture_count_(0),
@@ -420,8 +419,7 @@ RangeAtom(LifoAlloc* alloc, char16_t from, char16_t to)
static inline RegExpTree*
NegativeLookahead(LifoAlloc* alloc, char16_t from, char16_t to)
{
return alloc->newInfallible<RegExpLookaround>(RangeAtom(alloc, from, to), false,
0, 0, RegExpLookaround::LOOKAHEAD);
return alloc->newInfallible<RegExpLookahead>(RangeAtom(alloc, from, to), false, 0, 0);
}
static bool
@@ -1216,38 +1214,6 @@ RegExpParser<CharT>::ParseBackReferenceIndex(int* index_out)
return true;
}
template <typename CharT>
RegExpCapture*
RegExpParser<CharT>::GetCapture(int index) {
// The index for the capture groups are one-based. Its index in the list is
// zero-based.
int known_captures =
is_scanned_for_captures_ ? capture_count_ : captures_started_;
MOZ_ASSERT(index <= known_captures);
if (captures_ == NULL) {
captures_ = alloc->newInfallible<RegExpCaptureVector>(*alloc);
}
while ((int)captures_->length() < known_captures) {
RegExpCapture* capture = alloc->newInfallible<RegExpCapture>(nullptr, captures_->length() + 1);
captures_->append(capture);
}
return (*captures_)[index - 1];
}
template <typename CharT>
bool
RegExpParser<CharT>::RegExpParserState::IsInsideCaptureGroup(int index) {
for (RegExpParserState* s = this; s != NULL; s = s->previous_state()) {
if (s->group_type() != CAPTURE) continue;
// Return true if we found the matching capture index.
if (index == s->capture_index()) return true;
// Abort if index is larger than what has been parsed up till this state.
if (index > s->capture_index()) return false;
}
return false;
}
// QuantifierPrefix ::
// { DecimalDigits }
// { DecimalDigits , }
@@ -1490,24 +1456,24 @@ RegExpTree*
RegExpParser<CharT>::ParseDisjunction()
{
// Used to store current state while parsing subexpressions.
RegExpParserState initial_state(alloc, nullptr, INITIAL, RegExpLookaround::LOOKAHEAD, 0);
RegExpParserState* state = &initial_state;
RegExpParserState initial_state(alloc, nullptr, INITIAL, 0);
RegExpParserState* stored_state = &initial_state;
// Cache the builder in a local variable for quick access.
RegExpBuilder* builder = initial_state.builder();
while (true) {
switch (current()) {
case kEndMarker:
if (state->IsSubexpression()) {
if (stored_state->IsSubexpression()) {
// Inside a parenthesized group when hitting end of input.
return ReportError(JSMSG_MISSING_PAREN);
}
MOZ_ASSERT(INITIAL == state->group_type());
MOZ_ASSERT(INITIAL == stored_state->group_type());
// Parsing completed successfully.
return builder->ToRegExp();
case ')': {
if (!state->IsSubexpression())
if (!stored_state->IsSubexpression())
return ReportError(JSMSG_UNMATCHED_RIGHT_PAREN);
MOZ_ASSERT(INITIAL != state->group_type());
MOZ_ASSERT(INITIAL != stored_state->group_type());
Advance();
// End disjunction parsing and convert builder content to new single
@@ -1516,30 +1482,29 @@ RegExpParser<CharT>::ParseDisjunction()
int end_capture_index = captures_started();
int capture_index = state->capture_index();
SubexpressionType group_type = state->group_type();
int capture_index = stored_state->capture_index();
SubexpressionType group_type = stored_state->group_type();
// Restore previous state.
stored_state = stored_state->previous_state();
builder = stored_state->builder();
// Build result of subexpression.
if (group_type == CAPTURE) {
RegExpCapture* capture = GetCapture(capture_index);
capture->set_body(body);
RegExpCapture* capture = alloc->newInfallible<RegExpCapture>(body, capture_index);
(*captures_)[capture_index - 1] = capture;
body = capture;
} else if (group_type != GROUPING) {
MOZ_ASSERT(group_type == POSITIVE_LOOKAROUND ||
group_type == NEGATIVE_LOOKAROUND);
bool is_positive = (group_type == POSITIVE_LOOKAROUND);
body = alloc->newInfallible<RegExpLookaround>(body,
MOZ_ASSERT(group_type == POSITIVE_LOOKAHEAD ||
group_type == NEGATIVE_LOOKAHEAD);
bool is_positive = (group_type == POSITIVE_LOOKAHEAD);
body = alloc->newInfallible<RegExpLookahead>(body,
is_positive,
end_capture_index - capture_index,
capture_index,
state->lookaround_type());
capture_index);
}
// Restore previous state.
state = state->previous_state();
builder = state->builder();
builder->AddAtom(body);
if (unicode_ && (group_type == POSITIVE_LOOKAROUND || group_type == NEGATIVE_LOOKAROUND))
if (unicode_ && (group_type == POSITIVE_LOOKAHEAD || group_type == NEGATIVE_LOOKAHEAD))
continue;
// For compatability with JSC and ES3, we allow quantifiers after
// lookaheads, and break in all cases.
@@ -1599,7 +1564,6 @@ RegExpParser<CharT>::ParseDisjunction()
}
case '(': {
SubexpressionType subexpr_type = CAPTURE;
RegExpLookaround::Type lookaround_type = state->lookaround_type();
Advance();
if (current() == '?') {
switch (Next()) {
@@ -1607,39 +1571,26 @@ RegExpParser<CharT>::ParseDisjunction()
subexpr_type = GROUPING;
break;
case '=':
lookaround_type = RegExpLookaround::LOOKAHEAD;
subexpr_type = POSITIVE_LOOKAROUND;
subexpr_type = POSITIVE_LOOKAHEAD;
break;
case '!':
lookaround_type = RegExpLookaround::LOOKAHEAD;
subexpr_type = NEGATIVE_LOOKAROUND;
subexpr_type = NEGATIVE_LOOKAHEAD;
break;
case '<':
Advance();
lookaround_type = RegExpLookaround::LOOKBEHIND;
if (Next() == '=') {
subexpr_type = POSITIVE_LOOKAROUND;
break;
} else if (Next() == '!') {
subexpr_type = NEGATIVE_LOOKAROUND;
break;
}
// We didn't get a positive or negative after '<'.
// That's an error.
return ReportError(JSMSG_INVALID_GROUP);
default:
return ReportError(JSMSG_INVALID_GROUP);
}
Advance(2);
} else {
if (captures_ == nullptr)
captures_ = alloc->newInfallible<RegExpCaptureVector>(*alloc);
if (captures_started() >= kMaxCaptures)
return ReportError(JSMSG_TOO_MANY_PARENS);
captures_started_++;
captures_->append((RegExpCapture*) nullptr);
}
// Store current state and begin new disjunction parsing.
state = alloc->newInfallible<RegExpParserState>(alloc, state, subexpr_type,
lookaround_type, captures_started_);
builder = state->builder();
stored_state = alloc->newInfallible<RegExpParserState>(alloc, stored_state, subexpr_type,
captures_started());
builder = stored_state->builder();
continue;
}
case '[': {
@@ -1694,18 +1645,19 @@ RegExpParser<CharT>::ParseDisjunction()
case '7': case '8': case '9': {
int index = 0;
if (ParseBackReferenceIndex(&index)) {
if (state->IsInsideCaptureGroup(index)) {
// The backreference is inside the capture group it refers to.
// Nothing can possibly have been captured yet.
builder->AddEmpty();
} else {
RegExpCapture* capture = GetCapture(index);
RegExpTree* atom = alloc->newInfallible<RegExpBackReference>(capture);
if (unicode_)
builder->AddAtom(UnicodeBackReferenceAtom(alloc, atom));
else
builder->AddAtom(atom);
RegExpCapture* capture = nullptr;
if (captures_ != nullptr && index <= (int) captures_->length()) {
capture = (*captures_)[index - 1];
}
if (capture == nullptr) {
builder->AddEmpty();
break;
}
RegExpTree* atom = alloc->newInfallible<RegExpBackReference>(capture);
if (unicode_)
builder->AddAtom(UnicodeBackReferenceAtom(alloc, atom));
else
builder->AddAtom(atom);
break;
}
if (unicode_)
+3 -16
View File
@@ -229,7 +229,7 @@ class RegExpParser
bool simple() { return simple_; }
bool contains_anchor() { return contains_anchor_; }
void set_contains_anchor() { contains_anchor_ = true; }
int captures_started() { return captures_started_; }
int captures_started() { return captures_ == nullptr ? 0 : captures_->length(); }
const CharT* position() { return next_pos_ - 1; }
static const int kMaxCaptures = 1 << 16;
@@ -239,8 +239,8 @@ class RegExpParser
enum SubexpressionType {
INITIAL,
CAPTURE, // All positive values represent captures.
POSITIVE_LOOKAROUND,
NEGATIVE_LOOKAROUND,
POSITIVE_LOOKAHEAD,
NEGATIVE_LOOKAHEAD,
GROUPING
};
@@ -249,12 +249,10 @@ class RegExpParser
RegExpParserState(LifoAlloc* alloc,
RegExpParserState* previous_state,
SubexpressionType group_type,
RegExpLookaround::Type lookaround_type,
int disjunction_capture_index)
: previous_state_(previous_state),
builder_(alloc->newInfallible<RegExpBuilder>(alloc)),
group_type_(group_type),
lookaround_type_(lookaround_type),
disjunction_capture_index_(disjunction_capture_index)
{}
// Parser state of containing expression, if any.
@@ -264,16 +262,11 @@ class RegExpParser
RegExpBuilder* builder() { return builder_; }
// Type of regexp being parsed (parenthesized group or entire regexp).
SubexpressionType group_type() { return group_type_; }
// Lookahead or Lookbehind.
RegExpLookaround::Type lookaround_type() { return lookaround_type_; }
// Index in captures array of first capture in this sub-expression, if any.
// Also the capture index of this sub-expression itself, if group_type
// is CAPTURE.
int capture_index() { return disjunction_capture_index_; }
// Check whether the parser is inside a capture group with the given index.
bool IsInsideCaptureGroup(int index);
private:
// Linked list implementation of stack of states.
RegExpParserState* previous_state_;
@@ -281,15 +274,10 @@ class RegExpParser
RegExpBuilder* builder_;
// Stored disjunction type (capture, look-ahead or grouping), if any.
SubexpressionType group_type_;
// Stored read direction.
RegExpLookaround::Type lookaround_type_;
// Stored disjunction's capture index (if any).
int disjunction_capture_index_;
};
// Return the 1-indexed RegExpCapture object, allocate if necessary.
RegExpCapture* GetCapture(int index);
widechar current() { return current_; }
bool has_more() { return has_more_; }
bool has_next() { return next_pos_ < end_; }
@@ -306,7 +294,6 @@ class RegExpParser
const CharT* next_pos_;
const CharT* end_;
widechar current_;
int captures_started_;
// The capture count is only valid after we have scanned for captures.
int capture_count_;
bool has_more_;
+2 -2
View File
@@ -86,8 +86,6 @@ GetObject(const MDefinition* ins)
case MDefinition::Op_SetInitializedLength:
case MDefinition::Op_ArrayLength:
case MDefinition::Op_SetArrayLength:
case MDefinition::Op_StoreElementHole:
case MDefinition::Op_FallibleStoreElement:
case MDefinition::Op_TypedObjectDescr:
case MDefinition::Op_Slots:
case MDefinition::Op_Elements:
@@ -143,6 +141,8 @@ GetObject(const MDefinition* ins)
case MDefinition::Op_WasmStoreGlobalVar:
case MDefinition::Op_ArrayJoin:
case MDefinition::Op_ArraySlice:
case MDefinition::Op_StoreElementHole:
case MDefinition::Op_FallibleStoreElement:
return nullptr;
default:
#ifdef DEBUG
-9
View File
@@ -9460,12 +9460,6 @@ class MStoreElementHole
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value))
AliasSet getAliasSet() const override {
// StoreElementHole can update the initialized length, the array length
// or reallocate obj->elements.
return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
}
ALLOW_CLONE(MStoreElementHole)
};
@@ -9496,9 +9490,6 @@ class MFallibleStoreElement
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value))
AliasSet getAliasSet() const override {
return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
}
bool strict() const {
return strict_;
}
+4 -1
View File
@@ -158,7 +158,10 @@ function setServerType()
var serverType = document.getElementById("servertype").value;
var deferStorageBox = document.getElementById("deferStorageBox");
var leaveMessages = document.getElementById("leaveMsgsOnSrvrBox");
var port = serverType == "pop3" ? 110 : 143;
// pop3 110 (unsecure) 995 (SSL)
// imap 143 (unsecure) 993 (SSL)
var port = serverType == "pop3" ? 995 : 993;
document.getElementById("serverPort").value = port;
document.getElementById("defaultPortValue").value = port;
+21 -5
View File
@@ -35,20 +35,36 @@ interface nsIMsgAsyncPrompter : nsISupports {
in nsIMsgAsyncPromptListener aCaller);
};
[scriptable, function, uuid(acca94c9-378e-46e3-9a91-6655bf9c91a3)]
interface nsIMsgAsyncPromptCallback : nsISupports {
/**
* Called when an auth result is available. Can be passed as a function.
*
* @param aResult True if there is auth information available following the
* prompt, false otherwise.
*/
void onAuthResult(in boolean aResult);
};
/**
* This is used in combination with nsIMsgAsyncPrompter.
*/
[scriptable, uuid(fb5307a3-39d0-462e-92c8-c5c288a2612f)]
interface nsIMsgAsyncPromptListener : nsISupports {
/**
* Called when the listener should do its prompt. The listener
* should not return until the prompt is complete.
*
* @return True if there is auth information available following the prompt,
* false otherwise.
* This method has been deprecated, please use onPromptStartAsync instead.
*/
boolean onPromptStart();
/**
* Called when the listener should do its prompt. This can happen
* synchronously or asynchronously, but in any case when done the callback
* method should be called.
*
* @param aCallback The callback to execute when auth prompt has completed.
*/
void onPromptStartAsync(in nsIMsgAsyncPromptCallback aCallback);
/**
* Called in the case that the queued prompt was combined with another and
* there is now authentication information available.
@@ -224,7 +224,7 @@
let identitiesRaw = MailServices.accounts
.getIdentitiesForServer(gFilterList.folder.server);
let identities = Array.from(this.fixIterator(identitiesRaw,
Ci.nsIMsgIdentity));
Components.interfaces.nsIMsgIdentity));
if (identities.length == 0) { // typically if this is Local Folders
if (MailServices.accounts.defaultAccount)
+26 -7
View File
@@ -2,6 +2,7 @@
* 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/. */
Components.utils.import("resource://gre/modules/Deprecated.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/Task.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
@@ -19,28 +20,46 @@ runnablePrompter.prototype = {
_asyncPrompter: null,
_hashKey: null,
_promiseAuthPrompt: function(listener) {
return new Promise((resolve, reject) => {
try {
listener.onPromptStartAsync({ onAuthResult: resolve });
} catch (e) {
if (e.result == Components.results.NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED) {
// Fall back to onPromptStart, for add-ons compat
Deprecated.warning("onPromptStart has been replaced by onPromptStartAsync",
"https://bugzilla.mozilla.org/show_bug.cgi?id=1176399");
let ok = listener.onPromptStart();
resolve(ok);
} else {
reject(e);
}
}
});
},
run: Task.async(function *() {
yield Services.logins.initializationPromise;
this._asyncPrompter._log.debug("Running prompt for " + this._hashKey);
let prompter = this._asyncPrompter._pendingPrompts[this._hashKey];
let ok = false;
try {
ok = prompter.first.onPromptStart();
}
catch (ex) {
ok = yield this._promiseAuthPrompt(prompter.first);
} catch (ex) {
Components.utils.reportError("runnablePrompter:run: " + ex + "\n");
prompter.first.onPromptCanceled();
}
delete this._asyncPrompter._pendingPrompts[this._hashKey];
for (var consumer of prompter.consumers) {
try {
if (ok)
if (ok) {
consumer.onPromptAuthAvailable();
else
} else {
consumer.onPromptCanceled();
}
catch (ex) {
}
} catch (ex) {
// Log the error for extension devs and others to pick up.
Components.utils.reportError("runnablePrompter:run: consumer.onPrompt* reported an exception: " + ex + "\n");
}
+33 -9
View File
@@ -126,19 +126,43 @@ OAuth2Module.prototype = {
}
}
// Otherwise, we need a new login, so create one and fill it in.
let login = Cc["@mozilla.org/login-manager/loginInfo;1"]
.createInstance(Ci.nsILoginInfo);
login.init(this._loginUrl, null, this._scope, this._username, token,
'', '');
loginMgr.addLogin(login);
// Unless the token is null, we need to create and fill in a new login
if (token) {
let login = Cc["@mozilla.org/login-manager/loginInfo;1"]
.createInstance(Ci.nsILoginInfo);
login.init(this._loginUrl, null, this._scope, this._username, token,
'', '');
loginMgr.addLogin(login);
}
return token;
},
connect(aWithUI, aListener) {
this._oauth.connect(() => aListener.onSuccess(this._oauth.accessToken),
x => aListener.onFailure(x),
aWithUI, false);
let oauth = this._oauth;
let promptlistener = {
onPromptStartAsync: function(callback) {
oauth.connect(() => {
this.onPromptAuthAvailable();
callback.onAuthResult(true);
}, (err) => {
this.onPromptCanceled();
callback.onAuthResult(false);
}, aWithUI, false);
},
onPromptAuthAvailable: function() {
aListener.onSuccess(oauth.accessToken);
},
onPromptCanceled: function() {
aListener.onFailure(Components.results.NS_ERROR_ABORT);
},
onPromptStart: function() {}
};
let asyncprompter = Components.classes["@mozilla.org/messenger/msgAsyncPrompter;1"]
.getService(Components.interfaces.nsIMsgAsyncPrompter);
let promptkey = this._loginUrl + "/" + this._username;
asyncprompter.queueAsyncAuthPrompt(promptkey, false, promptlistener);
},
buildXOAuth2String() {
+101 -70
View File
@@ -3,30 +3,37 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Provides OAuth 2.0 authentication
* Provides OAuth 2.0 authentication.
* @see RFC 6749
*/
var EXPORTED_SYMBOLS = ["OAuth2"];
var {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
Cu.import("resource://gre/modules/Http.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/gloda/log4moz.js");
function parseURLData(aData) {
let result = {};
aData.split(/[?#]/, 2)[1].split("&").forEach(function (aParam) {
let [key, value] = aParam.split("=");
result[key] = decodeURIComponent(value);
});
return result;
}
Cu.importGlobalProperties(["fetch"]);
// Only allow one connecting window per endpoint.
var gConnecting = {};
function OAuth2(aBaseURI, aScope, aAppKey, aAppSecret) {
/**
* Constructor for the OAuth2 object.
*
* @constructor
* @param {string} aBaseURI - The base URI for authentication and token
* requests, oauth2/auth or oauth2/token will be added for the actual
* requests.
* @param {?string} aScope - The scope as specified by RFC 6749 Section 3.3.
* Will not be included in the requests if falsy.
* @param {string} aAppKey - The client_id as specified by RFC 6749 Section
* 2.3.1.
* @param {string} [aAppSecret=null] - The client_secret as specified in
* RFC 6749 section 2.3.1. Will not be included in the requests if null.
*/
function OAuth2(aBaseURI, aScope, aAppKey, aAppSecret = null) {
this.authURI = aBaseURI + "oauth2/auth";
this.tokenURI = aBaseURI + "oauth2/token";
this.consumerKey = aAppKey;
@@ -37,12 +44,7 @@ function OAuth2(aBaseURI, aScope, aAppKey, aAppSecret) {
this.log = Log4Moz.getConfiguredLogger("TBOAuth");
}
OAuth2.CODE_AUTHORIZATION = "authorization_code";
OAuth2.CODE_REFRESH = "refresh_token";
OAuth2.prototype = {
responseType: "code",
consumerKey: null,
consumerSecret: null,
completionURI: "http://localhost",
@@ -63,7 +65,7 @@ OAuth2.prototype = {
if (!aRefresh && this.accessToken) {
aSuccess();
} else if (this.refreshToken) {
this.requestAccessToken(this.refreshToken, OAuth2.CODE_REFRESH);
this.requestAccessToken(this.refreshToken, true);
} else {
if (!aWithUI) {
aFailure('{ "error": "auth_noui" }');
@@ -78,25 +80,31 @@ OAuth2.prototype = {
},
requestAuthorization: function requestAuthorization() {
let params = [
["response_type", this.responseType],
["client_id", this.consumerKey],
["redirect_uri", this.completionURI],
];
// The scope can be optional.
let params = new URLSearchParams({
response_type: "code",
client_id: this.consumerKey,
redirect_uri: this.completionURI,
});
// The scope is optional.
if (this.scope) {
params.push(["scope", this.scope]);
params.append("scope", this.scope);
}
// Add extra parameters
params.push(...this.extraAuthParams);
for (let [name, value] of this.extraAuthParams) {
params.append(name, value);
}
// Now map the parameters to a string
params = params.map(([k,v]) => k + "=" + encodeURIComponent(v)).join("&");
let authEndpointURI = this.authURI + "?" + params.toString();
this.log.info(
"Interacting with the resource owner to obtain an authorization grant " +
"from the authorization endpoint: " +
authEndpointURI
);
this._browserRequest = {
account: this,
url: this.authURI + "?" + params,
url: authEndpointURI,
_active: true,
iconURI: "",
cancelled: function() {
@@ -170,65 +178,88 @@ OAuth2.prototype = {
delete this._browserRequest;
},
onAuthorizationReceived: function(aData) {
this.log.info("authorization received" + aData);
let results = parseURLData(aData);
if (this.responseType == "code" && results.code) {
this.requestAccessToken(results.code, OAuth2.CODE_AUTHORIZATION);
} else if (this.responseType == "token") {
this.onAccessTokenReceived(JSON.stringify(results));
// @see RFC 6749 section 4.1.2: Authorization Response
onAuthorizationReceived(aURL) {
this.log.info("OAuth2 authorization received: url=" + aURL);
let params = new URLSearchParams(aURL.split("?", 2)[1]);
if (params.has("code")) {
this.requestAccessToken(params.get("code"), false);
} else {
this.onAuthorizationFailed(null, aURL);
}
else
this.onAuthorizationFailed(null, aData);
},
onAuthorizationFailed: function(aError, aData) {
this.connectFailureCallback(aData);
},
requestAccessToken: function requestAccessToken(aCode, aType) {
let params = [
["client_id", this.consumerKey],
["client_secret", this.consumerSecret],
["grant_type", aType],
];
/**
* Request a new access token, or refresh an existing one.
* @param {string} aCode - The token issued to the client.
* @param {boolean} aRefresh - Whether it's a refresh of a token or not.
*/
requestAccessToken(aCode, aRefresh) {
// @see RFC 6749 section 4.1.3. Access Token Request
// @see RFC 6749 section 6. Refreshing an Access Token
if (aType == OAuth2.CODE_AUTHORIZATION) {
params.push(["code", aCode]);
params.push(["redirect_uri", this.completionURI]);
} else if (aType == OAuth2.CODE_REFRESH) {
params.push(["refresh_token", aCode]);
let data = new URLSearchParams();
data.append("client_id", this.consumerKey);
if (this.consumerSecret !== null) {
// Section 2.3.1. of RFC 6749 states that empty secrets MAY be omitted
// by the client. This OAuth implementation delegates this decission to
// the caller: If the secret is null, it will be omitted.
data.append("client_secret", this.consumerSecret);
}
if (aRefresh) {
this.log.info(
`Making a refresh request to the token endpoint: ${this.tokenURI}`
);
data.append("grant_type", "refresh_token");
data.append("refresh_token", aCode);
} else {
this.log.info(
`Making access token request to the token endpoint: ${this.tokenURI}`
);
data.append("grant_type", "authorization_code");
data.append("code", aCode);
data.append("redirect_uri", this.completionURI);
}
let options = {
postData: params,
onLoad: this.onAccessTokenReceived.bind(this),
onError: this.onAccessTokenFailed.bind(this)
fetch(this.tokenURI, {
method: "POST",
cache: "no-cache",
body: data,
})
.then(response => response.json())
.then(result => {
if ("error" in result) {
// RFC 6749 section 5.2. Error Response
this.log.info(
`The authorization server returned an error response: ${JSON.stringify(
result
)}`
);
this.connectFailureCallback(result);
return;
}
httpRequest(this.tokenURI, options);
},
onAccessTokenFailed: function onAccessTokenFailed(aError, aData) {
if (aError != "offline") {
this.refreshToken = null;
}
this.connectFailureCallback(aData);
},
onAccessTokenReceived: function onRequestTokenReceived(aData) {
let result = JSON.parse(aData);
// RFC 6749 section 5.1. Successful Response
this.log.info("The authorization server issued an access token.");
this.accessToken = result.access_token;
if ("refresh_token" in result) {
this.refreshToken = result.refresh_token;
this.refreshToken = result.refresh_token;
}
if ("expires_in" in result) {
this.tokenExpires = (new Date()).getTime() + (result.expires_in * 1000);
this.tokenExpires = new Date().getTime() + result.expires_in * 1000;
} else {
this.tokenExpires = Number.MAX_VALUE;
this.tokenExpires = Number.MAX_VALUE;
}
this.tokenType = result.token_type;
this.connectSuccessCallback();
})
.catch(err => {
this.log.info(`Connection to authorization server failed: ${err}`);
this.connectFailureCallback(err);
});
}
};
+40 -26
View File
@@ -5714,6 +5714,36 @@ void nsImapProtocol::ResetAuthMethods()
m_failedAuthMethods = 0;
}
nsresult nsImapProtocol::SendDataParseIMAPandCheckForNewMail(const char *aData, const char *aCommand)
{
nsresult rv;
bool isResend = false;
while (true)
{
// Send authentication string (true: suppress logging the string).
rv = SendData(aData, true);
if (NS_FAILED(rv))
break;
ParseIMAPandCheckForNewMail(aCommand);
if (!GetServerStateParser().WaitingForMoreClientInput())
break;
// The server is asking for the authentication string again. So we send
// the same string again although we know that it might be rejected again.
// We do that to get a firm authentication failure instead of a resend
// request. That keeps things in order before failing authentication and
// trying another method if capable.
if (isResend)
{
rv = NS_ERROR_FAILURE;
break;
}
isResend = true;
}
return rv;
}
nsresult nsImapProtocol::AuthLogin(const char *userName, const nsCString &password, eIMAPCapabilityFlag flag)
{
ProgressEventFunctionUsingName("imapStatusSendingAuthLogin");
@@ -5880,29 +5910,7 @@ nsresult nsImapProtocol::AuthLogin(const char *userName, const nsCString &passwo
PR_snprintf(m_dataOutputBuf, OUTPUT_BUFFER_SIZE, "%s" CRLF, base64Str);
PR_Free(base64Str);
bool isResend = false;
while (true)
{
// Send authentication string (true: suppress logging the string).
rv = SendData(m_dataOutputBuf, true);
if (NS_FAILED(rv))
break;
ParseIMAPandCheckForNewMail(currentCommand);
if (!GetServerStateParser().WaitingForMoreClientInput())
break;
// Server is asking for authentication string again. So we send the
// same string again although we already know that it will be
// rejected again. We do that to get a firm authentication failure
// instead of a resend request. That keeps things in order before
// failing "authenticate PLAIN" and trying another method if capable.
if (isResend)
{
rv = NS_ERROR_FAILURE;
break;
}
isResend = true;
}
rv = SendDataParseIMAPandCheckForNewMail(m_dataOutputBuf, currentCommand);
} // if the last command succeeded
} // if auth plain capability
else if (flag & kHasAuthLoginCapability)
@@ -5953,9 +5961,8 @@ nsresult nsImapProtocol::AuthLogin(const char *userName, const nsCString &passwo
EscapeUserNamePasswordString(password.get(), &correctedPassword);
command.Append(correctedPassword);
command.Append("\"" CRLF);
rv = SendData(command.get(), true /* suppress logging */);
NS_ENSURE_SUCCESS(rv, rv);
ParseIMAPandCheckForNewMail();
rv = SendDataParseIMAPandCheckForNewMail(command.get(), nullptr);
}
#ifdef MOZ_MAILNEWS_OAUTH2
else if (flag & kHasXOAuth2Capability)
@@ -8513,6 +8520,13 @@ nsresult nsImapProtocol::GetPassword(nsCString &password,
return rv;
}
NS_IMETHODIMP nsImapProtocol::OnPromptStartAsync(nsIMsgAsyncPromptCallback *aCallback)
{
bool result = false;
OnPromptStart(&result);
return aCallback->OnAuthResult(result);
}
// This is called from the UI thread.
NS_IMETHODIMP
nsImapProtocol::OnPromptStart(bool *aResult)
+1
View File
@@ -485,6 +485,7 @@ private:
void Namespace();
void InsecureLogin(const char *userName, const nsCString &password);
nsresult AuthLogin(const char *userName, const nsCString &password, eIMAPCapabilityFlag flag);
nsresult SendDataParseIMAPandCheckForNewMail(const char *data, const char *command);
void ProcessAuthenticatedStateURL();
void ProcessAfterAuthenticated();
void ProcessSelectedStateURL();
+7
View File
@@ -740,6 +740,13 @@ nsresult nsPop3Protocol::StartGetAsyncPassword(Pop3StatesEnum aNextState)
return rv;
}
NS_IMETHODIMP nsPop3Protocol::OnPromptStartAsync(nsIMsgAsyncPromptCallback *aCallback)
{
bool result = false;
OnPromptStart(&result);
return aCallback->OnAuthResult(result);
}
NS_IMETHODIMP nsPop3Protocol::OnPromptStart(bool *aResult)
{
MOZ_LOG(POP3LOGMODULE, LogLevel::Debug, (POP3LOG("OnPromptStart()")));
+2 -2
View File
@@ -450,7 +450,7 @@ pref("mail.server.default.valid", true);
pref("mail.server.default.abbreviate", true);
pref("mail.server.default.isSecure", false);
pref("mail.server.default.authMethod", 3); // cleartext password. @see nsIMsgIncomingServer.authMethod.
pref("mail.server.default.socketType", 0); // @see nsIMsgIncomingServer.socketType
pref("mail.server.default.socketType", 3); // SSL/TLS. @see nsIMsgIncomingServer.socketType
pref("mail.server.default.override_namespaces", true);
pref("mail.server.default.deferred_to_account", "");
@@ -579,7 +579,7 @@ pref("mail.smtp.useMatchingDomainServer", false);
pref("mail.smtp.useMatchingHostNameServer", false);
pref("mail.smtpserver.default.authMethod", 3); // cleartext password. @see nsIMsgIncomingServer.authMethod.
pref("mail.smtpserver.default.try_ssl", 0); // @see nsISmtpServer.socketType
pref("mail.smtpserver.default.try_ssl", 3); // SSL/TLS. @see nsISmtpServer.socketType
// For the next 3 prefs, see <http://www.bucksch.org/1/projects/mozilla/16507>
pref("mail.display_glyph", true); // TXT->HTML :-) etc. in viewer
+7
View File
@@ -2472,6 +2472,13 @@ nsresult nsNNTPProtocol::PasswordResponse()
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsNNTPProtocol::OnPromptStartAsync(nsIMsgAsyncPromptCallback *aCallback)
{
bool result = false;
OnPromptStart(&result);
return aCallback->OnAuthResult(result);
}
NS_IMETHODIMP nsNNTPProtocol::OnPromptStart(bool *authAvailable)
{
NS_ENSURE_ARG_POINTER(authAvailable);
+1 -1
View File
@@ -283,9 +283,9 @@ void SoundTouch::calcEffectiveRateAndTempo()
// Sets sample rate.
void SoundTouch::setSampleRate(uint srate)
{
bSrateSet = true;
// set sample rate, leave other tempo changer parameters as they are.
pTDStretch->setParameters((int)srate);
bSrateSet = true;
}
+7 -2
View File
@@ -126,8 +126,13 @@ void TDStretch::setParameters(int aSampleRate, int aSequenceMS,
int aSeekWindowMS, int aOverlapMS)
{
// accept only positive parameter values - if zero or negative, use old values instead
if (aSampleRate > 0) this->sampleRate = aSampleRate;
if (aOverlapMS > 0) this->overlapMs = aOverlapMS;
if (aSampleRate > 0)
{
if (aSampleRate > 192000) ST_THROW_RT_ERROR("Error: Excessive samplerate");
this->sampleRate = aSampleRate;
}
if (aOverlapMS > 0) this->overlapMs = aOverlapMS;
if (aSequenceMS > 0)
{
+14 -4
View File
@@ -82,6 +82,9 @@ nsFtpState::nsFtpState()
, mAnonymous(true)
, mRetryPass(false)
, mStorReplyReceived(false)
, mRlist1xxReceived(false)
, mRstor1xxReceived(false)
, mRretr1xxReceived(false)
, mInternalError(NS_OK)
, mReconnectAndLoginAgain(false)
, mCacheConnection(true)
@@ -1153,15 +1156,18 @@ nsFtpState::S_list() {
FTP_STATE
nsFtpState::R_list() {
if (mResponseCode/100 == 1) {
mRlist1xxReceived = true;
// OK, time to start reading from the data connection.
if (mDataStream && HasPendingCallback())
mDataStream->AsyncWait(this, 0, 0, CallbackTarget());
return FTP_READ_BUF;
}
if (mResponseCode/100 == 2) {
if (mResponseCode/100 == 2 && mRlist1xxReceived) {
//(DONE)
mNextState = FTP_COMPLETE;
mRlist1xxReceived = false;
return FTP_COMPLETE;
}
return FTP_ERROR;
@@ -1181,13 +1187,16 @@ nsFtpState::S_retr() {
FTP_STATE
nsFtpState::R_retr() {
if (mResponseCode/100 == 2) {
if (mResponseCode/100 == 2 && mRretr1xxReceived) {
//(DONE)
mNextState = FTP_COMPLETE;
mRretr1xxReceived = false;
return FTP_COMPLETE;
}
if (mResponseCode/100 == 1) {
mRretr1xxReceived = true;
if (mDataStream && HasPendingCallback())
mDataStream->AsyncWait(this, 0, 0, CallbackTarget());
return FTP_READ_BUF;
@@ -1262,7 +1271,7 @@ nsFtpState::S_stor() {
FTP_STATE
nsFtpState::R_stor() {
if (mResponseCode/100 == 2) {
if (mResponseCode/100 == 2 && mRstor1xxReceived) {
//(DONE)
mNextState = FTP_COMPLETE;
mStorReplyReceived = true;
@@ -1270,11 +1279,12 @@ nsFtpState::R_stor() {
// Call Close() if it was not called in nsFtpState::OnStoprequest()
if (!mUploadRequest && !IsClosed())
Close();
mRstor1xxReceived = false;
return FTP_COMPLETE;
}
if (mResponseCode/100 == 1) {
mRstor1xxReceived = true;
LOG(("FTP:(%x) writing on DT\n", this));
return FTP_READ_BUF;
}
@@ -180,6 +180,12 @@ private:
bool mRetryPass; // retrying the password
bool mStorReplyReceived; // FALSE if waiting for STOR
// completion status from server
bool mRlist1xxReceived; // TRUE if the server has sent a
// LIST 1xx response.
bool mRstor1xxReceived; // TRUE if the server has sent a
// STOR 1xx response.
bool mRretr1xxReceived; // TRUE if the server has sent a
// RETR 1xx response.
nsresult mInternalError; // represents internal state errors
bool mReconnectAndLoginAgain;
bool mCacheConnection;
+2 -2
View File
@@ -486,8 +486,8 @@ nsHttpNTLMAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel,
len -= 5;
// strip off any padding (see bug 230351)
while (challenge[len - 1] == '=')
len--;
while (len && challenge[len - 1] == '=')
len--;
// decode into the input secbuffer
rv = Base64Decode(challenge, len, (char**)&inBuf, &inBufLen);
+2 -2
View File
@@ -141,8 +141,6 @@ nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self)
tokenizer->setState(NS_HTML5TOKENIZER_DATA);
}
}
contextName = nullptr;
contextNode = nullptr;
} else {
mode = NS_HTML5TREE_BUILDER_INITIAL;
if (tokenizer->isViewingXmlSource()) {
@@ -581,6 +579,8 @@ nsHtml5TreeBuilder::endTokenization()
{
formPointer = nullptr;
headPointer = nullptr;
contextName = nullptr;
contextNode = nullptr;
deepTreeSurrogateParent = nullptr;
templateModeStack = nullptr;
if (stack) {
@@ -8,6 +8,7 @@
#include "PSMRunnable.h"
#include "mozilla/Casting.h"
#include "mozilla/net/DNS.h"
#include "nsComponentManagerUtils.h"
#include "nsIArray.h"
#include "nsICertOverrideService.h"
@@ -681,8 +682,10 @@ GetSubjectAltNames(CERTCertificate* nssCert, nsString& allNames)
case certIPAddress:
{
char buf[INET6_ADDRSTRLEN];
// According to DNS.h, this includes space for the null-terminator
char buf[net::kNetAddrMaxCStrBufSize] = {0};
PRNetAddr addr;
memset(&addr, 0, sizeof(addr));
if (current->name.other.len == 4) {
addr.inet.family = PR_AF_INET;
memcpy(&addr.inet.ip, current->name.other.data, current->name.other.len);
+3 -1
View File
@@ -11,6 +11,7 @@
#include "mozilla/NotNull.h"
#include "mozilla/Sprintf.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/net/DNS.h"
#include "nsCOMPtr.h"
#include "nsComponentManagerUtils.h"
#include "nsDateTimeFormatCID.h"
@@ -1006,8 +1007,9 @@ ProcessGeneralName(const UniquePLArenaPool& arena, CERTGeneralName* current,
break;
case certIPAddress:
{
char buf[INET6_ADDRSTRLEN];
PRStatus status = PR_FAILURE;
// According to DNS.h, this includes space for the null-terminator
char buf[net::kNetAddrMaxCStrBufSize] = {0};
PRNetAddr addr;
memset(&addr, 0, sizeof(addr));
nssComponent->GetPIPNSSBundleString("CertDumpIPAddress", key);
+38 -34
View File
@@ -4118,45 +4118,49 @@ XRE_InitCommandLine(int aArgc, char* aArgv[])
delete[] canonArgs;
#endif
const char *path = nullptr;
ArgResult ar = CheckArg("greomni", true, &path);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR,
"Error: argument --greomni requires a path argument or the "
"--osint argument was specified with the --greomni argument "
"which is invalid.\n");
return NS_ERROR_FAILURE;
}
if (PR_GetEnv("UXP_CUSTOM_OMNI")) {
// Process CLI parameters for specifying custom omnijars
const char *path = nullptr;
ArgResult ar = CheckArg("greomni", true, &path);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR,
"Error: argument --greomni requires a path argument or the "
"--osint argument was specified with the --greomni argument "
"which is invalid.\n");
return NS_ERROR_FAILURE;
}
if (!path)
return rv;
if (!path)
return rv;
nsCOMPtr<nsIFile> greOmni;
rv = XRE_GetFileFromPath(path, getter_AddRefs(greOmni));
if (NS_FAILED(rv)) {
PR_fprintf(PR_STDERR, "Error: argument --greomni requires a valid path\n");
return rv;
}
nsCOMPtr<nsIFile> greOmni;
rv = XRE_GetFileFromPath(path, getter_AddRefs(greOmni));
if (NS_FAILED(rv)) {
PR_fprintf(PR_STDERR, "Error: argument --greomni requires a valid path\n");
return rv;
}
ar = CheckArg("appomni", true, &path);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR,
"Error: argument --appomni requires a path argument or the "
"--osint argument was specified with the --appomni argument "
"which is invalid.\n");
return NS_ERROR_FAILURE;
}
ar = CheckArg("appomni", true, &path);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR,
"Error: argument --appomni requires a path argument or the "
"--osint argument was specified with the --appomni argument "
"which is invalid.\n");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIFile> appOmni;
if (path) {
rv = XRE_GetFileFromPath(path, getter_AddRefs(appOmni));
if (NS_FAILED(rv)) {
PR_fprintf(PR_STDERR, "Error: argument --appomni requires a valid path\n");
return rv;
}
}
nsCOMPtr<nsIFile> appOmni;
if (path) {
rv = XRE_GetFileFromPath(path, getter_AddRefs(appOmni));
if (NS_FAILED(rv)) {
PR_fprintf(PR_STDERR, "Error: argument --appomni requires a valid path\n");
return rv;
}
}
mozilla::Omnijar::Init(greOmni, appOmni);
} // UXP_CUSTOM_OMNI
mozilla::Omnijar::Init(greOmni, appOmni);
return rv;
}
@@ -406,75 +406,107 @@ already_AddRefed<nsMIMEInfoWin> nsOSHelperAppService::GetByExtension(const nsAFl
return mimeInfo.forget();
}
already_AddRefed<nsIMIMEInfo> nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType, const nsACString& aFileExt, bool *aFound)
already_AddRefed<nsIMIMEInfo> nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType,
const nsACString& aFileExt,
bool *aFound)
{
*aFound = true;
*aFound = false;
const nsCString& flatType = PromiseFlatCString(aMIMEType);
const nsCString& flatExt = PromiseFlatCString(aFileExt);
nsAutoString fileExtension;
/* XXX The Equals is a gross hack to wallpaper over the most common Win32
* extension issues caused by the fix for bug 116938. See bug
* 120327, comment 271 for why this is needed. Not even sure we
CopyUTF8toUTF16(aFileExt, fileExtension);
/* XXX The octet-stream check is a gross hack to wallpaper over the most
* common Win32 extension issues caused by the fix for bug 116938. See bug
* 120327, comment 271 for why this is needed. Not even sure we
* want to remove this once we have fixed all this stuff to work
* right; any info we get from the OS on this type is pretty much
* useless....
* We'll do extension-based lookup for this type later in this function.
* useless...
*/
if (!aMIMEType.LowerCaseEqualsLiteral(APPLICATION_OCTET_STREAM)) {
// try to use the windows mime database to see if there is a mapping to a file extension
GetExtensionFromWindowsMimeDatabase(aMIMEType, fileExtension);
LOG(("Windows mime database: extension '%s'\n", fileExtension.get()));
}
// If we found an extension for the type, do the lookup
RefPtr<nsMIMEInfoWin> mi;
if (!fileExtension.IsEmpty())
mi = GetByExtension(fileExtension, flatType.get());
LOG(("Extension lookup on '%s' found: 0x%p\n", fileExtension.get(), mi.get()));
bool haveMeaningfulMimeType =
!aMIMEType.IsEmpty() &&
!aMIMEType.LowerCaseEqualsLiteral(APPLICATION_OCTET_STREAM);
LOG(("Extension lookup on '%s' with mimetype '%s'%s\n", fileExtension.get(),
flatType.get(),
haveMeaningfulMimeType ? " (treated as meaningful)" : ""));
bool hasDefault = false;
if (mi) {
mi->GetHasDefaultHandler(&hasDefault);
// OK. We might have the case that |aFileExt| is a valid extension for the
// mimetype we were given. In that case, we do want to append aFileExt
// to the mimeinfo that we have. (E.g.: We are asked for video/mpeg and
// .mpg, but the primary extension for video/mpeg is .mpeg. But because
// .mpg is an extension for video/mpeg content, we want to append it)
if (!aFileExt.IsEmpty() && typeFromExtEquals(NS_ConvertUTF8toUTF16(flatExt).get(), flatType.get())) {
LOG(("Appending extension '%s' to mimeinfo, because its mimetype is '%s'\n",
flatExt.get(), flatType.get()));
bool extExist = false;
mi->ExtensionExists(aFileExt, &extExist);
if (!extExist)
mi->AppendExtension(aFileExt);
}
RefPtr<nsMIMEInfoWin> mi;
// We should have *something* to go on here.
if (fileExtension.IsEmpty() && !haveMeaningfulMimeType) {
mi = new nsMIMEInfoWin(flatType.get());
return mi.forget();
}
if (!mi || !hasDefault) {
RefPtr<nsMIMEInfoWin> miByExt =
GetByExtension(NS_ConvertUTF8toUTF16(aFileExt), flatType.get());
LOG(("Ext. lookup for '%s' found 0x%p\n", flatExt.get(), miByExt.get()));
if (!miByExt && mi)
return mi.forget();
if (miByExt && !mi) {
return miByExt.forget();
}
if (!miByExt && !mi) {
*aFound = false;
mi = new nsMIMEInfoWin(flatType);
nsAutoString extensionFromMimeType;
if (haveMeaningfulMimeType) {
GetExtensionFromWindowsMimeDatabase(aMIMEType, extensionFromMimeType);
if (extensionFromMimeType.IsEmpty()) {
// We can't verify the mime type and file extension make sense.
mi = new nsMIMEInfoWin(flatType.get());
if (!aFileExt.IsEmpty()) {
mi->AppendExtension(aFileExt);
}
return mi.forget();
}
}
// Either fileExtension or extensionFromMimeType must now be non-empty.
// if we get here, mi has no default app. copy from extension lookup.
nsCOMPtr<nsIFile> defaultApp;
nsAutoString desc;
miByExt->GetDefaultDescription(desc);
*aFound = true;
mi->SetDefaultDescription(desc);
// On Windows, we prefer the file extension for lookups over the mimetype,
// because that's how windows does things.
// If we have no file extension or it doesn't match the mimetype, use the
// mime type's default file extension instead.
bool usedMimeTypeExtensionForLookup = false;
if (fileExtension.IsEmpty() ||
(haveMeaningfulMimeType &&
!typeFromExtEquals(fileExtension.get(), flatType.get()))) {
usedMimeTypeExtensionForLookup = true;
fileExtension = extensionFromMimeType;
LOG(("Now using '%s' mimetype's default file extension '%s' for lookup\n",
flatType.get(), fileExtension.get()));
}
// If we have an extension, use it for lookup:
mi = GetByExtension(fileExtension, flatType.get());
LOG(("Extension lookup on '%s' found: 0x%p\n", fileExtension.get(), mi.get()));
if (mi) {
bool hasDefault = false;
mi->GetHasDefaultHandler(&hasDefault);
// If we don't find a default handler description, see if we can find one
// using the mimetype.
if (!hasDefault && !usedMimeTypeExtensionForLookup) {
RefPtr<nsMIMEInfoWin> miFromMimeType =
GetByExtension(extensionFromMimeType, flatType.get());
LOG(("Mime-based ext. lookup for '%s' found 0x%p\n",
extensionFromMimeType.get(), miFromMimeType.get()));
if (miFromMimeType) {
nsAutoString desc;
miFromMimeType->GetDefaultDescription(desc);
mi->SetDefaultDescription(desc);
}
}
return mi.forget();
}
// The extension didn't work. Try the extension from the mimetype if
// different:
if (!extensionFromMimeType.IsEmpty() && !usedMimeTypeExtensionForLookup) {
mi = GetByExtension(extensionFromMimeType, flatType.get());
LOG(("Mime-based ext. lookup for '%s' found 0x%p\n",
extensionFromMimeType.get(), mi.get()));
}
if (mi) {
return mi.forget();
}
// This didn't work either, so just return an empty dummy mimeinfo.
*aFound = false;
mi = new nsMIMEInfoWin(flatType.get());
// If we didn't resort to the mime type's extension, we must have had a
// valid extension, so stick it on the mime info.
if (!usedMimeTypeExtensionForLookup) {
mi->AppendExtension(aFileExt);
}
return mi.forget();
}
+4
View File
@@ -300,6 +300,10 @@ struct InputContext final
* compatibility with webapps relying on key listeners. */
bool mMayBeIMEUnaware;
/* Whether the owning document of the input element has been loaded
* in private browsing mode. */
bool mInPrivateBrowsing;
bool IsOriginMainProcess() const
{
return mOrigin == ORIGIN_MAIN;
+29 -22
View File
@@ -120,24 +120,13 @@ NS_IMETHODIMP
nsClipboard::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData)
{
if (strcmp(aTopic, "quit-application") == 0) {
// application is going to quit, save clipboard content
Store();
// Application is going to quit, save clipboard content
gtk_clipboard_store(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
gdk_window_remove_filter(nullptr, selection_request_filter, nullptr);
}
return NS_OK;
}
nsresult
nsClipboard::Store(void)
{
// Ask the clipboard manager to store the current clipboard content
if (mGlobalTransferable) {
GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
gtk_clipboard_store(clipboard);
}
return NS_OK;
}
NS_IMETHODIMP
nsClipboard::SetData(nsITransferable *aTransferable,
nsIClipboardOwner *aOwner, int32_t aWhichClipboard)
@@ -152,9 +141,6 @@ nsClipboard::SetData(nsITransferable *aTransferable,
return NS_OK;
}
// Clear out the clipboard in order to set the new data
EmptyClipboard(aWhichClipboard);
// List of suported targets
GtkTargetList *list = gtk_target_list_new(nullptr, 0);
@@ -163,8 +149,12 @@ nsClipboard::SetData(nsITransferable *aTransferable,
nsresult rv =
aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavors));
if (!flavors || NS_FAILED(rv))
if (!flavors || NS_FAILED(rv)) {
// Clear references to the any old data and let GTK know that it is no
// longer available.
EmptyClipboard(aWhichClipboard);
return NS_ERROR_FAILURE;
}
// Add all the flavors to this widget's supported type.
bool imagesAdded = false;
@@ -232,8 +222,10 @@ nsClipboard::SetData(nsITransferable *aTransferable,
}
rv = NS_OK;
}
else {
} else {
// Clear references to the any old data and let GTK know that it is no
// longer available.
EmptyClipboard(aWhichClipboard);
rv = NS_ERROR_FAILURE;
}
@@ -373,6 +365,23 @@ nsClipboard::GetData(nsITransferable *aTransferable, int32_t aWhichClipboard)
NS_IMETHODIMP
nsClipboard::EmptyClipboard(int32_t aWhichClipboard)
{
if (aWhichClipboard == kSelectionClipboard) {
if (mSelectionTransferable) {
gtk_clipboard_clear(gtk_clipboard_get(GDK_SELECTION_PRIMARY));
MOZ_ASSERT(!mSelectionTransferable);
}
} else {
if (mGlobalTransferable) {
gtk_clipboard_clear(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
MOZ_ASSERT(!mGlobalTransferable);
}
}
return NS_OK;
}
void
nsClipboard::ClearTransferable(int32_t aWhichClipboard) {
if (aWhichClipboard == kSelectionClipboard) {
if (mSelectionOwner) {
mSelectionOwner->LosingOwnership(mSelectionTransferable);
@@ -387,8 +396,6 @@ nsClipboard::EmptyClipboard(int32_t aWhichClipboard)
}
mGlobalTransferable = nullptr;
}
return NS_OK;
}
NS_IMETHODIMP
@@ -652,7 +659,7 @@ nsClipboard::SelectionClearEvent(GtkClipboard *aGtkClipboard)
else
return; // THAT AIN'T NO CLIPBOARD I EVER HEARD OF
EmptyClipboard(whichClipboard);
ClearTransferable(whichClipboard);
}
void
+2 -3
View File
@@ -39,13 +39,12 @@ private:
static GdkAtom GetSelectionAtom (int32_t aWhichClipboard);
static GtkSelectionData *GetTargets (GdkAtom aWhichClipboard);
// Save global clipboard content to gtk
nsresult Store (void);
// Get our hands on the correct transferable, given a specific
// clipboard
nsITransferable *GetTransferable (int32_t aWhichClipboard);
void ClearTransferable(int32_t aWhichClipboard);
// Hang on to our owners and transferables so we can transfer data
// when asked.
nsCOMPtr<nsIClipboardOwner> mSelectionOwner;
+12 -3
View File
@@ -1355,7 +1355,9 @@ TSFTextStore::Init(nsWindowBase* aWidget,
return false;
}
SetInputScope(aContext.mHTMLInputType, aContext.mHTMLInputInputmode);
SetInputScope(aContext.mHTMLInputType,
aContext.mHTMLInputInputmode,
aContext.mInPrivateBrowsing);
// Create document manager
RefPtr<ITfThreadMgr> threadMgr = sThreadMgr;
@@ -3205,9 +3207,15 @@ TSFTextStore::InsertEmbedded(DWORD dwFlags,
void
TSFTextStore::SetInputScope(const nsString& aHTMLInputType,
const nsString& aHTMLInputInputMode)
const nsString& aHTMLInputInputMode,
bool aInPrivateBrowsing)
{
mInputScopes.Clear();
if (aInPrivateBrowsing) {
mInputScopes.AppendElement(IS_PRIVATE);
}
if (aHTMLInputType.IsEmpty() || aHTMLInputType.EqualsLiteral("text")) {
if (aHTMLInputInputMode.EqualsLiteral("url")) {
mInputScopes.AppendElement(IS_URL);
@@ -5688,7 +5696,8 @@ TSFTextStore::SetInputContext(nsWindowBase* aWidget,
if (sEnabledTextStore) {
RefPtr<TSFTextStore> textStore(sEnabledTextStore);
textStore->SetInputScope(aContext.mHTMLInputType,
aContext.mHTMLInputInputmode);
aContext.mHTMLInputInputmode,
aContext.mInPrivateBrowsing);
}
return;
}
+2 -1
View File
@@ -355,7 +355,8 @@ protected:
ULONG aFilterCount,
const TS_ATTRID* aFilterAttrs);
void SetInputScope(const nsString& aHTMLInputType,
const nsString& aHTMLInputInputmode);
const nsString& aHTMLInputInputmode,
bool aInPrivateBrowsing);
// Creates native caret over our caret. This method only works on desktop
// application. Otherwise, this does nothing.
+38 -54
View File
@@ -409,7 +409,7 @@ IMEHandler::OnDestroyWindow(nsWindow* aWindow)
if (!sIsInTSFMode) {
// MSDN says we need to set IS_DEFAULT to avoid memory leak when we use
// SetInputScopes API. Use an empty string to do this.
SetInputScopeForIMM32(aWindow, EmptyString(), EmptyString());
SetInputScopeForIMM32(aWindow, EmptyString(), EmptyString(), false);
}
#endif // #ifdef NS_ENABLE_TSF
AssociateIMEContext(aWindow, true);
@@ -481,8 +481,10 @@ IMEHandler::SetInputContext(nsWindow* aWindow,
}
} else {
// Set at least InputScope even when TextStore is not available.
SetInputScopeForIMM32(aWindow, aInputContext.mHTMLInputType,
aInputContext.mHTMLInputInputmode);
SetInputScopeForIMM32(aWindow,
aInputContext.mHTMLInputType,
aInputContext.mHTMLInputInputmode,
aInputContext.mInPrivateBrowsing);
}
#endif // #ifdef NS_ENABLE_TSF
@@ -583,82 +585,64 @@ IMEHandler::OnKeyboardLayoutChanged()
void
IMEHandler::SetInputScopeForIMM32(nsWindow* aWindow,
const nsAString& aHTMLInputType,
const nsAString& aHTMLInputInputmode)
const nsAString& aHTMLInputInputmode,
bool aInPrivateBrowsing)
{
if (sIsInTSFMode || !sSetInputScopes || aWindow->Destroyed()) {
return;
}
UINT arraySize = 0;
const InputScope* scopes = nullptr;
AutoTArray<InputScope, 3> scopes;
if (aInPrivateBrowsing) {
scopes.AppendElement(IS_PRIVATE);
}
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html
if (aHTMLInputType.IsEmpty() || aHTMLInputType.EqualsLiteral("text")) {
if (aHTMLInputInputmode.EqualsLiteral("url")) {
static const InputScope inputScopes[] = { IS_URL };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_URL);
} else if (aHTMLInputInputmode.EqualsLiteral("email")) {
static const InputScope inputScopes[] = { IS_EMAIL_SMTPEMAILADDRESS };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_EMAIL_SMTPEMAILADDRESS);
} else if (aHTMLInputInputmode.EqualsLiteral("tel")) {
static const InputScope inputScopes[] =
{IS_TELEPHONE_LOCALNUMBER, IS_TELEPHONE_FULLTELEPHONENUMBER};
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_TELEPHONE_LOCALNUMBER);
scopes.AppendElement(IS_TELEPHONE_FULLTELEPHONENUMBER);
} else if (aHTMLInputInputmode.EqualsLiteral("numeric")) {
static const InputScope inputScopes[] = { IS_NUMBER };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_NUMBER);
} else {
static const InputScope inputScopes[] = { IS_DEFAULT };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_DEFAULT);
}
} else if (aHTMLInputType.EqualsLiteral("url")) {
static const InputScope inputScopes[] = { IS_URL };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_URL);
} else if (aHTMLInputType.EqualsLiteral("search")) {
static const InputScope inputScopes[] = { IS_SEARCH };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_SEARCH);
} else if (aHTMLInputType.EqualsLiteral("email")) {
static const InputScope inputScopes[] = { IS_EMAIL_SMTPEMAILADDRESS };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_EMAIL_SMTPEMAILADDRESS);
} else if (aHTMLInputType.EqualsLiteral("password")) {
static const InputScope inputScopes[] = { IS_PASSWORD };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_PASSWORD);
} else if (aHTMLInputType.EqualsLiteral("datetime") ||
aHTMLInputType.EqualsLiteral("datetime-local")) {
static const InputScope inputScopes[] = {
IS_DATE_FULLDATE, IS_TIME_FULLTIME };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_DATE_FULLDATE);
scopes.AppendElement(IS_TIME_FULLTIME);
} else if (aHTMLInputType.EqualsLiteral("date") ||
aHTMLInputType.EqualsLiteral("month") ||
aHTMLInputType.EqualsLiteral("week")) {
static const InputScope inputScopes[] = { IS_DATE_FULLDATE };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_DATE_FULLDATE);
} else if (aHTMLInputType.EqualsLiteral("time")) {
static const InputScope inputScopes[] = { IS_TIME_FULLTIME };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_TIME_FULLTIME);
} else if (aHTMLInputType.EqualsLiteral("tel")) {
static const InputScope inputScopes[] = {
IS_TELEPHONE_FULLTELEPHONENUMBER, IS_TELEPHONE_LOCALNUMBER };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_TELEPHONE_FULLTELEPHONENUMBER);
scopes.AppendElement(IS_TELEPHONE_LOCALNUMBER);
} else if (aHTMLInputType.EqualsLiteral("number")) {
static const InputScope inputScopes[] = { IS_NUMBER };
scopes = &inputScopes[0];
arraySize = ArrayLength(inputScopes);
scopes.AppendElement(IS_NUMBER);
}
if (scopes && arraySize > 0) {
sSetInputScopes(aWindow->GetWindowHandle(), scopes, arraySize, nullptr, 0,
nullptr, nullptr);
if (!scopes.IsEmpty()) {
sSetInputScopes(aWindow->GetWindowHandle(),
scopes.Elements(),
scopes.Length(),
nullptr,
0,
nullptr,
nullptr);
}
}
+2 -1
View File
@@ -144,7 +144,8 @@ private:
static decltype(SetInputScopes)* sSetInputScopes;
static void SetInputScopeForIMM32(nsWindow* aWindow,
const nsAString& aHTMLInputType,
const nsAString& aHTMLInputInputmode);
const nsAString& aHTMLInputInputmode,
bool aInPrivateBrowsing);
static bool sIsInTSFMode;
// If sIMMEnabled is false, any IME messages are not handled in TSF mode.
// Additionally, IME context is always disassociated from focused window.