From debfadcca4ebb53b19fda08db93602babf01bb1c Mon Sep 17 00:00:00 2001 From: roytam1 Date: Thu, 14 Jan 2021 23:51:05 +0800 Subject: [PATCH] import changes from `dev' branch of rmottola/Arctic-Fox: - Bug 751387 - Fix crash caused by out-of-bounds accesses in command line options handling. r=bholley (240670c35) - Bug 1162187 - Pass around AutoJSAPI instead of cx to give us more control over error handling. r=glandium (702954016) - Bug 1162187 - Factor out single line argument processing into a helper. r=glandium (56efce591) - Bug 1162187 - Use the AutoJSAPI machinery to handle xpcshell exceptions. r=glandium (162309001) - Bug 1162187 - Remove the custom XPCShell error reporter. r=glandium (523d84539) - Bug 1162187 - Remove ignoreReportedErrors. r=glandium (072f247a3) - Bug 1161590 - xpcshell needs to initialize graphics prefs so that GfxInfo::GetFeatureStatus can check preferences. r=ehsan (5a8415817) - Bug 1166243 - Remove build() function from js and xpc shells. r=bholley,r=efaust (8537f2259) - Bug 1182357 - Implement support for optional size_is for arrays passed from JS. r=mrbkap (0d22d3f34) - missing profiler parts of Bug 1092311 - Fix IndexedDB profiler markers and logging (a68567bbb) - Bug 1086999 - CSP: Asterisk (*) wildcard should not allow blob:, data:, or filesystem: when matching source expressions (r=fabrice,pauljt) (7757a92ae) - Bug 1105827 - Part 1: Add stub PermissionStatus implementation. r=baku (2bd4c1dd3) - Bug 635134 - Adds X11 run-time check for Gtk3 backend. r=karlt (7e9304f5e) - Bug 994541 - Enable BasicCompositor OMTC on linux. r=Bas (c9a266beb) - Bug 1105827 - Part 2: Add stub Permissions implementation. r=baku (751f5e9e6) - Bug 1105827 - Part 3: Implement Permissions.query. r=baku (a30a48cbe) - Bug 1105827 - Part 4: Add Navigator.permissions. r=baku (0d70fc5e6) - Bug 1174861 - Remove unnecessary Rooted from Prefable::isEnabled(). r=bholley (a0893081d) --- b2g/app/b2g.js | 4 +- dom/base/Navigator.cpp | 23 +- dom/base/Navigator.h | 4 + dom/base/nsJSEnvironment.cpp | 4 +- dom/bindings/DOMJSClass.h | 10 +- dom/devicestorage/nsDeviceStorage.cpp | 6 +- dom/indexedDB/IndexedDatabaseManager.cpp | 13 + dom/ipc/TabChild.cpp | 2 +- dom/mobilemessage/MobileMessageCallback.cpp | 4 +- dom/permission/PermissionStatus.cpp | 33 +++ dom/permission/PermissionStatus.h | 38 +++ dom/permission/Permissions.cpp | 160 +++++++++++ dom/permission/Permissions.h | 50 ++++ dom/permission/moz.build | 14 + dom/plugins/base/nsJSNPRuntime.cpp | 2 +- dom/security/nsCSPService.cpp | 2 +- dom/system/OSFileConstants.cpp | 2 +- .../mochitest/general/test_interfaces.html | 4 + dom/webidl/Navigator.webidl | 5 + dom/webidl/PermissionStatus.webidl | 21 ++ dom/webidl/Permissions.webidl | 30 +++ dom/webidl/moz.build | 2 + dom/workers/XMLHttpRequest.cpp | 2 +- dom/workers/XMLHttpRequest.h | 2 +- gfx/thebes/gfxPlatform.cpp | 6 - gfx/thebes/gfxPlatformGtk.cpp | 9 +- ipc/testshell/XPCShellEnvironment.cpp | 14 +- js/ipc/JavaScriptShared.cpp | 2 +- js/public/Value.h | 12 +- js/src/ctypes/CTypes.cpp | 35 +-- js/src/jsapi-tests/testArgumentsObject.cpp | 2 +- js/src/jsapi-tests/testArrayBuffer.cpp | 4 +- js/src/jsapi-tests/testDeepFreeze.cpp | 10 +- js/src/jsapi-tests/testFunctionProperties.cpp | 4 +- js/src/jsapi-tests/testLookup.cpp | 6 +- js/src/jsapi-tests/testLooselyEqual.cpp | 4 +- js/src/jsapi-tests/testNewObject.cpp | 2 +- .../testObjectEmulatingUndefined.cpp | 22 +- js/src/jsapi-tests/testParseJSON.cpp | 14 +- js/src/jsapi-tests/testResolveRecursion.cpp | 8 +- js/src/jsapi-tests/testXDR.cpp | 2 +- js/src/jsapi.cpp | 2 +- js/src/jsapi.h | 2 +- js/src/shell/js.cpp | 13 - js/src/vm/Value.cpp | 10 +- js/xpconnect/src/XPCConvert.cpp | 2 +- js/xpconnect/src/XPCShellImpl.cpp | 248 +++++++++--------- js/xpconnect/src/XPCWrappedNative.cpp | 41 ++- js/xpconnect/src/XPCWrappedNativeJSOps.cpp | 2 +- .../tests/components/js/xpctest_params.js | 8 +- .../components/native/xpctest_params.cpp | 13 + js/xpconnect/tests/idl/xpctest_params.idl | 5 +- js/xpconnect/tests/unit/test_bug809674.js | 6 +- js/xpconnect/tests/unit/test_params.js | 3 + js/xpconnect/wrappers/XrayWrapper.cpp | 4 +- modules/libpref/init/all.js | 27 +- storage/mozStorageStatementJSHelper.cpp | 2 +- storage/mozStorageStatementRow.cpp | 2 +- toolkit/devtools/server/nsJSInspector.cpp | 4 +- .../server/tests/unit/test_sourcemaps-04.js | 9 - .../server/tests/unit/test_sourcemaps-05.js | 9 - toolkit/mozapps/installer/precompile_cache.js | 10 - toolkit/xre/nsAppRunner.cpp | 50 ++-- widget/gtk/compat/gdk/gdkx.h | 5 + widget/gtk/mozgtk/mozgtk.c | 3 + widget/gtk/nsClipboard.cpp | 76 +++--- widget/gtk/nsGtkKeyUtils.cpp | 11 +- widget/gtk/nsIdleServiceGTK.cpp | 4 +- widget/gtk/nsScreenManagerGtk.cpp | 10 +- widget/gtk/nsWindow.cpp | 130 ++++----- xpcom/base/CycleCollectedJSRuntime.cpp | 2 +- 71 files changed, 841 insertions(+), 465 deletions(-) create mode 100644 dom/permission/PermissionStatus.cpp create mode 100644 dom/permission/PermissionStatus.h create mode 100644 dom/permission/Permissions.cpp create mode 100644 dom/permission/Permissions.h create mode 100644 dom/webidl/PermissionStatus.webidl create mode 100644 dom/webidl/Permissions.webidl diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index b8efa800e2..3d72b264f6 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -360,9 +360,9 @@ pref("browser.dom.window.dump.enabled", false); // Default Content Security Policy to apply to certified apps. // If you change this CSP, make sure to update the fast path in nsCSPService.cpp -pref("security.apps.certified.CSP.default", "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline' app://theme.gaiamobile.org"); +pref("security.apps.certified.CSP.default", "default-src * data: blob:; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline' app://theme.gaiamobile.org"); // Default Content Security Policy to apply to trusted apps. -pref("security.apps.trusted.CSP.default", "default-src *; object-src 'none'; frame-src 'none'"); +pref("security.apps.trusted.CSP.default", "default-src * data: blob:; object-src 'none'; frame-src 'none'"); // Temporarily force-enable GL compositing. This is default-disabled // deep within the bowels of the widgetry system. Remove me when GL diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 634bf7754d..f7d4fa4a8b 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -40,6 +40,7 @@ #include "mozilla/dom/IccManager.h" #include "mozilla/dom/InputPortManager.h" #include "mozilla/dom/MobileMessageManager.h" +#include "mozilla/dom/Permissions.h" #include "mozilla/dom/ServiceWorkerContainer.h" #include "mozilla/dom/Telephony.h" #include "mozilla/dom/Voicemail.h" @@ -169,8 +170,9 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Navigator) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMimeTypes) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager) @@ -212,12 +214,14 @@ Navigator::Invalidate() // Don't clear mWindow here so we know we've got a non-null mWindow // until we're unlinked. + mMimeTypes = nullptr; + if (mPlugins) { mPlugins->Invalidate(); mPlugins = nullptr; } - mMimeTypes = nullptr; + mPermissions = nullptr; // If there is a page transition, make sure delete the geolocation object. if (mGeolocation) { @@ -553,6 +557,21 @@ Navigator::GetPlugins(ErrorResult& aRv) return mPlugins; } +Permissions* +Navigator::GetPermissions(ErrorResult& aRv) +{ + if (!mWindow) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } + + if (!mPermissions) { + mPermissions = new Permissions(mWindow); + } + + return mPermissions; +} + // Values for the network.cookie.cookieBehavior pref are documented in // nsCookieService.cpp. #define COOKIE_BEHAVIOR_REJECT 2 diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h index 5568dda809..84c7e2d871 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -48,6 +48,8 @@ class ServiceWorkerContainer; namespace mozilla { namespace dom { +class Permissions; + namespace battery { class BatteryManager; } // namespace battery @@ -150,6 +152,7 @@ public: const nsAString& aTitle, ErrorResult& aRv); nsMimeTypeArray* GetMimeTypes(ErrorResult& aRv); nsPluginArray* GetPlugins(ErrorResult& aRv); + Permissions* GetPermissions(ErrorResult& aRv); // The XPCOM GetDoNotTrack is ok Geolocation* GetGeolocation(ErrorResult& aRv); battery::BatteryManager* GetBattery(ErrorResult& aRv); @@ -341,6 +344,7 @@ private: nsRefPtr mMimeTypes; nsRefPtr mPlugins; + nsRefPtr mPermissions; nsRefPtr mGeolocation; nsRefPtr mNotification; nsRefPtr mBatteryManager; diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 44e28d9663..c94970eeba 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1096,12 +1096,12 @@ nsJSContext::AddSupportsPrimitiveTojsvals(nsISupports *aArg, JS::Value *aArgv) case nsISupportsPrimitive::TYPE_PRTIME : case nsISupportsPrimitive::TYPE_VOID : { NS_WARNING("Unsupported primitive type used"); - *aArgv = JSVAL_NULL; + aArgv->setNull(); break; } default : { NS_WARNING("Unknown primitive type used"); - *aArgv = JSVAL_NULL; + aArgv->setNull(); break; } } diff --git a/dom/bindings/DOMJSClass.h b/dom/bindings/DOMJSClass.h index 386df7a622..04427b7554 100644 --- a/dom/bindings/DOMJSClass.h +++ b/dom/bindings/DOMJSClass.h @@ -52,25 +52,23 @@ typedef bool (*PropertyEnabled)(JSContext* cx, JSObject* global); template struct Prefable { - inline bool isEnabled(JSContext* cx, JSObject* obj) const { + inline bool isEnabled(JSContext* cx, JS::Handle obj) const { if (!enabled) { return false; } if (!enabledFunc && !availableFunc && !checkPermissions) { return true; } - // Just go ahead and root obj, in case enabledFunc GCs - JS::Rooted rootedObj(cx, obj); if (enabledFunc && - !enabledFunc(cx, js::GetGlobalForObjectCrossCompartment(rootedObj))) { + !enabledFunc(cx, js::GetGlobalForObjectCrossCompartment(obj))) { return false; } if (availableFunc && - !availableFunc(cx, js::GetGlobalForObjectCrossCompartment(rootedObj))) { + !availableFunc(cx, js::GetGlobalForObjectCrossCompartment(obj))) { return false; } if (checkPermissions && - !CheckPermissions(cx, js::GetGlobalForObjectCrossCompartment(rootedObj), + !CheckPermissions(cx, js::GetGlobalForObjectCrossCompartment(obj), checkPermissions)) { return false; } diff --git a/dom/devicestorage/nsDeviceStorage.cpp b/dom/devicestorage/nsDeviceStorage.cpp index 0417d02da2..a55a723fb3 100644 --- a/dom/devicestorage/nsDeviceStorage.cpp +++ b/dom/devicestorage/nsDeviceStorage.cpp @@ -1906,12 +1906,12 @@ nsIFileToJsval(nsPIDOMWindow* aWindow, DeviceStorageFile* aFile) MOZ_ASSERT(aWindow); if (!aFile) { - return JSVAL_NULL; + return JS::NullValue(); } if (aFile->mEditable) { // TODO - needs janv's file handle support. - return JSVAL_NULL; + return JS::NullValue(); } nsString fullPath; @@ -2531,7 +2531,7 @@ public: } AutoJSContext cx; - JS::Rooted result(cx, JSVAL_NULL); + JS::Rooted result(cx, JS::NullValue()); if (mFile) { result = nsIFileToJsval(window, mFile); diff --git a/dom/indexedDB/IndexedDatabaseManager.cpp b/dom/indexedDB/IndexedDatabaseManager.cpp index f9cde64759..805fd5dc64 100644 --- a/dom/indexedDB/IndexedDatabaseManager.cpp +++ b/dom/indexedDB/IndexedDatabaseManager.cpp @@ -131,6 +131,11 @@ const char kPrefExperimental[] = IDB_PREF_BRANCH_ROOT "experimental"; const char kPrefLoggingEnabled[] = IDB_PREF_LOGGING_BRANCH_ROOT "enabled"; const char kPrefLoggingDetails[] = IDB_PREF_LOGGING_BRANCH_ROOT "details"; +#if defined(DEBUG) || defined(MOZ_ENABLE_PROFILER_SPS) +const char kPrefLoggingProfiler[] = + IDB_PREF_LOGGING_BRANCH_ROOT "profiler-marks"; +#endif + #undef IDB_PREF_LOGGING_BRANCH_ROOT #undef IDB_PREF_BRANCH_ROOT @@ -329,6 +334,10 @@ IndexedDatabaseManager::Init() Preferences::RegisterCallback(LoggingModePrefChangedCallback, kPrefLoggingDetails); +#ifdef MOZ_ENABLE_PROFILER_SPS + Preferences::RegisterCallback(LoggingModePrefChangedCallback, + kPrefLoggingProfiler); +#endif Preferences::RegisterCallbackAndCall(LoggingModePrefChangedCallback, kPrefLoggingEnabled); @@ -353,6 +362,10 @@ IndexedDatabaseManager::Destroy() Preferences::UnregisterCallback(LoggingModePrefChangedCallback, kPrefLoggingDetails); +#ifdef MOZ_ENABLE_PROFILER_SPS + Preferences::UnregisterCallback(LoggingModePrefChangedCallback, + kPrefLoggingProfiler); +#endif Preferences::UnregisterCallback(LoggingModePrefChangedCallback, kPrefLoggingEnabled); diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 9b678a2c3c..aced4e9cf7 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -475,7 +475,7 @@ TabChildBase::DispatchMessageManagerMessage(const nsAString& aMessageName, const nsAString& aJSONData) { AutoSafeJSContext cx; - JS::Rooted json(cx, JSVAL_NULL); + JS::Rooted json(cx, JS::NullValue()); StructuredCloneData cloneData; JSAutoStructuredCloneBuffer buffer; if (JS_ParseJSON(cx, diff --git a/dom/mobilemessage/MobileMessageCallback.cpp b/dom/mobilemessage/MobileMessageCallback.cpp index c4555fcc47..ae53ac632f 100644 --- a/dom/mobilemessage/MobileMessageCallback.cpp +++ b/dom/mobilemessage/MobileMessageCallback.cpp @@ -186,7 +186,7 @@ MobileMessageCallback::NotifyMessageDeleted(bool *aDeleted, uint32_t aSize) { if (aSize == 1) { AutoJSContext cx; - JS::Rooted val(cx, aDeleted[0] ? JSVAL_TRUE : JSVAL_FALSE); + JS::Rooted val(cx, JS::BooleanValue(*aDeleted)); return NotifySuccess(val); } @@ -215,7 +215,7 @@ NS_IMETHODIMP MobileMessageCallback::NotifyMessageMarkedRead(bool aRead) { AutoJSContext cx; - JS::Rooted val(cx, aRead ? JSVAL_TRUE : JSVAL_FALSE); + JS::Rooted val(cx, JS::BooleanValue(aRead)); return NotifySuccess(val); } diff --git a/dom/permission/PermissionStatus.cpp b/dom/permission/PermissionStatus.cpp new file mode 100644 index 0000000000..862e9be5b5 --- /dev/null +++ b/dom/permission/PermissionStatus.cpp @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/PermissionStatus.h" +#include "mozilla/Services.h" + +#include "nsIPermissionManager.h" + +namespace mozilla { +namespace dom { + +PermissionStatus::PermissionStatus(nsPIDOMWindow* aWindow, + PermissionState aState) + : DOMEventTargetHelper(aWindow) + , mState(aState) +{ +} + +PermissionStatus::~PermissionStatus() +{ +} + +JSObject* +PermissionStatus::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + return PermissionStatusBinding::Wrap(aCx, this, aGivenProto); +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/permission/PermissionStatus.h b/dom/permission/PermissionStatus.h new file mode 100644 index 0000000000..b4c0e1a73e --- /dev/null +++ b/dom/permission/PermissionStatus.h @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_PermissionStatus_h_ +#define mozilla_dom_PermissionStatus_h_ + +#include "mozilla/dom/PermissionStatusBinding.h" +#include "mozilla/DOMEventTargetHelper.h" + +namespace mozilla { +namespace dom { + +class PermissionStatus final + : public DOMEventTargetHelper +{ +public: + explicit PermissionStatus(nsPIDOMWindow* aWindow, PermissionState aState); + + JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + + PermissionState State() const { return mState; } + + IMPL_EVENT_HANDLER(change) + +private: + ~PermissionStatus(); + + PermissionState mState; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_permissionstatus_h_ diff --git a/dom/permission/Permissions.cpp b/dom/permission/Permissions.cpp new file mode 100644 index 0000000000..c7518f9983 --- /dev/null +++ b/dom/permission/Permissions.cpp @@ -0,0 +1,160 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/Permissions.h" + +#include "mozilla/dom/PermissionsBinding.h" +#include "mozilla/dom/Promise.h" +#include "mozilla/Services.h" + +#include "nsIPermissionManager.h" + +namespace mozilla { +namespace dom { + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Permissions) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(Permissions) +NS_IMPL_CYCLE_COLLECTING_RELEASE(Permissions) + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Permissions, mWindow) + +Permissions::Permissions(nsPIDOMWindow* aWindow) + : mWindow(aWindow) +{ +} + +Permissions::~Permissions() +{ +} + +JSObject* +Permissions::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + return PermissionsBinding::Wrap(aCx, this, aGivenProto); +} + +namespace { + +PermissionState +ActionToPermissionState(uint32_t aAction) +{ + switch (aAction) { + case nsIPermissionManager::ALLOW_ACTION: + return PermissionState::Granted; + + case nsIPermissionManager::DENY_ACTION: + return PermissionState::Denied; + + default: + case nsIPermissionManager::PROMPT_ACTION: + return PermissionState::Prompt; + } +} + +nsresult +CheckPermission(const char* aName, + nsPIDOMWindow* aWindow, + PermissionState& aResult) +{ + MOZ_ASSERT(aName); + MOZ_ASSERT(aWindow); + + nsCOMPtr permMgr = services::GetPermissionManager(); + if (NS_WARN_IF(!permMgr)) { + return NS_ERROR_FAILURE; + } + + uint32_t action = nsIPermissionManager::DENY_ACTION; + nsresult rv = permMgr->TestPermissionFromWindow(aWindow, aName, &action); + if (NS_WARN_IF(NS_FAILED(rv))) { + return NS_ERROR_FAILURE; + } + + aResult = ActionToPermissionState(action); + return NS_OK; +} + +nsresult +CheckPushPermission(JSContext* aCx, + JS::Handle aPermission, + nsPIDOMWindow* aWindow, + PermissionState& aResult) +{ + PushPermissionDescriptor permission; + JS::Rooted value(aCx, JS::ObjectOrNullValue(aPermission)); + if (NS_WARN_IF(!permission.Init(aCx, value))) { + return NS_ERROR_UNEXPECTED; + } + + if (permission.mUserVisible) { + return NS_ERROR_NOT_IMPLEMENTED; + } + + return CheckPermission("push", aWindow, aResult); +} + +nsresult +CheckPermission(JSContext* aCx, + JS::Handle aPermission, + nsPIDOMWindow* aWindow, + PermissionState& aResult) +{ + PermissionDescriptor permission; + JS::Rooted value(aCx, JS::ObjectOrNullValue(aPermission)); + if (NS_WARN_IF(!permission.Init(aCx, value))) { + return NS_ERROR_UNEXPECTED; + } + + switch (permission.mName) { + case PermissionName::Geolocation: + return CheckPermission("geo", aWindow, aResult); + + case PermissionName::Notifications: + return CheckPermission("desktop-notification", aWindow, aResult); + + case PermissionName::Push: + return CheckPushPermission(aCx, aPermission, aWindow, aResult); + + case PermissionName::Midi: + default: + return NS_ERROR_NOT_IMPLEMENTED; + } +} + +} // namespace + +already_AddRefed +Permissions::Query(JSContext* aCx, + JS::Handle aPermission, + ErrorResult& aRv) +{ + nsCOMPtr global = do_QueryInterface(mWindow); + if (!global) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } + + nsRefPtr promise = Promise::Create(global, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + PermissionState state = PermissionState::Denied; + nsresult rv = CheckPermission(aCx, aPermission, mWindow, state); + if (NS_WARN_IF(NS_FAILED(rv))) { + promise->MaybeReject(rv); + } else { + promise->MaybeResolve(new PermissionStatus(mWindow, state)); + } + return promise.forget(); +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/permission/Permissions.h b/dom/permission/Permissions.h new file mode 100644 index 0000000000..e57c236d72 --- /dev/null +++ b/dom/permission/Permissions.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_Permissions_h_ +#define mozilla_dom_Permissions_h_ + +#include "nsISupports.h" +#include "nsPIDOMWindow.h" +#include "nsWrapperCache.h" + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class Promise; + +class Permissions final + : public nsISupports + , public nsWrapperCache +{ +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Permissions) + + explicit Permissions(nsPIDOMWindow* aWindow); + + nsPIDOMWindow* GetParentObject() const { return mWindow; } + + JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + + already_AddRefed Query(JSContext* aCx, + JS::Handle aPermission, + ErrorResult& aRv); + +private: + ~Permissions(); + + nsCOMPtr mWindow; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_permissions_h_ diff --git a/dom/permission/moz.build b/dom/permission/moz.build index f17b89f2ec..b027459d55 100644 --- a/dom/permission/moz.build +++ b/dom/permission/moz.build @@ -4,6 +4,16 @@ # 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/. +EXPORTS.mozilla.dom += [ + 'Permissions.h', + 'PermissionStatus.h', +] + +UNIFIED_SOURCES += [ + 'Permissions.cpp', + 'PermissionStatus.cpp', +] + EXTRA_COMPONENTS += [ 'PermissionPromptService.js', 'PermissionPromptService.manifest', @@ -33,3 +43,7 @@ if CONFIG['MOZ_WEBSMS_BACKEND']: if CONFIG['MOZ_TIME_MANAGER']: MOCHITEST_MANIFESTS += ['tests/mochitest-time.ini'] + +FAIL_ON_WARNINGS = True + +FINAL_LIBRARY = 'xul' diff --git a/dom/plugins/base/nsJSNPRuntime.cpp b/dom/plugins/base/nsJSNPRuntime.cpp index 06ec12402a..305edda031 100644 --- a/dom/plugins/base/nsJSNPRuntime.cpp +++ b/dom/plugins/base/nsJSNPRuntime.cpp @@ -489,7 +489,7 @@ NPVariantToJSVal(NPP npp, JSContext* cx, const NPVariant* variant) case NPVariantType_Void : return JS::UndefinedValue(); case NPVariantType_Null : - return JSVAL_NULL; + return JS::NullValue(); case NPVariantType_Bool : return JS::BooleanValue(NPVARIANT_TO_BOOLEAN(*variant)); case NPVariantType_Int32 : diff --git a/dom/security/nsCSPService.cpp b/dom/security/nsCSPService.cpp index 028a718340..27e8a6bc99 100644 --- a/dom/security/nsCSPService.cpp +++ b/dom/security/nsCSPService.cpp @@ -158,7 +158,7 @@ CSPService::ShouldLoad(uint32_t aContentType, if (status == nsIPrincipal::APP_STATUS_CERTIFIED) { // The CSP for certified apps is : - // "default-src *; script-src 'self'; object-src 'none'; style-src 'self' app://theme.gaiamobile.org:*" + // "default-src * data: blob:; script-src 'self'; object-src 'none'; style-src 'self' app://theme.gaiamobile.org:*" // That means we can optimize for this case by: // - loading same origin scripts and stylesheets, and stylesheets from the // theme url space. diff --git a/dom/system/OSFileConstants.cpp b/dom/system/OSFileConstants.cpp index f0e58f3f93..ed8d8a2aec 100644 --- a/dom/system/OSFileConstants.cpp +++ b/dom/system/OSFileConstants.cpp @@ -914,7 +914,7 @@ bool DefineOSFileConstants(JSContext *cx, JS::Handle global) #endif // defined(MOZ_WIDGET_GONK) #if defined(DEBUG) - JS::Rooted valDebug(cx, JSVAL_TRUE); + JS::Rooted valDebug(cx, JS::TrueValue()); if (!JS_SetProperty(cx, objSys, "DEBUG", valDebug)) { return false; } diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html index 12d1444dfd..271f4eaade 100644 --- a/dom/tests/mochitest/general/test_interfaces.html +++ b/dom/tests/mochitest/general/test_interfaces.html @@ -857,8 +857,12 @@ var interfaceNamesInGlobalScope = "PerformanceTiming", // IMPORTANT: Do not change this list without review from a DOM peer! "PeriodicWave", +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "Permissions", nightly: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "PermissionSettings", b2g: true, permission: ["permissions"]}, +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "PermissionStatus", nightly: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "PhoneNumberService", permission: ["phonenumberservice"]}, // IMPORTANT: Do not change this list without review from a DOM peer! diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index 6257a66764..d30e87b6c0 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -96,6 +96,11 @@ interface NavigatorFeatures { Promise hasFeature(DOMString name); }; +partial interface Navigator { + [Throws, Pref="dom.permissions.enabled"] + readonly attribute Permissions permissions; +}; + // Things that definitely need to be in the spec and and are not for some // reason. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=22406 partial interface Navigator { diff --git a/dom/webidl/PermissionStatus.webidl b/dom/webidl/PermissionStatus.webidl new file mode 100644 index 0000000000..27ae490c39 --- /dev/null +++ b/dom/webidl/PermissionStatus.webidl @@ -0,0 +1,21 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * https://w3c.github.io/permissions/#status-of-a-permission + */ + +enum PermissionState { + "granted", + "denied", + "prompt" +}; + +[Exposed=(Window), + Pref="dom.permissions.enabled"] +interface PermissionStatus : EventTarget { + readonly attribute PermissionState state; + attribute EventHandler onchange; +}; diff --git a/dom/webidl/Permissions.webidl b/dom/webidl/Permissions.webidl new file mode 100644 index 0000000000..fa1f6d874a --- /dev/null +++ b/dom/webidl/Permissions.webidl @@ -0,0 +1,30 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * https://w3c.github.io/permissions/#permissions-interface + */ + +enum PermissionName { + "geolocation", + "notifications", + "push", + "midi" +}; + +dictionary PermissionDescriptor { + required PermissionName name; +}; + +dictionary PushPermissionDescriptor : PermissionDescriptor { + boolean userVisible = false; +}; + +[Exposed=(Window), + Pref="dom.permissions.enabled"] +interface Permissions { + [Throws] + Promise query(object permission); +}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index b2409c45b9..aee804dc32 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -347,7 +347,9 @@ WEBIDL_FILES = [ 'PerformanceResourceTiming.webidl', 'PerformanceTiming.webidl', 'PeriodicWave.webidl', + 'Permissions.webidl', 'PermissionSettings.webidl', + 'PermissionStatus.webidl', 'PhoneNumberService.webidl', 'Plugin.webidl', 'PluginArray.webidl', diff --git a/dom/workers/XMLHttpRequest.cpp b/dom/workers/XMLHttpRequest.cpp index ac41871fb8..8f9f42eadf 100644 --- a/dom/workers/XMLHttpRequest.cpp +++ b/dom/workers/XMLHttpRequest.cpp @@ -1184,7 +1184,7 @@ EventRunnable::PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate) if (NS_SUCCEEDED(mResponseTextResult)) { mResponseResult = mResponseTextResult; if (mResponseText.IsVoid()) { - mResponse = JSVAL_NULL; + mResponse.setNull(); } } else { diff --git a/dom/workers/XMLHttpRequest.h b/dom/workers/XMLHttpRequest.h index 9475d9ad33..7f0d8b60b3 100644 --- a/dom/workers/XMLHttpRequest.h +++ b/dom/workers/XMLHttpRequest.h @@ -250,7 +250,7 @@ public: NullResponseText() { mStateData.mResponseText.SetIsVoid(true); - mStateData.mResponse = JSVAL_NULL; + mStateData.mResponse.setNull(); } bool MozAnon() const diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index b86279f97c..c409b2bcd5 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -2388,12 +2388,6 @@ gfxPlatform::UsesOffMainThreadCompositing() // Linux users who chose OpenGL are being grandfathered in to OMTC result |= gfxPrefs::LayersAccelerationForceEnabled(); -#if !defined(NIGHTLY_BUILD) - // Yeah, these two env vars do the same thing. - // I'm told that one of them is enabled on some test slaves config, - // so be slightly careful if you think you can remove one of them. - result &= PR_GetEnv("MOZ_USE_OMTC") || PR_GetEnv("MOZ_OMTC_ENABLED"); -#endif #endif firstTime = false; } diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp index 59c15c37f1..61f2bdccc2 100644 --- a/gfx/thebes/gfxPlatformGtk.cpp +++ b/gfx/thebes/gfxPlatformGtk.cpp @@ -70,7 +70,8 @@ gfxPlatformGtk::gfxPlatformGtk() } #ifdef MOZ_X11 - sUseXRender = mozilla::Preferences::GetBool("gfx.xrender.enabled"); + sUseXRender = (GDK_IS_X11_DISPLAY(gdk_display_get_default())) ? + mozilla::Preferences::GetBool("gfx.xrender.enabled") : false; #endif uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO) | BackendTypeBit(BackendType::SKIA); @@ -372,11 +373,15 @@ gfxPlatformGtk::GetPlatformCMSOutputProfile(void *&mem, size_t &size) size = 0; #ifdef MOZ_X11 + GdkDisplay *display = gdk_display_get_default(); + if (!GDK_IS_X11_DISPLAY(display)) + return; + const char EDID1_ATOM_NAME[] = "XFree86_DDC_EDID1_RAWDATA"; const char ICC_PROFILE_ATOM_NAME[] = "_ICC_PROFILE"; Atom edidAtom, iccAtom; - Display *dpy = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + Display *dpy = GDK_DISPLAY_XDISPLAY(display); // In xpcshell tests, we never initialize X and hence don't have a Display. // In this case, there's no output colour management to be done, so we just // return with nullptr. diff --git a/ipc/testshell/XPCShellEnvironment.cpp b/ipc/testshell/XPCShellEnvironment.cpp index 89ecfa6a9f..1580c4197d 100644 --- a/ipc/testshell/XPCShellEnvironment.cpp +++ b/ipc/testshell/XPCShellEnvironment.cpp @@ -196,15 +196,6 @@ Version(JSContext *cx, return true; } -static bool -BuildDate(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - fprintf(stdout, "built on %s at %s\n", __DATE__, __TIME__); - args.rval().setUndefined(); - return true; -} - static bool Quit(JSContext *cx, unsigned argc, @@ -274,7 +265,6 @@ const JSFunctionSpec gGlobalFunctions[] = JS_FS("load", Load, 1,0), JS_FS("quit", Quit, 0,0), JS_FS("version", Version, 1,0), - JS_FS("build", BuildDate, 0,0), JS_FS("dumpXPC", DumpXPC, 1,0), JS_FS("dump", Dump, 1,0), JS_FS("gc", GC, 0,0), @@ -377,7 +367,7 @@ XPCShellEnvironment::ProcessFile(JSContext *cx, JSErrorReporter older; ok = JS_ExecuteScript(cx, script, &result); - if (ok && result != JSVAL_VOID) { + if (ok && !result.isUndefined()) { /* Suppress error reports from JS::ToString(). */ older = JS_SetErrorReporter(JS_GetRuntime(cx), nullptr); str = JS::ToString(cx, result); @@ -594,7 +584,7 @@ XPCShellEnvironment::EvaluateString(const nsString& aString, JS::Rooted result(cx); bool ok = JS_ExecuteScript(cx, script, &result); - if (ok && result != JSVAL_VOID) { + if (ok && !result.isUndefined()) { JSErrorReporter old = JS_SetErrorReporter(JS_GetRuntime(cx), nullptr); JSString* str = JS::ToString(cx, result); nsAutoJSString autoStr; diff --git a/js/ipc/JavaScriptShared.cpp b/js/ipc/JavaScriptShared.cpp index 9a6168d2c2..a22020f0dc 100644 --- a/js/ipc/JavaScriptShared.cpp +++ b/js/ipc/JavaScriptShared.cpp @@ -265,7 +265,7 @@ JavaScriptShared::toVariant(JSContext* cx, JS::HandleValue from, JSVariant* to) { RootedObject obj(cx, from.toObjectOrNull()); if (!obj) { - MOZ_ASSERT(from == JSVAL_NULL); + MOZ_ASSERT(from.isNull()); *to = NullVariant(); return true; } diff --git a/js/public/Value.h b/js/public/Value.h index 0a35198460..5ac7384a5a 100644 --- a/js/public/Value.h +++ b/js/public/Value.h @@ -1673,6 +1673,7 @@ class ValueOperations bool isFalse() const { return value()->isFalse(); } bool isNumber() const { return value()->isNumber(); } bool isInt32() const { return value()->isInt32(); } + bool isInt32(int32_t i32) const { return value()->isInt32(i32); } bool isDouble() const { return value()->isDouble(); } bool isString() const { return value()->isString(); } bool isSymbol() const { return value()->isSymbol(); } @@ -1966,17 +1967,6 @@ UINT_TO_JSVAL(uint32_t i) : DOUBLE_TO_JSVAL((double)i); } -// JS constants. For efficiency, prefer predicates (e.g. v.isNull()) and -// constructing values from scratch (e.g. Int32Value(0)). These constants are -// stored in memory and initialized at startup, so testing against them and -// using them requires memory loads and will be correspondingly slow. -extern JS_PUBLIC_DATA(const jsval) JSVAL_NULL; -extern JS_PUBLIC_DATA(const jsval) JSVAL_ZERO; -extern JS_PUBLIC_DATA(const jsval) JSVAL_ONE; -extern JS_PUBLIC_DATA(const jsval) JSVAL_FALSE; -extern JS_PUBLIC_DATA(const jsval) JSVAL_TRUE; -extern JS_PUBLIC_DATA(const jsval) JSVAL_VOID; - namespace JS { extern JS_PUBLIC_DATA(const HandleValue) NullHandleValue; diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index 9de74b0c6b..ea1f6d37dd 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -1889,7 +1889,8 @@ InitTypeClasses(JSContext* cx, HandleObject ctypesObj) // Create objects representing the special types void_t and voidptr_t. RootedObject typeObj(cx, CType::DefineBuiltin(cx, ctypesObj, "void_t", CTypeProto, CDataProto, "void", - TYPE_void_t, JSVAL_VOID, JSVAL_VOID, &ffi_type_void)); + TYPE_void_t, JS::UndefinedValue(), JS::UndefinedValue(), + &ffi_type_void)); if (!typeObj) return false; @@ -4186,7 +4187,7 @@ CType::GetSafeSize(JSObject* obj, size_t* result) jsval size = JS_GetReservedSlot(obj, SLOT_SIZE); - // The "size" property can be an int, a double, or JSVAL_VOID + // The "size" property can be an int, a double, or JS::UndefinedValue() // (for arrays of undefined length), and must always fit in a size_t. if (size.isInt32()) { *result = size.toInt32(); @@ -4210,9 +4211,10 @@ CType::GetSize(JSObject* obj) MOZ_ASSERT(!size.isUndefined()); - // The "size" property can be an int, a double, or JSVAL_VOID + // The "size" property can be an int, a double, or JS::UndefinedValue() // (for arrays of undefined length), and must always fit in a size_t. - // For callers who know it can never be JSVAL_VOID, return a size_t directly. + // For callers who know it can never be JS::UndefinedValue(), return a size_t + // directly. if (size.isInt32()) return size.toInt32(); return Convert(size.toDouble()); @@ -4225,7 +4227,7 @@ CType::IsSizeDefined(JSObject* obj) jsval size = JS_GetReservedSlot(obj, SLOT_SIZE); - // The "size" property can be an int, a double, or JSVAL_VOID + // The "size" property can be an int, a double, or JS::UndefinedValue() // (for arrays of undefined length), and must always fit in a size_t. MOZ_ASSERT(size.isInt32() || size.isDouble() || size.isUndefined()); return !size.isUndefined(); @@ -4704,7 +4706,7 @@ PointerType::ConstructData(JSContext* cx, // The third argument is an optional error sentinel that js-ctypes will return // if an exception is raised while executing the closure. The type must match // the return type of the callback. - jsval errVal = JSVAL_VOID; + Value errVal = JS::UndefinedValue(); if (args.length() == 3) errVal = args[2]; @@ -4925,8 +4927,8 @@ ArrayType::CreateInternal(JSContext* cx, return nullptr; } - RootedValue sizeVal(cx, JSVAL_VOID); - RootedValue lengthVal(cx, JSVAL_VOID); + RootedValue sizeVal(cx, JS::UndefinedValue()); + RootedValue lengthVal(cx, JS::UndefinedValue()); if (lengthDefined) { // Check for overflow, and convert to an int or double as required. size_t size = length * baseSize; @@ -5079,7 +5081,7 @@ ArrayType::GetSafeLength(JSObject* obj, size_t* result) jsval length = JS_GetReservedSlot(obj, SLOT_LENGTH); - // The "length" property can be an int, a double, or JSVAL_VOID + // The "length" property can be an int, a double, or JS::UndefinedValue() // (for arrays of undefined length), and must always fit in a size_t. if (length.isInt32()) { *result = length.toInt32(); @@ -5104,9 +5106,10 @@ ArrayType::GetLength(JSObject* obj) MOZ_ASSERT(!length.isUndefined()); - // The "length" property can be an int, a double, or JSVAL_VOID + // The "length" property can be an int, a double, or JS::UndefinedValue() // (for arrays of undefined length), and must always fit in a size_t. - // For callers who know it can never be JSVAL_VOID, return a size_t directly. + // For callers who know it can never be JS::UndefinedValue(), return a size_t + // directly. if (length.isInt32()) return length.toInt32(); return Convert(length.toDouble()); @@ -5436,7 +5439,8 @@ StructType::Create(JSContext* cx, unsigned argc, jsval* vp) // non-instantiable as CData, will have no 'prototype' property, and will // have undefined size and alignment and no ffi_type. RootedObject result(cx, CType::Create(cx, typeProto, nullptr, TYPE_struct, - name.toString(), JSVAL_VOID, JSVAL_VOID, nullptr)); + name.toString(), JS::UndefinedValue(), + JS::UndefinedValue(), nullptr)); if (!result) return false; @@ -6402,7 +6406,8 @@ FunctionType::CreateInternal(JSContext* cx, // Create a new CType object with the common properties and slots. RootedObject typeObj(cx, CType::Create(cx, typeProto, dataProto, TYPE_function, - nullptr, JSVAL_VOID, JSVAL_VOID, nullptr)); + nullptr, JS::UndefinedValue(), + JS::UndefinedValue(), nullptr)); if (!typeObj) return nullptr; @@ -7927,7 +7932,7 @@ CDataFinalizer::Methods::Dispose(JSContext* cx, unsigned argc, jsval* vp) MOZ_ASSERT(CType::GetTypeCode(objCodeType) == TYPE_function); RootedObject resultType(cx, FunctionType::GetFunctionInfo(objCodeType)->mReturnType); - RootedValue result(cx, JSVAL_VOID); + RootedValue result(cx, JS::UndefinedValue()); int errnoStatus; #if defined(XP_WIN) @@ -8005,7 +8010,7 @@ CDataFinalizer::Cleanup(CDataFinalizer::Private* p, JSObject* obj) JS_SetPrivate(obj, nullptr); for (int i = 0; i < CDATAFINALIZER_SLOTS; ++i) { - JS_SetReservedSlot(obj, i, JSVAL_NULL); + JS_SetReservedSlot(obj, i, JS::NullValue()); } } diff --git a/js/src/jsapi-tests/testArgumentsObject.cpp b/js/src/jsapi-tests/testArgumentsObject.cpp index 754fea580f..5880d21cea 100644 --- a/js/src/jsapi-tests/testArgumentsObject.cpp +++ b/js/src/jsapi-tests/testArgumentsObject.cpp @@ -94,7 +94,7 @@ ExhaustiveTest(const char funcode[]) for (size_t k = 0; k < j; k++) CHECK_SAME(elems[k], INT_TO_JSVAL(i + k)); for (size_t k = j; k < MAX_ELEMS - 1; k++) - CHECK_SAME(elems[k], JSVAL_NULL); + CHECK(elems[k].isNull()); CHECK_SAME(elems[MAX_ELEMS - 1], INT_TO_JSVAL(42)); } } diff --git a/js/src/jsapi-tests/testArrayBuffer.cpp b/js/src/jsapi-tests/testArrayBuffer.cpp index 693d6ce5f2..f83a2b3698 100644 --- a/js/src/jsapi-tests/testArrayBuffer.cpp +++ b/js/src/jsapi-tests/testArrayBuffer.cpp @@ -68,9 +68,9 @@ BEGIN_TEST(testArrayBuffer_bug720949_steal) CHECK(JS_GetProperty(cx, view, "length", &v)); CHECK_SAME(v, INT_TO_JSVAL(0)); CHECK_EQUAL(JS_GetArrayBufferByteLength(obj), 0u); - v = JSVAL_VOID; + v.setUndefined(); JS_GetElement(cx, obj, 0, &v); - CHECK_SAME(v, JSVAL_VOID); + CHECK(v.isUndefined()); // Transfer to a new ArrayBuffer JS::RootedObject dst(cx, JS_NewArrayBufferWithContents(cx, size, contents)); diff --git a/js/src/jsapi-tests/testDeepFreeze.cpp b/js/src/jsapi-tests/testDeepFreeze.cpp index efc7183ebb..d6623775f6 100644 --- a/js/src/jsapi-tests/testDeepFreeze.cpp +++ b/js/src/jsapi-tests/testDeepFreeze.cpp @@ -14,7 +14,7 @@ BEGIN_TEST(testDeepFreeze_bug535703) JS::RootedObject obj(cx, v.toObjectOrNull()); CHECK(JS_DeepFreezeObject(cx, obj)); // don't crash EVAL("Object.isFrozen(x)", &v); - CHECK_SAME(v, JSVAL_TRUE); + CHECK(v.isTrue()); return true; } END_TEST(testDeepFreeze_bug535703) @@ -33,9 +33,9 @@ BEGIN_TEST(testDeepFreeze_deep) JS::RootedValue b(cx); EVAL("Object.isFrozen(a)", &b); - CHECK_SAME(b, JSVAL_TRUE); + CHECK(b.isTrue()); EVAL("Object.isFrozen(o)", &b); - CHECK_SAME(b, JSVAL_TRUE); + CHECK(b.isTrue()); return true; } END_TEST(testDeepFreeze_deep) @@ -52,9 +52,9 @@ BEGIN_TEST(testDeepFreeze_loop) JS::RootedValue b(cx); EVAL("Object.isFrozen(x)", &b); - CHECK_SAME(b, JSVAL_TRUE); + CHECK(b.isTrue()); EVAL("Object.isFrozen(y)", &b); - CHECK_SAME(b, JSVAL_TRUE); + CHECK(b.isTrue()); return true; } END_TEST(testDeepFreeze_loop) diff --git a/js/src/jsapi-tests/testFunctionProperties.cpp b/js/src/jsapi-tests/testFunctionProperties.cpp index 20a098ccc4..e79f5ec288 100644 --- a/js/src/jsapi-tests/testFunctionProperties.cpp +++ b/js/src/jsapi-tests/testFunctionProperties.cpp @@ -16,10 +16,10 @@ BEGIN_TEST(testFunctionProperties) JS::RootedValue y(cx); CHECK(JS_GetProperty(cx, obj, "arguments", &y)); - CHECK_SAME(y, JSVAL_NULL); + CHECK(y.isNull()); CHECK(JS_GetProperty(cx, obj, "caller", &y)); - CHECK_SAME(y, JSVAL_NULL); + CHECK(y.isNull()); return true; } diff --git a/js/src/jsapi-tests/testLookup.cpp b/js/src/jsapi-tests/testLookup.cpp index f912a2fac8..09900af720 100644 --- a/js/src/jsapi-tests/testLookup.cpp +++ b/js/src/jsapi-tests/testLookup.cpp @@ -19,7 +19,7 @@ BEGIN_TEST(testLookup_bug522590) // Calling mkobj() multiple times must create multiple functions in ES5. EVAL("mkobj().f !== mkobj().f", &x); - CHECK_SAME(x, JSVAL_TRUE); + CHECK(x.isTrue()); // Now make x.f a method. EVAL("mkobj()", &x); @@ -86,9 +86,9 @@ BEGIN_TEST(testLookup_bug570195) CHECK(JS_DefineProperty(cx, global, "document", obj, 0)); JS::RootedValue v(cx); EVAL("document.all ? true : false", &v); - CHECK_SAME(v, JSVAL_FALSE); + CHECK(v.isFalse()); EVAL("document.hasOwnProperty('all')", &v); - CHECK_SAME(v, JSVAL_TRUE); + CHECK(v.isTrue()); return true; } END_TEST(testLookup_bug570195) diff --git a/js/src/jsapi-tests/testLooselyEqual.cpp b/js/src/jsapi-tests/testLooselyEqual.cpp index 3e09bf86c9..0bbca1a7ae 100644 --- a/js/src/jsapi-tests/testLooselyEqual.cpp +++ b/js/src/jsapi-tests/testLooselyEqual.cpp @@ -55,8 +55,8 @@ struct LooseEqualityData sNaN = DOUBLE_TO_JSVAL(numeric_limits::signaling_NaN()); d42 = DOUBLE_TO_JSVAL(42.0); i42 = INT_TO_JSVAL(42); - undef = JSVAL_VOID; - null = JSVAL_NULL; + undef = JS::UndefinedValue(); + null = JS::NullValue(); obj = OBJECT_TO_JSVAL(JS::CurrentGlobalOrNull(cx)); poszero = DOUBLE_TO_JSVAL(0.0); negzero = DOUBLE_TO_JSVAL(-0.0); diff --git a/js/src/jsapi-tests/testNewObject.cpp b/js/src/jsapi-tests/testNewObject.cpp index d33b33746a..52b97f8600 100644 --- a/js/src/jsapi-tests/testNewObject.cpp +++ b/js/src/jsapi-tests/testNewObject.cpp @@ -106,7 +106,7 @@ BEGIN_TEST(testNewObject_1) obj = JS_New(cx, ctor, JS::HandleValueArray::subarray(argv, 0, 3)); CHECK(obj); CHECK(JS_GetElement(cx, ctor, 0, &v)); - CHECK_SAME(v, JSVAL_ZERO); + CHECK(v.isInt32(0)); return true; } diff --git a/js/src/jsapi-tests/testObjectEmulatingUndefined.cpp b/js/src/jsapi-tests/testObjectEmulatingUndefined.cpp index 54b9ebf279..8ba4b4b634 100644 --- a/js/src/jsapi-tests/testObjectEmulatingUndefined.cpp +++ b/js/src/jsapi-tests/testObjectEmulatingUndefined.cpp @@ -29,10 +29,10 @@ BEGIN_TEST(testObjectEmulatingUndefined_truthy) JS::RootedValue result(cx); EVAL("if (new ObjectEmulatingUndefined()) true; else false;", &result); - CHECK_SAME(result, JSVAL_FALSE); + CHECK(result.isFalse()); EVAL("if (!new ObjectEmulatingUndefined()) true; else false;", &result); - CHECK_SAME(result, JSVAL_TRUE); + CHECK(result.isTrue()); EVAL("var obj = new ObjectEmulatingUndefined(); \n" "var res = []; \n" @@ -40,7 +40,7 @@ BEGIN_TEST(testObjectEmulatingUndefined_truthy) " res.push(Boolean(obj)); \n" "res.every(function(v) { return v === false; });", &result); - CHECK_SAME(result, JSVAL_TRUE); + CHECK(result.isTrue()); return true; } @@ -55,16 +55,16 @@ BEGIN_TEST(testObjectEmulatingUndefined_equal) JS::RootedValue result(cx); EVAL("if (new ObjectEmulatingUndefined() == undefined) true; else false;", &result); - CHECK_SAME(result, JSVAL_TRUE); + CHECK(result.isTrue()); EVAL("if (new ObjectEmulatingUndefined() == null) true; else false;", &result); - CHECK_SAME(result, JSVAL_TRUE); + CHECK(result.isTrue()); EVAL("if (new ObjectEmulatingUndefined() != undefined) true; else false;", &result); - CHECK_SAME(result, JSVAL_FALSE); + CHECK(result.isFalse()); EVAL("if (new ObjectEmulatingUndefined() != null) true; else false;", &result); - CHECK_SAME(result, JSVAL_FALSE); + CHECK(result.isFalse()); EVAL("var obj = new ObjectEmulatingUndefined(); \n" "var res = []; \n" @@ -72,7 +72,7 @@ BEGIN_TEST(testObjectEmulatingUndefined_equal) " res.push(obj == undefined); \n" "res.every(function(v) { return v === true; });", &result); - CHECK_SAME(result, JSVAL_TRUE); + CHECK(result.isTrue()); EVAL("var obj = new ObjectEmulatingUndefined(); \n" "var res = []; \n" @@ -80,7 +80,7 @@ BEGIN_TEST(testObjectEmulatingUndefined_equal) " res.push(obj == null); \n" "res.every(function(v) { return v === true; });", &result); - CHECK_SAME(result, JSVAL_TRUE); + CHECK(result.isTrue()); EVAL("var obj = new ObjectEmulatingUndefined(); \n" "var res = []; \n" @@ -88,7 +88,7 @@ BEGIN_TEST(testObjectEmulatingUndefined_equal) " res.push(obj != undefined); \n" "res.every(function(v) { return v === false; });", &result); - CHECK_SAME(result, JSVAL_TRUE); + CHECK(result.isTrue()); EVAL("var obj = new ObjectEmulatingUndefined(); \n" "var res = []; \n" @@ -96,7 +96,7 @@ BEGIN_TEST(testObjectEmulatingUndefined_equal) " res.push(obj != null); \n" "res.every(function(v) { return v === false; });", &result); - CHECK_SAME(result, JSVAL_TRUE); + CHECK(result.isTrue()); return true; } diff --git a/js/src/jsapi-tests/testParseJSON.cpp b/js/src/jsapi-tests/testParseJSON.cpp index 538f44e853..aae0f9a43a 100644 --- a/js/src/jsapi-tests/testParseJSON.cpp +++ b/js/src/jsapi-tests/testParseJSON.cpp @@ -39,13 +39,13 @@ BEGIN_TEST(testParseJSON_success) { // Primitives JS::RootedValue expected(cx); - expected = JSVAL_TRUE; + expected = JS::TrueValue(); CHECK(TryParse(cx, "true", expected)); - expected = JSVAL_FALSE; + expected = JS::FalseValue(); CHECK(TryParse(cx, "false", expected)); - expected = JSVAL_NULL; + expected = JS::NullValue(); CHECK(TryParse(cx, "null", expected)); expected = INT_TO_JSVAL(0); @@ -107,16 +107,16 @@ BEGIN_TEST(testParseJSON_success) obj = &v.toObject(); CHECK(JS_IsArrayObject(cx, obj)); CHECK(JS_GetProperty(cx, obj, "length", &v2)); - CHECK_SAME(v2, JSVAL_ZERO); + CHECK(v2.isInt32(0)); CHECK(Parse(cx, "[1]", &v)); CHECK(v.isObject()); obj = &v.toObject(); CHECK(JS_IsArrayObject(cx, obj)); CHECK(JS_GetProperty(cx, obj, "0", &v2)); - CHECK_SAME(v2, JSVAL_ONE); + CHECK(v2.isInt32(1)); CHECK(JS_GetProperty(cx, obj, "length", &v2)); - CHECK_SAME(v2, JSVAL_ONE); + CHECK(v2.isInt32(1)); // Objects @@ -361,7 +361,7 @@ TryParse(JSContext* cx, const char (&input)[N], JS::HandleValue filter) JS::RootedValue v(cx); str = input; CHECK(JS_ParseJSONWithReviver(cx, str.chars(), str.length(), filter, &v)); - CHECK_SAME(v, JSVAL_NULL); + CHECK(v.isNull()); return true; } END_TEST(testParseJSON_reviver) diff --git a/js/src/jsapi-tests/testResolveRecursion.cpp b/js/src/jsapi-tests/testResolveRecursion.cpp index 1cc98e7c87..bd59faeed3 100644 --- a/js/src/jsapi-tests/testResolveRecursion.cpp +++ b/js/src/jsapi-tests/testResolveRecursion.cpp @@ -42,7 +42,7 @@ BEGIN_TEST(testResolveRecursion) /* Start the essence of the test via invoking the first resolve hook. */ JS::RootedValue v(cx); EVAL("obj1.x", &v); - CHECK_SAME(v, JSVAL_FALSE); + CHECK(v.isFalse()); CHECK_EQUAL(resolveEntryCount, 4); CHECK_EQUAL(resolveExitCount, 4); @@ -86,7 +86,7 @@ doResolve(JS::HandleObject obj, JS::HandleId id, bool* resolvedp) /* First resolve hook invocation. */ CHECK_EQUAL(resolveEntryCount, 1); EVAL("obj2.y = true", &v); - CHECK_SAME(v, JSVAL_TRUE); + CHECK(v.isTrue()); CHECK(JS_DefinePropertyById(cx, obj, id, JS::FalseHandleValue, JSPROP_RESOLVING)); *resolvedp = true; return true; @@ -103,7 +103,7 @@ doResolve(JS::HandleObject obj, JS::HandleId id, bool* resolvedp) EVAL("obj1.x", &v); CHECK(v.isUndefined()); EVAL("obj1.y", &v); - CHECK_SAME(v, JSVAL_ZERO); + CHECK(v.isInt32(0)); *resolvedp = true; return true; } @@ -118,7 +118,7 @@ doResolve(JS::HandleObject obj, JS::HandleId id, bool* resolvedp) EVAL("obj2.x", &v); CHECK(v.isUndefined()); EVAL("obj1.y = 0", &v); - CHECK_SAME(v, JSVAL_ZERO); + CHECK(v.isInt32(0)); *resolvedp = true; return true; } diff --git a/js/src/jsapi-tests/testXDR.cpp b/js/src/jsapi-tests/testXDR.cpp index 76960d85c9..7f29f5e31c 100644 --- a/js/src/jsapi-tests/testXDR.cpp +++ b/js/src/jsapi-tests/testXDR.cpp @@ -65,7 +65,7 @@ BEGIN_TEST(testXDR_bug506491) // confirm EVAL("f() === 'ok';\n", &v2); - JS::RootedValue trueval(cx, JSVAL_TRUE); + JS::RootedValue trueval(cx, JS::TrueValue()); CHECK_SAME(v2, trueval); return true; } diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 6dcd5c6338..e6dcf5d1d3 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1434,7 +1434,7 @@ JS_ComputeThis(JSContext* cx, jsval* vp) assertSameCompartment(cx, JSValueArray(vp, 2)); CallReceiver call = CallReceiverFromVp(vp); if (!BoxNonStrictThis(cx, call)) - return JSVAL_NULL; + return NullValue(); return call.thisv(); } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index f8a63d4932..0ebf2de5b6 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2506,7 +2506,7 @@ struct JSPropertyDescriptor { JS::Value value; JSPropertyDescriptor() - : obj(nullptr), attrs(0), getter(nullptr), setter(nullptr), value(JSVAL_VOID) + : obj(nullptr), attrs(0), getter(nullptr), setter(nullptr), value(JS::UndefinedValue()) {} void trace(JSTracer* trc); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 62e379e5e0..570536263a 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -2235,15 +2235,6 @@ DisassWithSrc(JSContext* cx, unsigned argc, jsval* vp) #endif /* DEBUG */ -static bool -BuildDate(JSContext* cx, unsigned argc, jsval* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - fprintf(gOutFile, "built on %s at %s\n", __DATE__, __TIME__); - args.rval().setUndefined(); - return true; -} - static bool Intern(JSContext* cx, unsigned argc, jsval* vp) { @@ -4459,10 +4450,6 @@ static const JSFunctionSpecWithHelp shell_functions[] = { " Similar to the DumpJSStack() function in the browser."), #endif - JS_FN_HELP("build", BuildDate, 0, 0, -"build()", -" Show build date and time."), - JS_FN_HELP("intern", Intern, 1, 0, "intern(str)", " Internalize str in the atom table."), diff --git a/js/src/vm/Value.cpp b/js/src/vm/Value.cpp index a2e41efca5..4f47d9a57f 100644 --- a/js/src/vm/Value.cpp +++ b/js/src/vm/Value.cpp @@ -6,12 +6,10 @@ #include "js/Value.h" -const jsval JSVAL_NULL = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL, 0)); -const jsval JSVAL_ZERO = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32, 0)); -const jsval JSVAL_ONE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32, 1)); -const jsval JSVAL_FALSE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, false)); -const jsval JSVAL_TRUE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, true)); -const jsval JSVAL_VOID = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0)); +static const jsval JSVAL_NULL = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL, 0)); +static const jsval JSVAL_FALSE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, false)); +static const jsval JSVAL_TRUE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, true)); +static const jsval JSVAL_VOID = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0)); namespace JS { diff --git a/js/xpconnect/src/XPCConvert.cpp b/js/xpconnect/src/XPCConvert.cpp index 3f07318e78..367602b717 100644 --- a/js/xpconnect/src/XPCConvert.cpp +++ b/js/xpconnect/src/XPCConvert.cpp @@ -1274,7 +1274,7 @@ XPCConvert::NativeArray2JS(MutableHandleValue d, const void** s, *pErr = NS_ERROR_XPC_BAD_CONVERT_NATIVE; uint32_t i; - RootedValue current(cx, JSVAL_NULL); + RootedValue current(cx, JS::NullValue()); #define POPULATE(_t) \ PR_BEGIN_MACRO \ diff --git a/js/xpconnect/src/XPCShellImpl.cpp b/js/xpconnect/src/XPCShellImpl.cpp index 9623264403..59f9e06d70 100644 --- a/js/xpconnect/src/XPCShellImpl.cpp +++ b/js/xpconnect/src/XPCShellImpl.cpp @@ -30,6 +30,7 @@ #include "nsIScriptSecurityManager.h" #include "nsIPrincipal.h" #include "nsJSUtils.h" +#include "gfxPrefs.h" #include "base/histogram.h" @@ -53,6 +54,8 @@ using namespace mozilla; using namespace JS; +using mozilla::dom::AutoJSAPI; +using mozilla::dom::AutoEntryScript; class XPCShellDirProvider : public nsIDirectoryServiceProvider2 { @@ -96,7 +99,6 @@ static FILE* gErrFile = nullptr; static FILE* gInFile = nullptr; static int gExitCode = 0; -static bool gIgnoreReportedErrors = false; static bool gQuitting = false; static bool reportWarnings = true; static bool compileOnly = false; @@ -365,15 +367,6 @@ Version(JSContext* cx, unsigned argc, jsval* vp) return true; } -static bool -BuildDate(JSContext* cx, unsigned argc, jsval* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - fprintf(gOutFile, "built on %s at %s\n", __DATE__, __TIME__); - args.rval().setUndefined(); - return true; -} - static bool Quit(JSContext* cx, unsigned argc, jsval* vp) { @@ -388,21 +381,6 @@ Quit(JSContext* cx, unsigned argc, jsval* vp) return false; } -// Provide script a way to disable the xpcshell error reporter, preventing -// reported errors from being logged to the console and also from affecting the -// exit code returned by the xpcshell binary. -static bool -IgnoreReportedErrors(JSContext* cx, unsigned argc, jsval* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - if (args.length() != 1 || !args[0].isBoolean()) { - JS_ReportError(cx, "Bad arguments"); - return false; - } - gIgnoreReportedErrors = args[0].toBoolean(); - return true; -} - static bool DumpXPC(JSContext* cx, unsigned argc, jsval* vp) { @@ -631,9 +609,7 @@ static const JSFunctionSpec glob_functions[] = { JS_FS("readline", ReadLine, 1,0), JS_FS("load", Load, 1,0), JS_FS("quit", Quit, 0,0), - JS_FS("ignoreReportedErrors", IgnoreReportedErrors, 1,0), JS_FS("version", Version, 1,0), - JS_FS("build", BuildDate, 0,0), JS_FS("dumpXPC", DumpXPC, 1,0), JS_FS("dump", Dump, 1,0), JS_FS("gc", GC, 0,0), @@ -793,23 +769,45 @@ my_GetErrorMessage(void* userRef, const unsigned errorNumber) return &jsShell_ErrorFormatString[errorNumber]; } -static void -ProcessFile(JSContext *cx, const char *filename, FILE *file, bool forceTTY) +static bool +ProcessLine(AutoJSAPI& jsapi, const char* buffer, int startline) { + JSContext* cx = jsapi.cx(); JS::RootedScript script(cx); JS::RootedValue result(cx); - int lineno, startline; - bool ok, hitEOF; - char* bufp, buffer[4096]; - JSString* str; + JS::CompileOptions options(cx); + options.setFileAndLine("typein", startline) + .setIsRunOnce(true); + if (!JS_CompileScript(cx, buffer, strlen(buffer), options, &script)) + return false; + if (compileOnly) + return true; + if (!JS_ExecuteScript(cx, script, &result)) + return false; + if (result.isUndefined()) + return true; + RootedString str(cx); + if (!(str = ToString(cx, result))) + return false; + JSAutoByteString bytes; + if (!bytes.encodeLatin1(cx, str)) + return false; + + fprintf(gOutFile, "%s\n", bytes.ptr()); + return true; +} + +static bool +ProcessFile(AutoJSAPI& jsapi, const char* filename, FILE* file, bool forceTTY) +{ + JSContext* cx = jsapi.cx(); JS::Rooted global(cx, JS::CurrentGlobalOrNull(cx)); MOZ_ASSERT(global); if (forceTTY) { file = stdin; - } else if (!isatty(fileno(file))) - { + } else if (!isatty(fileno(file))) { /* * It's not interactive - just execute it. * @@ -826,24 +824,25 @@ ProcessFile(JSContext *cx, const char *filename, FILE *file, bool forceTTY) } } ungetc(ch, file); - JS_BeginRequest(cx); + JS::RootedScript script(cx); + JS::RootedValue unused(cx); JS::CompileOptions options(cx); options.setUTF8(true) .setFileAndLine(filename, 1) - .setIsRunOnce(true); - if (JS::Compile(cx, options, file, &script) && !compileOnly) - (void)JS_ExecuteScript(cx, script, &result); - JS_EndRequest(cx); - - return; + .setIsRunOnce(true) + .setNoScriptRval(true); + if (!JS::Compile(cx, options, file, &script)) + return false; + return compileOnly || JS_ExecuteScript(cx, script, &unused); } /* It's an interactive filehandle; drop into read-eval-print loop. */ - lineno = 1; - hitEOF = false; + int lineno = 1; + bool hitEOF = false; do { - bufp = buffer; + char buffer[4096]; + char* bufp = buffer; *bufp = '\0'; /* @@ -852,7 +851,7 @@ ProcessFile(JSContext *cx, const char *filename, FILE *file, bool forceTTY) * cleanly. This should be whenever we get a complete statement that * coincides with the end of a line. */ - startline = lineno; + int startline = lineno; do { if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) { hitEOF = true; @@ -862,67 +861,53 @@ ProcessFile(JSContext *cx, const char *filename, FILE *file, bool forceTTY) lineno++; } while (!JS_BufferIsCompilableUnit(cx, global, buffer, strlen(buffer))); - JS_BeginRequest(cx); - /* Clear any pending exception from previous failed compiles. */ - JS_ClearPendingException(cx); - JS::CompileOptions options(cx); - options.setFileAndLine("typein", startline) - .setIsRunOnce(true); - if (JS_CompileScript(cx, buffer, strlen(buffer), options, &script)) { - JSErrorReporter older; - - if (!compileOnly) { - ok = JS_ExecuteScript(cx, script, &result); - if (ok && result != JSVAL_VOID) { - /* Suppress error reports from JS::ToString(). */ - older = JS_SetErrorReporter(JS_GetRuntime(cx), nullptr); - str = ToString(cx, result); - JS_SetErrorReporter(JS_GetRuntime(cx), older); - JSAutoByteString bytes; - if (str && bytes.encodeLatin1(cx, str)) - fprintf(gOutFile, "%s\n", bytes.ptr()); - else - ok = false; - } - } - } - JS_EndRequest(cx); + if (!ProcessLine(jsapi, buffer, startline)) + jsapi.ClearException(); // Errors from interactive processing are squelched. } while (!hitEOF && !gQuitting); fprintf(gOutFile, "\n"); + return true; } -static void -Process(JSContext *cx, const char *filename, bool forceTTY) +static bool +Process(AutoJSAPI& jsapi, const char* filename, bool forceTTY) { - FILE *file; + FILE* file; if (forceTTY || !filename || strcmp(filename, "-") == 0) { file = stdin; } else { file = fopen(filename, "r"); if (!file) { - JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, + JS_ReportErrorNumber(jsapi.cx(), my_GetErrorMessage, nullptr, JSSMSG_CANT_OPEN, filename, strerror(errno)); gExitCode = EXITCODE_FILE_NOT_FOUND; - return; + return false; } } - ProcessFile(cx, filename, file, forceTTY); + bool ok = ProcessFile(jsapi, filename, file, forceTTY); if (file != stdin) fclose(file); + return ok; } static int -usage(void) +usage() { fprintf(gErrFile, "%s\n", JS_GetImplementationVersion()); fprintf(gErrFile, "usage: xpcshell [-g gredir] [-a appdir] [-r manifest]... [-WwxiCSsmIp] [-v version] [-f scriptfile] [-e script] [scriptfile] [scriptarg...]\n"); return 2; } +static bool +printUsageAndSetExitCode() +{ + gExitCode = usage(); + return false; +} + static void ProcessArgsForCompartment(JSContext* cx, char** argv, int argc) { @@ -950,12 +935,13 @@ ProcessArgsForCompartment(JSContext* cx, char** argv, int argc) } } -static int -ProcessArgs(JSContext *cx, char **argv, int argc, XPCShellDirProvider* aDirProvider) +static bool +ProcessArgs(AutoJSAPI& jsapi, char** argv, int argc, XPCShellDirProvider* aDirProvider) { + JSContext* cx = jsapi.cx(); const char rcfilename[] = "xpcshell.js"; FILE* rcfile; - int i; + int rootPosition; JS::Rooted argsObj(cx); char* filename = nullptr; bool isInteractive = true; @@ -964,8 +950,11 @@ ProcessArgs(JSContext *cx, char **argv, int argc, XPCShellDirProvider* aDirProvi rcfile = fopen(rcfilename, "r"); if (rcfile) { printf("[loading '%s'...]\n", rcfilename); - ProcessFile(cx, rcfilename, rcfile, false); + bool ok = ProcessFile(jsapi, rcfilename, rcfile, false); fclose(rcfile); + if (!ok) { + return false; + } } JS::Rooted global(cx, JS::CurrentGlobalOrNull(cx)); @@ -975,19 +964,22 @@ ProcessArgs(JSContext *cx, char **argv, int argc, XPCShellDirProvider* aDirProvi * before processing any -f options, which must interleave properly with * -v and -w options. This requires two passes, and without getopt, we'll * have to keep the option logic here and in the second for loop in sync. + * First of all, find out the first argument position which will be passed + * as a script file to be executed. */ - for (i = 0; i < argc; i++) { - if (argv[i][0] != '-' || argv[i][1] == '\0') { - ++i; + for (rootPosition = 0; rootPosition < argc; rootPosition++) { + if (argv[rootPosition][0] != '-' || argv[rootPosition][1] == '\0') { + ++rootPosition; break; } - switch (argv[i][1]) { - case 'v': - case 'f': - case 'e': - ++i; - break; - default:; + + bool isPairedFlag = + argv[rootPosition][0] != '\0' && + (argv[rootPosition][1] == 'v' || + argv[rootPosition][1] == 'f' || + argv[rootPosition][1] == 'e'); + if (isPairedFlag && rootPosition < argc - 1) { + ++rootPosition; // Skip over the 'foo' portion of |-v foo|, |-f foo|, or |-e foo|. } } @@ -1001,15 +993,15 @@ ProcessArgs(JSContext *cx, char **argv, int argc, XPCShellDirProvider* aDirProvi if (!JS_DefineProperty(cx, global, "arguments", argsObj, 0)) return 1; - for (size_t j = 0, length = argc - i; j < length; j++) { - RootedString str(cx, JS_NewStringCopyZ(cx, argv[i++])); + for (int j = 0, length = argc - rootPosition; j < length; j++) { + RootedString str(cx, JS_NewStringCopyZ(cx, argv[rootPosition++])); if (!str || !JS_DefineElement(cx, argsObj, j, str, JSPROP_ENUMERATE)) { return 1; } } - for (i = 0; i < argc; i++) { + for (int i = 0; i < argc; i++) { if (argv[i][0] != '-' || argv[i][1] == '\0') { filename = argv[i++]; isInteractive = false; @@ -1018,7 +1010,7 @@ ProcessArgs(JSContext *cx, char **argv, int argc, XPCShellDirProvider* aDirProvi switch (argv[i][1]) { case 'v': if (++i == argc) { - return usage(); + return printUsageAndSetExitCode(); } JS_SetVersionForCompartment(js::GetContextCompartment(cx), JSVersion(atoi(argv[i]))); @@ -1038,9 +1030,10 @@ ProcessArgs(JSContext *cx, char **argv, int argc, XPCShellDirProvider* aDirProvi break; case 'f': if (++i == argc) { - return usage(); + return printUsageAndSetExitCode(); } - Process(cx, argv[i], false); + if (!Process(jsapi, argv[i], false)) + return false; /* * XXX: js -f foo.js should interpret foo.js and then * drop into interactive mode, but that breaks test @@ -1056,7 +1049,7 @@ ProcessArgs(JSContext *cx, char **argv, int argc, XPCShellDirProvider* aDirProvi RootedValue rval(cx); if (++i == argc) { - return usage(); + return printUsageAndSetExitCode(); } JS::CompileOptions opts(cx); @@ -1082,20 +1075,19 @@ ProcessArgs(JSContext *cx, char **argv, int argc, XPCShellDirProvider* aDirProvi nsCOMPtr pluginsDir; if (NS_FAILED(XRE_GetFileFromPath(pluginPath, getter_AddRefs(pluginsDir)))) { fprintf(gErrFile, "Couldn't use given plugins dir.\n"); - return usage(); + return printUsageAndSetExitCode(); } aDirProvider->SetPluginDir(pluginsDir); break; } default: - return usage(); + return printUsageAndSetExitCode(); } } if (filename || isInteractive) - Process(cx, filename, forceTTY); - - return gExitCode; + return Process(jsapi, filename, forceTTY); + return true; } /***************************************************************************/ @@ -1171,19 +1163,6 @@ nsXPCFunctionThisTranslator::TranslateThis(nsISupports* aInitialThis, #endif -static void -XPCShellErrorReporter(JSContext* cx, const char* message, JSErrorReport* rep) -{ - if (gIgnoreReportedErrors) - return; - - if (!JSREPORT_IS_WARNING(rep->flags)) - gExitCode = EXITCODE_RUNTIME_ERROR; - - // Delegate to the system error reporter for heavy lifting. - xpc::SystemErrorReporter(cx, message, rep); -} - static bool GetCurrentWorkingDirectory(nsAString& workingDirectory) { @@ -1228,7 +1207,7 @@ XRE_XPCShellMain(int argc, char** argv, char** envp) { JSRuntime* rt; JSContext* cx; - int result; + int result = 0; nsresult rv; gErrFile = stderr; @@ -1370,9 +1349,7 @@ XRE_XPCShellMain(int argc, char** argv, char** envp) sScriptedInterruptCallback.init(rt, UndefinedValue()); JS_SetInterruptCallback(rt, XPCShellInterruptCallback); - JS_SetErrorReporter(rt, XPCShellErrorReporter); - - dom::AutoJSAPI jsapi; + AutoJSAPI jsapi; jsapi.Init(); cx = jsapi.cx(); @@ -1442,6 +1419,9 @@ XRE_XPCShellMain(int argc, char** argv, char** envp) if (NS_FAILED(rv)) return 1; + // Initialize graphics prefs on the main thread, if not already done + gfxPrefs::GetSingleton(); + { JS::Rooted glob(cx, holder->GetJSObject()); if (!glob) { @@ -1483,14 +1463,28 @@ XRE_XPCShellMain(int argc, char** argv, char** envp) GetLocationProperty, nullptr); - // We are almost certainly going to run script here, so we need an - // AutoEntryScript. This is Gecko-specific and not in any spec. - dom::AutoEntryScript aes(backstagePass, - "xpcshell argument processing"); - result = ProcessArgs(aes.cx(), argv, argc, &dirprovider); + { + // We are almost certainly going to run script here, so we need an + // AutoEntryScript. This is Gecko-specific and not in any spec. + AutoEntryScript aes(backstagePass, "xpcshell argument processing"); + + // If an exception is thrown, we'll set our return code + // appropriately, and then let the AutoJSAPI destructor report + // the error to the console. + aes.TakeOwnershipOfErrorReporting(); + if (!ProcessArgs(aes, argv, argc, &dirprovider)) { + if (gExitCode) { + result = gExitCode; + } else if (gQuitting) { + result = 0; + } else { + result = EXITCODE_RUNTIME_ERROR; + } + } + } JS_DropPrincipals(rt, gJSPrincipals); - JS_SetAllNonReservedSlotsToUndefined(aes.cx(), glob); + JS_SetAllNonReservedSlotsToUndefined(cx, glob); JS_GC(rt); } JS_GC(rt); diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index 3fc2f880f0..d63aea2f4a 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -1327,7 +1327,7 @@ class MOZ_STACK_CLASS CallMethodHelper const uint32_t mArgc; MOZ_ALWAYS_INLINE bool - GetArraySizeFromParam(uint8_t paramIndex, uint32_t* result) const; + GetArraySizeFromParam(uint8_t paramIndex, HandleValue maybeArray, uint32_t* result); MOZ_ALWAYS_INLINE bool GetInterfaceTypeFromParam(uint8_t paramIndex, @@ -1417,7 +1417,7 @@ XPCWrappedNative::CallMethod(XPCCallContext& ccx, bool CallMethodHelper::Call() { - mCallContext.SetRetVal(JSVAL_VOID); + mCallContext.SetRetVal(JS::UndefinedValue()); XPCJSRuntime::Get()->SetPendingException(nullptr); @@ -1476,7 +1476,7 @@ CallMethodHelper::~CallMethodHelper() // We need some basic information to properly destroy the array. uint32_t array_count = 0; nsXPTType datum_type; - if (!GetArraySizeFromParam(i, &array_count) || + if (!GetArraySizeFromParam(i, UndefinedHandleValue, &array_count) || !NS_SUCCEEDED(mIFaceInfo->GetTypeForParam(mVTableIndex, ¶mInfo, 1, &datum_type))) { @@ -1510,7 +1510,8 @@ CallMethodHelper::~CallMethodHelper() bool CallMethodHelper::GetArraySizeFromParam(uint8_t paramIndex, - uint32_t* result) const + HandleValue maybeArray, + uint32_t* result) { nsresult rv; const nsXPTParamInfo& paramInfo = mMethodInfo->GetParam(paramIndex); @@ -1521,6 +1522,22 @@ CallMethodHelper::GetArraySizeFromParam(uint8_t paramIndex, if (NS_FAILED(rv)) return Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, mCallContext); + // If the array length wasn't passed, it might have been listed as optional. + // When converting arguments from JS to C++, we pass the array as |maybeArray|, + // and give ourselves the chance to infer the length. Once we have it, we stick + // it in the right slot so that we can find it again when cleaning up the params. + // from the array. + if (paramIndex >= mArgc && maybeArray.isObject()) { + MOZ_ASSERT(mMethodInfo->GetParam(paramIndex).IsOptional()); + RootedObject arrayOrNull(mCallContext, maybeArray.isObject() ? &maybeArray.toObject() + : nullptr); + if (!JS_IsArrayObject(mCallContext, maybeArray) || + !JS_GetArrayLength(mCallContext, arrayOrNull, &GetDispatchParam(paramIndex)->val.u32)) + { + return Throw(NS_ERROR_XPC_CANT_CONVERT_OBJECT_TO_ARRAY, mCallContext); + } + } + *result = GetDispatchParam(paramIndex)->val.u32; return true; @@ -1566,14 +1583,14 @@ CallMethodHelper::GetOutParamSource(uint8_t paramIndex, MutableHandleValue srcp) if (paramInfo.IsOut() && !paramInfo.IsRetval()) { MOZ_ASSERT(paramIndex < mArgc || paramInfo.IsOptional(), "Expected either enough arguments or an optional argument"); - jsval arg = paramIndex < mArgc ? mArgv[paramIndex] : JSVAL_NULL; + jsval arg = paramIndex < mArgc ? mArgv[paramIndex] : JS::NullValue(); if (paramIndex < mArgc) { RootedObject obj(mCallContext); if (!arg.isPrimitive()) obj = &arg.toObject(); if (!obj || !JS_GetPropertyById(mCallContext, obj, mIdxValueId, srcp)) { // Explicitly passed in unusable value for out param. Note - // that if i >= mArgc we already know that |arg| is JSVAL_NULL, + // that if i >= mArgc we already know that |arg| is JS::NullValue(), // and that's ok. ThrowBadParam(NS_ERROR_XPC_NEED_OUT_OBJECT, paramIndex, mCallContext); @@ -1616,7 +1633,7 @@ CallMethodHelper::GatherAndConvertResults() datum_type = type; if (isArray || isSizedString) { - if (!GetArraySizeFromParam(i, &array_count)) + if (!GetArraySizeFromParam(i, UndefinedHandleValue, &array_count)) return false; } @@ -1837,7 +1854,7 @@ CallMethodHelper::ConvertIndependentParam(uint8_t i) // indirectly, regardless of in/out-ness. if (type_tag == nsXPTType::T_JSVAL) { // Root the value. - dp->val.j = JSVAL_VOID; + dp->val.j.setUndefined(); if (!js::AddRawValueRoot(mCallContext, &dp->val.j, "XPCWrappedNative::CallMethod param")) return false; } @@ -1871,9 +1888,9 @@ CallMethodHelper::ConvertIndependentParam(uint8_t i) if (i < mArgc) src = mArgv[i]; else if (type_tag == nsXPTType::T_JSVAL) - src = JSVAL_VOID; + src.setUndefined(); else - src = JSVAL_NULL; + src.setNull(); } nsID param_iid; @@ -1987,7 +2004,7 @@ CallMethodHelper::ConvertDependentParam(uint8_t i) // Handle the 'in' case. MOZ_ASSERT(i < mArgc || paramInfo.IsOptional(), "Expected either enough arguments or an optional argument"); - src = i < mArgc ? mArgv[i] : JSVAL_NULL; + src = i < mArgc ? mArgv[i] : JS::NullValue(); } nsID param_iid; @@ -1998,7 +2015,7 @@ CallMethodHelper::ConvertDependentParam(uint8_t i) nsresult err; if (isArray || isSizedString) { - if (!GetArraySizeFromParam(i, &array_count)) + if (!GetArraySizeFromParam(i, src, &array_count)) return false; if (isArray) { diff --git a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp index f5dfe5fe34..678ef5ecca 100644 --- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp +++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp @@ -479,7 +479,7 @@ XPC_WN_Shared_Convert(JSContext* cx, HandleObject obj, JSType type, MutableHandl vp.set(JS_GetNaNValue(cx)); return true; case JSTYPE_BOOLEAN: - vp.set(JSVAL_TRUE); + vp.setBoolean(true); return true; case JSTYPE_VOID: case JSTYPE_STRING: diff --git a/js/xpconnect/tests/components/js/xpctest_params.js b/js/xpconnect/tests/components/js/xpctest_params.js index ace4ee374e..f06e9c2b6b 100644 --- a/js/xpconnect/tests/components/js/xpctest_params.js +++ b/js/xpconnect/tests/components/js/xpctest_params.js @@ -73,7 +73,13 @@ TestParams.prototype = { testSizedWstring: f_is, testInterfaceIs: f_is, testInterfaceIsArray: f_size_and_iid, - testOutAString: function(o) { o.value = "out"; } + testOutAString: function(o) { o.value = "out"; }, + testStringArrayOptionalSize: function(arr, size) { + if (arr.length != size) { throw "bad size passed to test method"; } + var rv = ""; + arr.forEach((x) => rv += x); + return rv; + } }; this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TestParams]); diff --git a/js/xpconnect/tests/components/native/xpctest_params.cpp b/js/xpconnect/tests/components/native/xpctest_params.cpp index f7f462db63..1f14b2b90f 100644 --- a/js/xpconnect/tests/components/native/xpctest_params.cpp +++ b/js/xpconnect/tests/components/native/xpctest_params.cpp @@ -346,3 +346,16 @@ NS_IMETHODIMP nsXPCTestParams::TestOutAString(nsAString & o) o.AssignLiteral("out"); return NS_OK; } + +/* + * ACString testStringArrayOptionalSize([array, size_is(aLength)] in string a, [optional] in unsigned long aLength); + */ +NS_IMETHODIMP nsXPCTestParams::TestStringArrayOptionalSize(const char * *a, uint32_t length, nsACString& out) +{ + out.Truncate(); + for (uint32_t i = 0; i < length; ++i) { + out.Append(a[i]); + } + + return NS_OK; +} diff --git a/js/xpconnect/tests/idl/xpctest_params.idl b/js/xpconnect/tests/idl/xpctest_params.idl index f2f80c74e1..f324a4595a 100644 --- a/js/xpconnect/tests/idl/xpctest_params.idl +++ b/js/xpconnect/tests/idl/xpctest_params.idl @@ -15,7 +15,7 @@ interface nsIXPCTestInterfaceA; interface nsIXPCTestInterfaceB; -[scriptable, uuid(fe2b7433-ac3b-49ef-9344-b67228bfdd46)] +[scriptable, uuid(812145c7-9fcc-425e-a878-36ad1b7730b7)] interface nsIXPCTestParams : nsISupports { // These types correspond to the ones in typelib.py @@ -84,4 +84,7 @@ interface nsIXPCTestParams : nsISupports { // Test for out dipper parameters void testOutAString(out AString o); + + // Test for optional array size_is. + ACString testStringArrayOptionalSize([array, size_is(aLength)] in string a, [optional] in unsigned long aLength); }; diff --git a/js/xpconnect/tests/unit/test_bug809674.js b/js/xpconnect/tests/unit/test_bug809674.js index 5718ca6d94..76bfdf7427 100644 --- a/js/xpconnect/tests/unit/test_bug809674.js +++ b/js/xpconnect/tests/unit/test_bug809674.js @@ -25,11 +25,7 @@ function test_property_throws(contractid) { do_check_true(false); } catch (e) { do_check_true(true); - // We want to throw a helpful error here, but in the current state of broken - // error reporting this gets reported directly to the system error reporter - // and not propagated upwards. Things are too broken in this department to - // worry about this now - we'll fix it somewhere around bug 981187. - todo_check_true(/implicit_jscontext/.test(e)) + do_check_true(/implicit_jscontext/.test(e)) } } diff --git a/js/xpconnect/tests/unit/test_params.js b/js/xpconnect/tests/unit/test_params.js index dbe2ae4a0c..381b0f6917 100644 --- a/js/xpconnect/tests/unit/test_params.js +++ b/js/xpconnect/tests/unit/test_params.js @@ -188,6 +188,9 @@ function test_component(contractid) { doIs2Test("testInterfaceIsArray", [makeA(), makeA(), makeA(), makeA(), makeA()], 5, Ci['nsIXPCTestInterfaceA'], [makeB(), makeB(), makeB()], 3, Ci['nsIXPCTestInterfaceB']); + // Test optional array size. + do_check_eq(o.testStringArrayOptionalSize(["some", "string", "array"]), "somestringarray"); + // Test incorrect (too big) array size parameter; this should throw NOT_ENOUGH_ELEMENTS. doTypedArrayMismatchTest("testShortArray", new Int16Array([-3, 7, 4]), 4, new Int16Array([1, -32, 6]), 3); diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp index a1d14dccb1..9002a7b377 100644 --- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -1240,9 +1240,9 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext* cx, HandleObject wr desc.setAttributes(JSPROP_ENUMERATE); desc.setGetter(nullptr); desc.setSetter(nullptr); - desc.value().set(JSVAL_VOID); + desc.value().setUndefined(); - RootedValue fval(cx, JSVAL_VOID); + RootedValue fval(cx, JS::UndefinedValue()); if (member->IsConstant()) { if (!member->GetConstantValue(ccx, iface, desc.value().address())) { JS_ReportError(cx, "Failed to convert constant native property to JS value"); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 153dfe86af..0849f65610 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -127,6 +127,8 @@ pref("dom.indexedDB.experimental", false); pref("dom.indexedDB.logging.enabled", true); // Detailed output in log messages. pref("dom.indexedDB.logging.details", true); +// Enable profiler marks for indexedDB events. +pref("dom.indexedDB.logging.profiler-marks", false); // Whether or not selection events are enabled pref("dom.select_events.enabled", true); @@ -137,6 +139,13 @@ pref("dom.select_events.textcontrols.enabled", true); // Whether or not the document visbility API is enabled pref("dom.visibilityAPI.enabled", true); +// Whether or not the Permissions API is enabled. +#ifdef NIGHTLY_BUILD +pref("dom.permissions.enabled", true); +#else +pref("dom.permissions.enabled", false); +#endif + // Whether or not Web Workers are enabled. pref("dom.workers.enabled", true); // The number of workers per domain allowed to run concurrently. @@ -2167,7 +2176,7 @@ pref("security.csp.debug", false); pref("security.csp.experimentalEnabled", false); // Default Content Security Policy to apply to privileged apps. -pref("security.apps.privileged.CSP.default", "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'"); +pref("security.apps.privileged.CSP.default", "default-src * data: blob:; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'"); // Mixed content blocking pref("security.mixed_content.block_active_content", false); @@ -4345,7 +4354,7 @@ pref("layers.max-active", -1); pref("layers.tiles.adjust", true); // Set the default values, and then override per-platform as needed -pref("layers.offmainthreadcomposition.enabled", false); +pref("layers.offmainthreadcomposition.enabled", true); // Compositor target frame rate. NOTE: If vsync is enabled the compositor // frame rate will still be capped. // -1 -> default (match layout.frame_rate or 60 FPS) @@ -4357,25 +4366,11 @@ pref("layers.offmainthreadcomposition.frame-rate", -1); pref("layers.async-video.enabled", true); pref("layers.async-video-oop.enabled",true); -#ifdef XP_WIN -pref("layers.offmainthreadcomposition.enabled", true); -#endif - -#ifdef MOZ_WIDGET_QT -pref("layers.offmainthreadcomposition.enabled", true); -#endif - #ifdef XP_MACOSX -pref("layers.offmainthreadcomposition.enabled", true); pref("layers.enable-tiles", true); pref("layers.tiled-drawtarget.enabled", true); #endif -// ANDROID covers android and b2g -#ifdef ANDROID -pref("layers.offmainthreadcomposition.enabled", true); -#endif - // same effect as layers.offmainthreadcomposition.enabled, but specifically for // use with tests. pref("layers.offmainthreadcomposition.testing.enabled", false); diff --git a/storage/mozStorageStatementJSHelper.cpp b/storage/mozStorageStatementJSHelper.cpp index 7799a0e34d..ed4ef9d24e 100644 --- a/storage/mozStorageStatementJSHelper.cpp +++ b/storage/mozStorageStatementJSHelper.cpp @@ -61,7 +61,7 @@ stepFunc(JSContext *aCtx, bool hasMore = false; rv = stmt->ExecuteStep(&hasMore); if (NS_SUCCEEDED(rv) && !hasMore) { - *_vp = JSVAL_FALSE; + _vp->setBoolean(false); (void)stmt->Reset(); return true; } diff --git a/storage/mozStorageStatementRow.cpp b/storage/mozStorageStatementRow.cpp index 18f9a21765..2436b6e32a 100644 --- a/storage/mozStorageStatementRow.cpp +++ b/storage/mozStorageStatementRow.cpp @@ -102,7 +102,7 @@ StatementRow::GetProperty(nsIXPConnectWrappedNative *aWrapper, } } else if (type == mozIStorageValueArray::VALUE_TYPE_NULL) { - *_vp = JSVAL_NULL; + _vp->setNull(); } else { NS_ERROR("unknown column type returned, what's going on?"); diff --git a/toolkit/devtools/server/nsJSInspector.cpp b/toolkit/devtools/server/nsJSInspector.cpp index c39781483a..fa1fead2b9 100644 --- a/toolkit/devtools/server/nsJSInspector.cpp +++ b/toolkit/devtools/server/nsJSInspector.cpp @@ -52,7 +52,7 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSInspector) NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mLastRequestor) NS_IMPL_CYCLE_COLLECTION_TRACE_END -nsJSInspector::nsJSInspector() : mNestedLoopLevel(0), mRequestors(1), mLastRequestor(JSVAL_NULL) +nsJSInspector::nsJSInspector() : mNestedLoopLevel(0), mRequestors(1), mLastRequestor(JS::NullValue()) { } @@ -99,7 +99,7 @@ nsJSInspector::ExitNestedEventLoop(uint32_t *out) if (mNestedLoopLevel > 0) mLastRequestor = mRequestors.ElementAt(mNestedLoopLevel - 1); else - mLastRequestor = JSVAL_NULL; + mLastRequestor = JS::NullValue(); } else { return NS_ERROR_FAILURE; } diff --git a/toolkit/devtools/server/tests/unit/test_sourcemaps-04.js b/toolkit/devtools/server/tests/unit/test_sourcemaps-04.js index 3e1bb8dcc3..9e261ae047 100644 --- a/toolkit/devtools/server/tests/unit/test_sourcemaps-04.js +++ b/toolkit/devtools/server/tests/unit/test_sourcemaps-04.js @@ -11,15 +11,6 @@ var gThreadClient; Components.utils.import('resource://gre/modules/devtools/SourceMap.jsm'); -// Deep in the complicated labyrinth of code that this test invokes, beneath -// debugger callbacks, sandboxes and nested event loops, lies an exception. -// This exception lay sleeping since the dawn of time, held captive in a -// delicate balance of custom xpcshell error reporters and garbage data about -// the XPCCallContext stack. But bholley dug too greedily, and too deep, and -// awoke shadow and flame in the darkness of nsExternalHelperAppService.cpp. -// We must now trust in deep magic to ensure that it does not awaken again. -ignoreReportedErrors(true); - function run_test() { initTestDebuggerServer(); diff --git a/toolkit/devtools/server/tests/unit/test_sourcemaps-05.js b/toolkit/devtools/server/tests/unit/test_sourcemaps-05.js index db47458d90..ab25dcef7c 100644 --- a/toolkit/devtools/server/tests/unit/test_sourcemaps-05.js +++ b/toolkit/devtools/server/tests/unit/test_sourcemaps-05.js @@ -11,15 +11,6 @@ var gThreadClient; Components.utils.import('resource://gre/modules/devtools/SourceMap.jsm'); -// Deep in the complicated labyrinth of code that this test invokes, beneath -// debugger callbacks, sandboxes and nested event loops, lies an exception. -// This exception lay sleeping since the dawn of time, held captive in a -// delicate balance of custom xpcshell error reporters and garbage data about -// the XPCCallContext stack. But bholley dug too greedily, and too deep, and -// awoke shadow and flame in the darkness of nsExternalHelperAppService.cpp. -// We must now trust in deep magic to ensure that it does not awaken again. -ignoreReportedErrors(true); - function run_test() { initTestDebuggerServer(); diff --git a/toolkit/mozapps/installer/precompile_cache.js b/toolkit/mozapps/installer/precompile_cache.js index 65d23c37af..9099e96999 100644 --- a/toolkit/mozapps/installer/precompile_cache.js +++ b/toolkit/mozapps/installer/precompile_cache.js @@ -66,22 +66,12 @@ function get_modules_under(uri) { function load_modules_under(spec, uri) { var entries = get_modules_under(uri).sort(); - // The precompilation of JS here sometimes reports errors, which we don't - // really care about. But if the errors are ever reported to xpcshell's - // error reporter, it will cause it to return an error code, which will break - // automation. Currently they won't be, because the component loader spins up - // its JSContext before xpcshell has time to set its context callback (which - // overrides the error reporter on all newly-created JSContexts). But as we - // move towards a singled-cxed browser, we'll run into this. So let's be - // forward-thinking and deal with it now. - ignoreReportedErrors(true); for each (let entry in entries) { try { dump(spec + entry + "\n"); Cu.import(spec + entry, null); } catch(e) {} } - ignoreReportedErrors(false); } function resolveResource(spec) { diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 092a200181..aa9b61f922 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -3220,13 +3220,30 @@ XREMain::XRE_mainStartup(bool* aExitFlag) } } #endif /* MOZ_WIDGET_GTK */ - +#ifdef MOZ_X11 + // Init X11 in thread-safe mode. Must be called prior to the first call to XOpenDisplay + // (called inside gdk_display_open). This is a requirement for off main tread compositing. + XInitThreads(); +#endif +#if defined(MOZ_WIDGET_GTK) + { + mGdkDisplay = gdk_display_open(display_name); + if (!mGdkDisplay) { + PR_fprintf(PR_STDERR, "Error: cannot open display: %s\n", display_name); + return 1; + } + gdk_display_manager_set_default_display (gdk_display_manager_get(), + mGdkDisplay); + if (!GDK_IS_X11_DISPLAY(mGdkDisplay)) + mDisableRemote = true; + } +#endif #ifdef MOZ_ENABLE_XREMOTE // handle --remote now that xpcom is fired up bool newInstance; { char *e = PR_GetEnv("MOZ_NO_REMOTE"); - mDisableRemote = (e && *e); + mDisableRemote = (mDisableRemote || (e && *e)); if (mDisableRemote) { newInstance = true; } else { @@ -3259,36 +3276,7 @@ XREMain::XRE_mainStartup(bool* aExitFlag) return 1; } #endif -#ifdef MOZ_X11 - // Init X11 in thread-safe mode. Must be called prior to the first call to XOpenDisplay - // (called inside gdk_display_open). This is a requirement for off main tread compositing. - // This is done only on X11 platforms if the environment variable MOZ_USE_OMTC is set so - // as to avoid overhead when omtc is not used. - // - // On nightly builds, we call this by default to enable OMTC for Electrolysis testing. On - // aurora, beta, and release builds, there is a small tpaint regression from enabling this - // call, so it sits behind an environment variable. - // - // An environment variable is used instead of a pref on X11 platforms because we start having - // access to prefs long after the first call to XOpenDisplay which is hard to change due to - // interdependencies in the initialization. -# ifndef NIGHTLY_BUILD - if (PR_GetEnv("MOZ_USE_OMTC") || - PR_GetEnv("MOZ_OMTC_ENABLED")) -# endif - { - XInitThreads(); - } -#endif #if defined(MOZ_WIDGET_GTK) - mGdkDisplay = gdk_display_open(display_name); - if (!mGdkDisplay) { - PR_fprintf(PR_STDERR, "Error: cannot open display: %s\n", display_name); - return 1; - } - gdk_display_manager_set_default_display (gdk_display_manager_get(), - mGdkDisplay); - // g_set_application_name () is only defined in glib2.2 and higher. _g_set_application_name_fn _g_set_application_name = (_g_set_application_name_fn)FindFunction("g_set_application_name"); diff --git a/widget/gtk/compat/gdk/gdkx.h b/widget/gtk/compat/gdk/gdkx.h index 422358c3a3..dc9d296360 100644 --- a/widget/gtk/compat/gdk/gdkx.h +++ b/widget/gtk/compat/gdk/gdkx.h @@ -22,4 +22,9 @@ gdk_x11_window_get_xid(GdkWindow *window) { return(GDK_WINDOW_XWINDOW(window)); } + +#ifndef GDK_IS_X11_DISPLAY +#define GDK_IS_X11_DISPLAY(a) (true) +#endif + #endif /* GDKX_WRAPPER_H */ diff --git a/widget/gtk/mozgtk/mozgtk.c b/widget/gtk/mozgtk/mozgtk.c index 0e725e2fec..46f6469a1f 100644 --- a/widget/gtk/mozgtk/mozgtk.c +++ b/widget/gtk/mozgtk/mozgtk.c @@ -54,6 +54,8 @@ STUB(gdk_property_get) STUB(gdk_screen_get_default) STUB(gdk_screen_get_display) STUB(gdk_screen_get_font_options) +STUB(gdk_screen_get_height) +STUB(gdk_screen_get_height_mm) STUB(gdk_screen_get_number) STUB(gdk_screen_get_resolution) STUB(gdk_screen_get_rgba_visual) @@ -491,6 +493,7 @@ STUB(gdk_error_trap_pop_ignored) STUB(gdk_event_get_source_device) STUB(gdk_window_get_type) STUB(gdk_x11_window_get_xid) +STUB(gdk_x11_display_get_type) STUB(gtk_cairo_should_draw_window) STUB(gtk_cairo_transform_to_window) STUB(gtk_combo_box_text_append) diff --git a/widget/gtk/nsClipboard.cpp b/widget/gtk/nsClipboard.cpp index ad908e28f1..be87ce7780 100644 --- a/widget/gtk/nsClipboard.cpp +++ b/widget/gtk/nsClipboard.cpp @@ -918,52 +918,54 @@ RetrievalContext::Wait() return data; } - Display *xDisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()) ; - checkEventContext context; - context.cbWidget = nullptr; - context.selAtom = gdk_x11_atom_to_xatom(gdk_atom_intern("GDK_SELECTION", - FALSE)); + GdkDisplay *gdkDisplay = gdk_display_get_default(); + if (GDK_IS_X11_DISPLAY(gdkDisplay)) { + Display *xDisplay = GDK_DISPLAY_XDISPLAY(gdkDisplay); + checkEventContext context; + context.cbWidget = nullptr; + context.selAtom = gdk_x11_atom_to_xatom(gdk_atom_intern("GDK_SELECTION", + FALSE)); - // Send X events which are relevant to the ongoing selection retrieval - // to the clipboard widget. Wait until either the operation completes, or - // we hit our timeout. All other X events remain queued. + // Send X events which are relevant to the ongoing selection retrieval + // to the clipboard widget. Wait until either the operation completes, or + // we hit our timeout. All other X events remain queued. - int select_result; + int select_result; - int cnumber = ConnectionNumber(xDisplay); - fd_set select_set; - FD_ZERO(&select_set); - FD_SET(cnumber, &select_set); - ++cnumber; - TimeStamp start = TimeStamp::Now(); + int cnumber = ConnectionNumber(xDisplay); + fd_set select_set; + FD_ZERO(&select_set); + FD_SET(cnumber, &select_set); + ++cnumber; + TimeStamp start = TimeStamp::Now(); - do { - XEvent xevent; + do { + XEvent xevent; - while (XCheckIfEvent(xDisplay, &xevent, checkEventProc, - (XPointer) &context)) { + while (XCheckIfEvent(xDisplay, &xevent, checkEventProc, + (XPointer) &context)) { - if (xevent.xany.type == SelectionNotify) - DispatchSelectionNotifyEvent(context.cbWidget, &xevent); - else - DispatchPropertyNotifyEvent(context.cbWidget, &xevent); + if (xevent.xany.type == SelectionNotify) + DispatchSelectionNotifyEvent(context.cbWidget, &xevent); + else + DispatchPropertyNotifyEvent(context.cbWidget, &xevent); - if (mState == COMPLETED) { - void *data = mData; - mData = nullptr; - return data; + if (mState == COMPLETED) { + void *data = mData; + mData = nullptr; + return data; + } } - } - - TimeStamp now = TimeStamp::Now(); - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = std::max(0, - kClipboardTimeout - (now - start).ToMicroseconds()); - select_result = select(cnumber, &select_set, nullptr, nullptr, &tv); - } while (select_result == 1 || - (select_result == -1 && errno == EINTR)); + TimeStamp now = TimeStamp::Now(); + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = std::max(0, + kClipboardTimeout - (now - start).ToMicroseconds()); + select_result = select(cnumber, &select_set, nullptr, nullptr, &tv); + } while (select_result == 1 || + (select_result == -1 && errno == EINTR)); + } #ifdef DEBUG_CLIPBOARD printf("exceeded clipboard timeout\n"); #endif diff --git a/widget/gtk/nsGtkKeyUtils.cpp b/widget/gtk/nsGtkKeyUtils.cpp index 9fed1f063b..9fbca06378 100644 --- a/widget/gtk/nsGtkKeyUtils.cpp +++ b/widget/gtk/nsGtkKeyUtils.cpp @@ -167,7 +167,8 @@ KeymapWrapper::KeymapWrapper() : g_object_weak_ref(G_OBJECT(mGdkKeymap), (GWeakNotify)OnDestroyKeymap, this); - InitXKBExtension(); + if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) + InitXKBExtension(); Init(); } @@ -187,7 +188,8 @@ KeymapWrapper::Init() mModifierKeys.Clear(); memset(mModifierMasks, 0, sizeof(mModifierMasks)); - InitBySystemSettings(); + if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) + InitBySystemSettings(); gdk_window_add_filter(nullptr, FilterEvents, this); @@ -889,9 +891,10 @@ KeymapWrapper::InitKeyEvent(WidgetKeyboardEvent& aKeyEvent, // state. It means if there're some pending modifier key press or // key release events, the result isn't what we want. guint modifierState = aGdkKeyEvent->state; - if (aGdkKeyEvent->is_modifier) { + GdkDisplay* gdkDisplay = gdk_display_get_default(); + if (aGdkKeyEvent->is_modifier && GDK_IS_X11_DISPLAY(gdkDisplay)) { Display* display = - gdk_x11_display_get_xdisplay(gdk_display_get_default()); + gdk_x11_display_get_xdisplay(gdkDisplay); if (XEventsQueued(display, QueuedAfterReading)) { XEvent nextEvent; XPeekEvent(display, &nextEvent); diff --git a/widget/gtk/nsIdleServiceGTK.cpp b/widget/gtk/nsIdleServiceGTK.cpp index 486d951859..d608f32021 100644 --- a/widget/gtk/nsIdleServiceGTK.cpp +++ b/widget/gtk/nsIdleServiceGTK.cpp @@ -32,6 +32,9 @@ NS_IMPL_ISUPPORTS_INHERITED0(nsIdleServiceGTK, nsIdleService) static void Initialize() { + if (!GDK_IS_X11_DISPLAY(gdk_display_get_default())) + return; + // This will leak - See comments in ~nsIdleServiceGTK(). PRLibrary* xsslib = PR_LoadLibrary("libXss.so.1"); if (!xsslib) // ouch. @@ -125,4 +128,3 @@ nsIdleServiceGTK::UsePollMode() { return sInitialized; } - diff --git a/widget/gtk/nsScreenManagerGtk.cpp b/widget/gtk/nsScreenManagerGtk.cpp index 92ba79ce21..98650d3271 100644 --- a/widget/gtk/nsScreenManagerGtk.cpp +++ b/widget/gtk/nsScreenManagerGtk.cpp @@ -53,6 +53,7 @@ root_window_event_filter(GdkXEvent *aGdkXEvent, GdkEvent *aGdkEvent, nsScreenManagerGtk :: nsScreenManagerGtk ( ) : mXineramalib(nullptr) , mRootWindow(nullptr) + , mNetWorkareaAtom(0) { // nothing else to do. I guess we could cache a bunch of information // here, but we want to ask the device at runtime in case anything @@ -100,8 +101,9 @@ nsScreenManagerGtk :: EnsureInit() GDK_PROPERTY_CHANGE_MASK)); gdk_window_add_filter(mRootWindow, root_window_event_filter, this); #ifdef MOZ_X11 - mNetWorkareaAtom = - XInternAtom(GDK_WINDOW_XDISPLAY(mRootWindow), "_NET_WORKAREA", False); + if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) + mNetWorkareaAtom = + XInternAtom(GDK_WINDOW_XDISPLAY(mRootWindow), "_NET_WORKAREA", False); #endif return Init(); @@ -114,7 +116,9 @@ nsScreenManagerGtk :: Init() XineramaScreenInfo *screenInfo = nullptr; int numScreens; - if (!mXineramalib) { + bool useXinerama = GDK_IS_X11_DISPLAY(gdk_display_get_default()); + + if (useXinerama && !mXineramalib) { mXineramalib = PR_LoadLibrary("libXinerama.so.1"); if (!mXineramalib) { mXineramalib = SCREEN_MANAGER_LIBRARY_LOAD_FAILED; diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index fb843e6f2b..31f563812f 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -729,14 +729,13 @@ nsWindow::GetParent(void) float nsWindow::GetDPI() { - Display *dpy = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); - int defaultScreen = DefaultScreen(dpy); - double heightInches = DisplayHeightMM(dpy, defaultScreen)/MM_PER_INCH_FLOAT; + GdkScreen *screen = gdk_display_get_default_screen(gdk_display_get_default()); + double heightInches = gdk_screen_get_height_mm(screen)/MM_PER_INCH_FLOAT; if (heightInches < 0.25) { // Something's broken, but we'd better not crash. return 96.0f; } - return float(DisplayHeight(dpy, defaultScreen)/heightInches); + return float(gdk_screen_get_height(screen)/heightInches); } double @@ -1951,22 +1950,25 @@ nsWindow::HasPendingInputEvent() bool haveEvent; #ifdef MOZ_X11 XEvent ev; - Display *display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); - haveEvent = - XCheckMaskEvent(display, - KeyPressMask | KeyReleaseMask | ButtonPressMask | - ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | - PointerMotionMask | PointerMotionHintMask | - Button1MotionMask | Button2MotionMask | - Button3MotionMask | Button4MotionMask | - Button5MotionMask | ButtonMotionMask | KeymapStateMask | - VisibilityChangeMask | StructureNotifyMask | - ResizeRedirectMask | SubstructureNotifyMask | - SubstructureRedirectMask | FocusChangeMask | - PropertyChangeMask | ColormapChangeMask | - OwnerGrabButtonMask, &ev); - if (haveEvent) { - XPutBackEvent(display, &ev); + GdkDisplay* gdkDisplay = gdk_display_get_default(); + if (GDK_IS_X11_DISPLAY(gdkDisplay)) { + Display *display = GDK_DISPLAY_XDISPLAY(gdkDisplay); + haveEvent = + XCheckMaskEvent(display, + KeyPressMask | KeyReleaseMask | ButtonPressMask | + ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | + PointerMotionMask | PointerMotionHintMask | + Button1MotionMask | Button2MotionMask | + Button3MotionMask | Button4MotionMask | + Button5MotionMask | ButtonMotionMask | KeymapStateMask | + VisibilityChangeMask | StructureNotifyMask | + ResizeRedirectMask | SubstructureNotifyMask | + SubstructureRedirectMask | FocusChangeMask | + PropertyChangeMask | ColormapChangeMask | + OwnerGrabButtonMask, &ev); + if (haveEvent) { + XPutBackEvent(display, &ev); + } } #else haveEvent = false; @@ -2605,23 +2607,26 @@ nsWindow::OnMotionNotifyEvent(GdkEventMotion *aEvent) #ifdef MOZ_X11 XEvent xevent; - while (XPending (GDK_WINDOW_XDISPLAY(aEvent->window))) { - XEvent peeked; - XPeekEvent (GDK_WINDOW_XDISPLAY(aEvent->window), &peeked); - if (peeked.xany.window != gdk_x11_window_get_xid(aEvent->window) - || peeked.type != MotionNotify) - break; + bool isX11Display = GDK_IS_X11_DISPLAY(gdk_display_get_default()); + if (isX11Display) { + while (XPending (GDK_WINDOW_XDISPLAY(aEvent->window))) { + XEvent peeked; + XPeekEvent (GDK_WINDOW_XDISPLAY(aEvent->window), &peeked); + if (peeked.xany.window != gdk_x11_window_get_xid(aEvent->window) + || peeked.type != MotionNotify) + break; - synthEvent = true; - XNextEvent (GDK_WINDOW_XDISPLAY(aEvent->window), &xevent); - } + synthEvent = true; + XNextEvent (GDK_WINDOW_XDISPLAY(aEvent->window), &xevent); + } #if (MOZ_WIDGET_GTK == 2) - // if plugins still keeps the focus, get it back - if (gPluginFocusWindow && gPluginFocusWindow != this) { - nsRefPtr kungFuDeathGrip = gPluginFocusWindow; - gPluginFocusWindow->LoseNonXEmbedPluginFocus(); - } + // if plugins still keeps the focus, get it back + if (gPluginFocusWindow && gPluginFocusWindow != this) { + nsRefPtr kungFuDeathGrip = gPluginFocusWindow; + gPluginFocusWindow->LoseNonXEmbedPluginFocus(); + } #endif /* MOZ_WIDGET_GTK2 */ + } #endif /* MOZ_X11 */ WidgetMouseEvent event(true, NS_MOUSE_MOVE, this, WidgetMouseEvent::eReal); @@ -3922,20 +3927,23 @@ nsWindow::SetWindowClass(const nsAString &xulWinType) gdk_window_set_role(shellWindow, role); #ifdef MOZ_X11 - XClassHint *class_hint = XAllocClassHint(); - if (!class_hint) { - free(res_name); - return NS_ERROR_OUT_OF_MEMORY; - } - class_hint->res_name = res_name; - class_hint->res_class = const_cast(res_class); + GdkDisplay *display = gdk_display_get_default(); + if (GDK_IS_X11_DISPLAY(display)) { + XClassHint *class_hint = XAllocClassHint(); + if (!class_hint) { + free(res_name); + return NS_ERROR_OUT_OF_MEMORY; + } + class_hint->res_name = res_name; + class_hint->res_class = const_cast(res_class); - // Can't use gtk_window_set_wmclass() for this; it prints - // a warning & refuses to make the change. - XSetClassHint(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), - gdk_x11_window_get_xid(shellWindow), - class_hint); - XFree(class_hint); + // Can't use gtk_window_set_wmclass() for this; it prints + // a warning & refuses to make the change. + XSetClassHint(GDK_DISPLAY_XDISPLAY(display), + gdk_x11_window_get_xid(shellWindow), + class_hint); + XFree(class_hint); + } #endif /* MOZ_X11 */ free(res_name); @@ -5652,20 +5660,22 @@ key_press_event_cb(GtkWidget *widget, GdkEventKey *event) // are generated only when the key is physically released. #define NS_GDKEVENT_MATCH_MASK 0x1FFF /* GDK_SHIFT_MASK .. GDK_BUTTON5_MASK */ GdkDisplay* gdkDisplay = gtk_widget_get_display(widget); - Display* dpy = GDK_DISPLAY_XDISPLAY(gdkDisplay); - while (XPending(dpy)) { - XEvent next_event; - XPeekEvent(dpy, &next_event); - GdkWindow* nextGdkWindow = - gdk_x11_window_lookup_for_display(gdkDisplay, next_event.xany.window); - if (nextGdkWindow != event->window || - next_event.type != KeyPress || - next_event.xkey.keycode != event->hardware_keycode || - next_event.xkey.state != (event->state & NS_GDKEVENT_MATCH_MASK)) { - break; + if (GDK_IS_X11_DISPLAY(gdkDisplay)) { + Display* dpy = GDK_DISPLAY_XDISPLAY(gdkDisplay); + while (XPending(dpy)) { + XEvent next_event; + XPeekEvent(dpy, &next_event); + GdkWindow* nextGdkWindow = + gdk_x11_window_lookup_for_display(gdkDisplay, next_event.xany.window); + if (nextGdkWindow != event->window || + next_event.type != KeyPress || + next_event.xkey.keycode != event->hardware_keycode || + next_event.xkey.state != (event->state & NS_GDKEVENT_MATCH_MASK)) { + break; + } + XNextEvent(dpy, &next_event); + event->time = next_event.xkey.time; } - XNextEvent(dpy, &next_event); - event->time = next_event.xkey.time; } #endif diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index 4cb746fbf9..d6baf59cef 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -862,7 +862,7 @@ struct ClearJSHolder : TraceCallbacks { virtual void Trace(JS::Heap* aPtr, const char*, void*) const override { - *aPtr = JSVAL_VOID; + aPtr->setUndefined(); } virtual void Trace(JS::Heap* aPtr, const char*, void*) const override