From 7f5366e43487ee1947bd9a22ed338f91f8a98e7d Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Fri, 6 Jul 2018 14:17:59 -0600 Subject: [PATCH 01/10] Bug 1463909 - Update android-4.3 avd for 'mach android-emulator'; r=me,a=test-only The new avd is compatible with emulator 27.2.9 as well as earlier versions such as 27.1.12. --- .../androidarm_4_3/mach-emulator.manifest | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testing/config/tooltool-manifests/androidarm_4_3/mach-emulator.manifest b/testing/config/tooltool-manifests/androidarm_4_3/mach-emulator.manifest index e066c30e8fc8..bdb5baf737e8 100644 --- a/testing/config/tooltool-manifests/androidarm_4_3/mach-emulator.manifest +++ b/testing/config/tooltool-manifests/androidarm_4_3/mach-emulator.manifest @@ -1,10 +1,10 @@ [ { - "size": 138424593, + "size": 136616367, "visibility": "public", - "digest": "1746b9c86d982492152567967aecdde147293f9f1d7b230821c191943fca8c39641276343ea4b1b2fc8eafb92f7b37507917ef7e2e1fd5b7f9b37d94050cec40", + "digest": "2e13e2ca795dc48ebcfe455bb1f9ec13c3d8b5095521acf94326ea44881aee8802b9021e19c93607db828ce8673fe421685c427c5cf31ced03a461f859dcd5dc", "algorithm": "sha512", - "filename": "AVDs-armv7a-android-4.3.1_r1-build-2018-06-07.tar.gz", + "filename": "AVDs-armv7a-android-4.3.1_r1-build-2018-07-06.tar.gz", "unpack": true } ] From 5c9335136ef56c632dd6b4cad50fb306fc67e267 Mon Sep 17 00:00:00 2001 From: Aaron Klotz Date: Wed, 4 Jul 2018 14:14:18 -0600 Subject: [PATCH 02/10] Bug 1473371: Create a separate function hook type for use with cross-process DLL interceptors; r=handyman --- browser/app/winlauncher/DllBlocklistWin.cpp | 14 +- mozglue/misc/nsWindowsDllInterceptor.h | 139 ++++++++++++++---- .../TestDllInterceptorCrossProcess.cpp | 12 +- 3 files changed, 117 insertions(+), 48 deletions(-) diff --git a/browser/app/winlauncher/DllBlocklistWin.cpp b/browser/app/winlauncher/DllBlocklistWin.cpp index a88a0747348f..a7c55882e7a4 100644 --- a/browser/app/winlauncher/DllBlocklistWin.cpp +++ b/browser/app/winlauncher/DllBlocklistWin.cpp @@ -357,21 +357,13 @@ InitializeDllBlocklistOOP(HANDLE aChildProcess) { mozilla::CrossProcessDllInterceptor intcpt(aChildProcess); intcpt.Init(L"ntdll.dll"); - bool ok = stub_NtMapViewOfSection.SetDetour(intcpt, "NtMapViewOfSection", + bool ok = stub_NtMapViewOfSection.SetDetour(aChildProcess, intcpt, + "NtMapViewOfSection", &patched_NtMapViewOfSection); if (!ok) { return false; } - // Set the child process's copy of stub_NtMapViewOfSection - SIZE_T bytesWritten; - ok = !!::WriteProcessMemory(aChildProcess, &stub_NtMapViewOfSection, - &stub_NtMapViewOfSection, - sizeof(stub_NtMapViewOfSection), &bytesWritten); - if (!ok) { - return false; - } - // Because aChildProcess has just been created in a suspended state, its // dynamic linker has not yet been initialized, thus its executable has // not yet been linked with ntdll.dll. If the blocklist hook intercepts a @@ -407,6 +399,8 @@ InitializeDllBlocklistOOP(HANDLE aChildProcess) ptrdiff_t iatLength = (curIatThunk - firstIatThunk) * sizeof(IMAGE_THUNK_DATA); + SIZE_T bytesWritten; + { // Scope for prot AutoVirtualProtect prot(firstIatThunk, iatLength, PAGE_READWRITE, aChildProcess); diff --git a/mozglue/misc/nsWindowsDllInterceptor.h b/mozglue/misc/nsWindowsDllInterceptor.h index 4ae504257b56..473ef201a4fc 100644 --- a/mozglue/misc/nsWindowsDllInterceptor.h +++ b/mozglue/misc/nsWindowsDllInterceptor.h @@ -84,32 +84,32 @@ namespace mozilla { namespace interceptor { +template +struct OriginalFunctionPtrTraits; + +template +struct OriginalFunctionPtrTraits +{ + using ReturnType = R; +}; + +#if defined(_M_IX86) +template +struct OriginalFunctionPtrTraits +{ + using ReturnType = R; +}; + +template +struct OriginalFunctionPtrTraits +{ + using ReturnType = R; +}; +#endif // defined(_M_IX86) + template class FuncHook final { - template - struct OriginalFunctionPtrTraits; - - template - struct OriginalFunctionPtrTraits - { - using ReturnType = R; - }; - -#if defined(_M_IX86) - template - struct OriginalFunctionPtrTraits - { - using ReturnType = R; - }; - - template - struct OriginalFunctionPtrTraits - { - using ReturnType = R; - }; -#endif // defined(_M_IX86) - public: using ThisType = FuncHook; using ReturnType = typename OriginalFunctionPtrTraits::ReturnType; @@ -221,15 +221,99 @@ private: INIT_ONCE mInitOnce; }; +template +class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS FuncHookCrossProcess final +{ +public: + using ThisType = FuncHookCrossProcess; + using ReturnType = typename OriginalFunctionPtrTraits::ReturnType; + +#if defined(DEBUG) + FuncHookCrossProcess() {} +#endif // defined(DEBUG) + + bool Set(HANDLE aProcess, InterceptorT& aInterceptor, const char* aName, + FuncPtrT aHookDest) + { + if (!aInterceptor.AddHook(aName, reinterpret_cast(aHookDest), + reinterpret_cast(&mOrigFunc))) { + return false; + } + + return CopyStubToChildProcess(aProcess); + } + + bool SetDetour(HANDLE aProcess, InterceptorT& aInterceptor, const char* aName, + FuncPtrT aHookDest) + { + if (!aInterceptor.AddDetour(aName, reinterpret_cast(aHookDest), + reinterpret_cast(&mOrigFunc))) { + return false; + } + + return CopyStubToChildProcess(aProcess); + } + + explicit operator bool() const + { + return !!mOrigFunc; + } + + /** + * NB: This operator is only meaningful when invoked in the target process! + */ + template + ReturnType operator()(ArgsType... aArgs) const + { + return mOrigFunc(std::forward(aArgs)...); + } + +#if defined(DEBUG) + FuncHookCrossProcess(const FuncHookCrossProcess&) = delete; + FuncHookCrossProcess(FuncHookCrossProcess&&) = delete; + FuncHookCrossProcess& operator=(const FuncHookCrossProcess&) = delete; + FuncHookCrossProcess& operator=(FuncHookCrossProcess&& aOther) = delete; +#endif // defined(DEBUG) + +private: + bool CopyStubToChildProcess(HANDLE aProcess) + { + SIZE_T bytesWritten; + return !!::WriteProcessMemory(aProcess, &mOrigFunc, &mOrigFunc, + sizeof(mOrigFunc), &bytesWritten); + } + +private: + FuncPtrT mOrigFunc; +}; + enum { kDefaultTrampolineSize = 128 }; +template +struct TypeResolver; + +template +struct TypeResolver +{ + template + using FuncHookType = FuncHook; +}; + +template +struct TypeResolver +{ + template + using FuncHookType = FuncHookCrossProcess; +}; + template > -class WindowsDllInterceptor final +class WindowsDllInterceptor final : public TypeResolver> { typedef WindowsDllInterceptor ThisType; @@ -372,13 +456,12 @@ private: return mDetourPatcher.AddHook(aProc, aHookDest, aOrigFunc); } -public: - template - using FuncHookType = FuncHook; - private: template friend class FuncHook; + + template + friend class FuncHookCrossProcess; }; } // namespace interceptor diff --git a/mozglue/tests/interceptor/TestDllInterceptorCrossProcess.cpp b/mozglue/tests/interceptor/TestDllInterceptorCrossProcess.cpp index c29d132ba9b0..7a2ee3737504 100644 --- a/mozglue/tests/interceptor/TestDllInterceptorCrossProcess.cpp +++ b/mozglue/tests/interceptor/TestDllInterceptorCrossProcess.cpp @@ -73,22 +73,14 @@ int ParentMain() mozilla::CrossProcessDllInterceptor intcpt(childProcess.get()); intcpt.Init("TestDllInterceptorCrossProcess.exe"); - if (!gOrigReturnResult.Set(intcpt, "ReturnResult", &ReturnResultHook)) { + if (!gOrigReturnResult.Set(childProcess.get(), intcpt, "ReturnResult", + &ReturnResultHook)) { printf("TEST-UNEXPECTED-FAIL | DllInterceptorCrossProcess | Failed to add hook\n"); return 1; } printf("TEST-PASS | DllInterceptorCrossProcess | Hook added\n"); - // Let's save the original hook - SIZE_T bytesWritten; - if (!::WriteProcessMemory(childProcess.get(), &gOrigReturnResult, - &gOrigReturnResult, sizeof(gOrigReturnResult), - &bytesWritten)) { - printf("TEST-UNEXPECTED-FAIL | DllInterceptorCrossProcess | Failed to write original function pointer\n"); - return 1; - } - if (::ResumeThread(childMainThread.get()) == static_cast(-1)) { printf("TEST-UNEXPECTED-FAIL | DllInterceptorCrossProcess | Failed to resume child thread\n"); return 1; From 9ea8dee08abcaa954175b9884656c8c9e3eae6b1 Mon Sep 17 00:00:00 2001 From: Arthur Iakab Date: Thu, 5 Jul 2018 21:19:00 +0300 Subject: [PATCH 03/10] Bug 1345346 - Disabled browser/components/originattributes/test/browser/browser_firstPartyIsolation.js for frequent failures. r=jmaher --- browser/components/originattributes/test/browser/browser.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/components/originattributes/test/browser/browser.ini b/browser/components/originattributes/test/browser/browser.ini index 7e8bf358db93..ace5a1a438ce 100644 --- a/browser/components/originattributes/test/browser/browser.ini +++ b/browser/components/originattributes/test/browser/browser.ini @@ -65,7 +65,7 @@ skip-if = verify [browser_favicon_firstParty.js] [browser_favicon_userContextId.js] [browser_firstPartyIsolation.js] -skip-if = verify +skip-if = verify || debug #Bug 1345346 [browser_firstPartyIsolation_about_newtab.js] [browser_firstPartyIsolation_aboutPages.js] [browser_firstPartyIsolation_blobURI.js] From d956f37c5e948802417e950aff3b5818ab69271b Mon Sep 17 00:00:00 2001 From: Stefan Hindli Date: Fri, 6 Jul 2018 07:26:00 +0300 Subject: [PATCH 04/10] Bug 1465683 - Disabled browser_dbg_search-symbols.js on Windows !debug r=jmaher --- devtools/client/debugger/test/mochitest/browser2.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devtools/client/debugger/test/mochitest/browser2.ini b/devtools/client/debugger/test/mochitest/browser2.ini index a2f926b14cf7..01909a43f344 100644 --- a/devtools/client/debugger/test/mochitest/browser2.ini +++ b/devtools/client/debugger/test/mochitest/browser2.ini @@ -313,7 +313,7 @@ uses-unsafe-cpows = true skip-if = e10s && debug [browser_dbg_search-symbols.js] uses-unsafe-cpows = true -skip-if = (e10s && debug) || os == "linux" # Bug 1132375 +skip-if = (e10s && debug) || os == "linux" || (os == "win" && !debug) # Bug 1132375 # Bug 1465683 [browser_dbg_searchbox-help-popup-01.js] uses-unsafe-cpows = true skip-if = e10s && debug From 5ee773b824cc04a844e997af1c913aef5d1d6e05 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Fri, 6 Jul 2018 16:47:22 -0400 Subject: [PATCH 05/10] Bug 1471726 - Part 1: Correct codegen for XPIDL arrays of JSVals, r=mccr8 --- xpcom/idl-parser/xpidl/xpidl.py | 133 ++++++++++++----------- xpcom/rust/xpcom/src/reexports.rs | 2 +- xpcom/rust/xpcom/xpcom_macros/src/lib.rs | 4 +- 3 files changed, 74 insertions(+), 65 deletions(-) diff --git a/xpcom/idl-parser/xpidl/xpidl.py b/xpcom/idl-parser/xpidl/xpidl.py index 6939537214b8..b9e978df12bc 100755 --- a/xpcom/idl-parser/xpidl/xpidl.py +++ b/xpcom/idl-parser/xpidl/xpidl.py @@ -20,7 +20,7 @@ from ply import yacc def nativeType(self, calltype): 'returns a string representation of the native type - calltype must be 'in', 'out', or 'inout' + calltype must be 'in', 'out', 'inout', or 'element' Interface members const/method/attribute conform to the following pattern: @@ -144,7 +144,7 @@ class Builtin(object): else: const = '' return "%s%s %s" % (const, self.nativename, - calltype != 'in' and '*' or '') + '*' if 'out' in calltype else '') def rustType(self, calltype, shared=False, const=False): # We want to rewrite any *mut pointers to *const pointers if constness @@ -400,8 +400,7 @@ class Typedef(object): return self.realtype.isScriptable() def nativeType(self, calltype): - return "%s %s" % (self.name, - calltype != 'in' and '*' or '') + return "%s %s" % (self.name, '*' if 'out' in calltype else '') def rustType(self, calltype): return "%s%s" % (calltype != 'in' and '*mut ' or '', @@ -440,8 +439,7 @@ class Forward(object): return True def nativeType(self, calltype): - return "%s %s" % (self.name, - calltype != 'in' and '* *' or '*') + return "%s *%s" % (self.name, '*' if 'out' in calltype else '') def rustType(self, calltype): if rustBlacklistedForward(self.name): @@ -459,29 +457,19 @@ class Native(object): modifier = None specialtype = None + # A tuple type here means that a custom value is used for each calltype: + # (in, out/inout, array element) respectively. + # A `None` here means that the written type should be used as-is. specialtypes = { 'nsid': None, - 'domstring': 'nsAString', - 'utf8string': 'nsACString', - 'cstring': 'nsACString', - 'astring': 'nsAString', - 'jsval': 'JS::Value', + 'domstring': ('const nsAString&', 'nsAString&', 'nsString'), + 'utf8string': ('const nsACString&', 'nsACString&', 'nsCString'), + 'cstring': ('const nsACString&', 'nsACString&', 'nsCString'), + 'astring': ('const nsAString&', 'nsAString&', 'nsString'), + 'jsval': ('JS::HandleValue', 'JS::MutableHandleValue', 'JS::Value'), 'promise': '::mozilla::dom::Promise', } - # Mappings from C++ native name types to rust native names. Types which - # aren't listed here are incompatible with rust code. - rust_nativenames = { - 'void': "libc::c_void", - 'char': "u8", - 'char16_t': "u16", - 'nsID': "nsID", - 'nsIID': "nsIID", - 'nsCID': "nsCID", - 'nsAString': "::nsstring::nsAString", - 'nsACString': "::nsstring::nsACString", - } - def __init__(self, name, nativename, attlist, location): self.name = name self.nativename = nativename @@ -536,44 +524,57 @@ class Native(object): raise IDLError("[shared] only applies to out parameters.") const = True - if self.specialtype not in [None, 'promise'] and calltype == 'in': + if isinstance(self.nativename, tuple): + if calltype == 'in': + return self.nativename[0] + ' ' + elif 'out' in calltype: + return self.nativename[1] + ' ' + else: + return self.nativename[2] + ' ' + + # 'in' nsid parameters should be made 'const' + if self.specialtype == 'nsid' and calltype == 'in': const = True - if self.specialtype == 'jsval': - if calltype == 'out' or calltype == 'inout': - return "JS::MutableHandleValue " - return "JS::HandleValue " - if self.isRef(calltype): - m = '& ' - elif self.isPtr(calltype): - m = '*' + ((self.modifier == 'ptr' and calltype != 'in') and '*' or '') + m = '& ' # [ref] is always passed with a single indirection else: - m = calltype != 'in' and '*' or '' + m = '* ' if 'out' in calltype else '' + if self.isPtr(calltype): + m += '* ' return "%s%s %s" % (const and 'const ' or '', self.nativename, m) def rustType(self, calltype, const=False, shared=False): - if shared: - if calltype != 'out': - raise IDLError("[shared] only applies to out parameters.") - const = True + # For the most part, 'native' types don't make sense in rust, as they + # are native C++ types. However, we can support a few types here, as + # they're important. + # + # NOTE: This code doesn't try to perfectly match C++ constness, as + # constness doesn't affect ABI, and raw pointers are already unsafe. - if self.specialtype is not None and calltype == 'in': - const = True + if self.modifier not in ['ptr', 'ref']: + raise RustNoncompat('Rust only supports [ref] / [ptr] native types') - if self.nativename not in self.rust_nativenames: - raise RustNoncompat("native type %s is unsupported" % self.nativename) - name = self.rust_nativenames[self.nativename] + prefix = '*mut ' if 'out' in calltype else '*const ' + if 'out' in calltype and self.modifier == 'ptr': + prefix += '*mut ' - if self.isRef(calltype): - m = const and '&' or '&mut ' - elif self.isPtr(calltype): - m = (const and '*const ' or '*mut ') - if self.modifier == 'ptr' and calltype != 'in': - m += '*mut ' - else: - m = calltype != 'in' and '*mut ' or '' - return "%s%s" % (m, name) + if self.specialtype == 'nsid': + return prefix + self.nativename + if self.specialtype in ['cstring', 'utf8string']: + if calltype == 'element': + return '::nsstring::nsCString' + return prefix + '::nsstring::nsACString' + if self.specialtype in ['astring', 'domstring']: + if calltype == 'element': + return '::nsstring::nsString' + return prefix + '::nsstring::nsAString' + if self.nativename == 'void': + return prefix + 'libc::c_void' + + if self.specialtype: + raise RustNoncompat("specialtype %s unsupported" % self.specialtype) + raise RustNoncompat("native type %s unsupported" % self.nativename) def __str__(self): return "native %s(%s)\n" % (self.name, self.nativename) @@ -613,11 +614,11 @@ class WebIDL(object): return True # All DOM objects are script exposed. def nativeType(self, calltype): - return "%s %s" % (self.native, calltype != 'in' and '* *' or '*') + return "%s *%s" % (self.native, '*' if 'out' in calltype else '') def rustType(self, calltype): # Just expose the type as a void* - we can't do any better. - return "%s*const libc::c_void" % (calltype != 'in' and '*mut ' or '') + return "%s*const libc::c_void" % ('*mut ' if 'out' in calltype else '') def __str__(self): return "webidl %s\n" % self.name @@ -713,12 +714,11 @@ class Interface(object): return True def nativeType(self, calltype, const=False): - return "%s%s %s" % (const and 'const ' or '', - self.name, - calltype != 'in' and '* *' or '*') + return "%s%s *%s" % ('const ' if const else '', self.name, + '*' if 'out' in calltype else '') - def rustType(self, calltype): - return "%s*const %s" % (calltype != 'in' and '*mut ' or '', + def rustType(self, calltype, const=False): + return "%s*const %s" % ('*mut ' if 'out' in calltype else '', self.name) def __str__(self): @@ -1219,12 +1219,19 @@ class Array(object): return self.type.isScriptable() def nativeType(self, calltype, const=False): - return "%s%s*" % (const and 'const ' or '', - self.type.nativeType(calltype)) + # For legacy reasons, we have to add a 'const ' to builtin pointer array + # types. (`[array] in string` and `[array] in wstring` parameters) + if calltype == 'in' and isinstance(self.type, Builtin) and self.type.isPointer(): + const = True + + return "%s%s*%s" % ('const ' if const else '', + self.type.nativeType('element'), + '*' if 'out' in calltype else '') def rustType(self, calltype, const=False): - return "%s %s" % (const and '*const' or '*mut', - self.type.rustType(calltype)) + return "%s%s%s" % ('*mut ' if 'out' in calltype else '', + '*const ' if const else '*mut ', + self.type.rustType('element')) class IDLParser(object): diff --git a/xpcom/rust/xpcom/src/reexports.rs b/xpcom/rust/xpcom/src/reexports.rs index 5673c0d6d5ef..623e8a44580e 100644 --- a/xpcom/rust/xpcom/src/reexports.rs +++ b/xpcom/rust/xpcom/src/reexports.rs @@ -11,7 +11,7 @@ // re-export libc so it can be used by the procedural macro. pub extern crate libc; -pub use nsstring::{nsACString, nsAString}; +pub use nsstring::{nsACString, nsAString, nsCString, nsString}; pub use nserror::{nsresult, NsresultExt, NS_ERROR_NO_INTERFACE, NS_OK}; diff --git a/xpcom/rust/xpcom/xpcom_macros/src/lib.rs b/xpcom/rust/xpcom/xpcom_macros/src/lib.rs index 7b576b1ca568..260d4ca64b18 100644 --- a/xpcom/rust/xpcom/xpcom_macros/src/lib.rs +++ b/xpcom/rust/xpcom/xpcom_macros/src/lib.rs @@ -563,7 +563,9 @@ fn xpcom(init: DeriveInput) -> Result> { #[allow(unused_imports)] use ::xpcom::interfaces::*; #[allow(unused_imports)] - use ::xpcom::reexports::{libc, nsACString, nsAString, nsresult}; + use ::xpcom::reexports::{ + libc, nsACString, nsAString, nsCString, nsString, nsresult + }; unsafe { // NOTE: This is split into multiple lines to make the From 95e4893811d0c2c88da34793eca1cf0d6456c43c Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Fri, 6 Jul 2018 16:48:20 -0400 Subject: [PATCH 06/10] Bug 1471726 - Part 2: Add basic tests for jsval array codegen, r=mccr8 --- js/xpconnect/tests/components/js/xpctest_params.js | 1 + js/xpconnect/tests/components/native/xpctest_params.cpp | 7 +++++++ js/xpconnect/tests/idl/xpctest_params.idl | 6 ++++++ js/xpconnect/tests/unit/test_params.js | 2 ++ 4 files changed, 16 insertions(+) diff --git a/js/xpconnect/tests/components/js/xpctest_params.js b/js/xpconnect/tests/components/js/xpctest_params.js index f8eaa2083858..7f7e04d5fb2d 100644 --- a/js/xpconnect/tests/components/js/xpctest_params.js +++ b/js/xpconnect/tests/components/js/xpctest_params.js @@ -69,6 +69,7 @@ TestParams.prototype = { testStringArray: f_is, testWstringArray: f_is, testInterfaceArray: f_is, + testJsvalArray: f_is, testSizedString: f_is, testSizedWstring: f_is, testInterfaceIs: f_is, diff --git a/js/xpconnect/tests/components/native/xpctest_params.cpp b/js/xpconnect/tests/components/native/xpctest_params.cpp index e88746d89375..1e2a8aea8deb 100644 --- a/js/xpconnect/tests/components/native/xpctest_params.cpp +++ b/js/xpconnect/tests/components/native/xpctest_params.cpp @@ -223,6 +223,13 @@ NS_IMETHODIMP nsXPCTestParams::TestInterfaceArray(uint32_t aLength, nsIXPCTestIn BUFFER_METHOD_IMPL(nsIXPCTestInterfaceA*, 0, TAKE_OWNERSHIP_INTERFACE); } +NS_IMETHODIMP nsXPCTestParams::TestJsvalArray(uint32_t aLength, JS::Value *a, + uint32_t* bLength, JS::Value **b, + uint32_t* rvLength, JS::Value **rv) +{ + BUFFER_METHOD_IMPL(JS::Value, 0, TAKE_OWNERSHIP_NOOP); +} + NS_IMETHODIMP nsXPCTestParams::TestSizedString(uint32_t aLength, const char * a, uint32_t* bLength, char * *b, uint32_t* rvLength, char * *rv) diff --git a/js/xpconnect/tests/idl/xpctest_params.idl b/js/xpconnect/tests/idl/xpctest_params.idl index f324a4595a4b..fcbc690a4e5a 100644 --- a/js/xpconnect/tests/idl/xpctest_params.idl +++ b/js/xpconnect/tests/idl/xpctest_params.idl @@ -82,6 +82,12 @@ interface nsIXPCTestParams : nsISupports { out unsigned long rvLength, out nsIIDPtr rvIID, [retval, array, size_is(rvLength), iid_is(rvIID)] out nsQIResult rv); + // Test arrays of jsvals + void testJsvalArray(in unsigned long aLength, [array, size_is(aLength)] in jsval a, + inout unsigned long bLength, [array, size_is(bLength)] inout jsval b, + out unsigned long rvLength, [retval, array, size_is(rvLength)] out jsval rv); + + // Test for out dipper parameters void testOutAString(out AString o); diff --git a/js/xpconnect/tests/unit/test_params.js b/js/xpconnect/tests/unit/test_params.js index 2058c3d1f0b3..7bd1a2480dce 100644 --- a/js/xpconnect/tests/unit/test_params.js +++ b/js/xpconnect/tests/unit/test_params.js @@ -163,6 +163,8 @@ function test_component(contractid) { ["we", "are", "being", "sooo", "international", "right", "now"], 7, arrayComparator(standardComparator)); doIsTest("testInterfaceArray", [makeA(), makeA()], 2, [makeA(), makeA(), makeA(), makeA(), makeA(), makeA()], 6, arrayComparator(interfaceComparator)); + doIsTest("testJsvalArray", [{ cheese: 'whiz', apple: 8 }, [1, 5, '3'], /regex/], 3, + ['apple', 2.2e10, 3.3e30, { only: "wheedle", except: {} }], 4, arrayComparator(standardComparator)); // Test typed arrays and ArrayBuffer aliasing. var arrayBuffer = new ArrayBuffer(16); From aa3038043cc9d4f8fe079032fb4a1600bad3d2b4 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Fri, 6 Jul 2018 19:26:59 -0400 Subject: [PATCH 07/10] Bug 1461450 - Part 1: Add move constructors and assignment operators to nsTArray, r=froydnj --- xpcom/ds/nsTArray.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/xpcom/ds/nsTArray.h b/xpcom/ds/nsTArray.h index 87788f05c7b8..dd6c66804dc6 100644 --- a/xpcom/ds/nsTArray.h +++ b/xpcom/ds/nsTArray.h @@ -2460,6 +2460,13 @@ public: this->AppendElements(aOther); } + AutoTArray(self_type&& aOther) + : nsTArray() + { + Init(); + this->SwapElements(aOther); + } + explicit AutoTArray(const base_type& aOther) : mAlign() { @@ -2494,6 +2501,12 @@ public: return *this; } + self_type& operator=(self_type&& aOther) + { + base_type::operator=(std::move(aOther)); + return *this; + } + template self_type& operator=(const nsTArray_Impl& aOther) { From c1f2b811499d01b4da0ffb946146a9535bcdbc13 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Fri, 6 Jul 2018 19:27:38 -0400 Subject: [PATCH 08/10] Bug 1461450 - Part 2: Add tests for AutoTArray move constructors, r=erahm --- xpcom/tests/gtest/TestTArray2.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/xpcom/tests/gtest/TestTArray2.cpp b/xpcom/tests/gtest/TestTArray2.cpp index a228007acab5..f20e207b0bbb 100644 --- a/xpcom/tests/gtest/TestTArray2.cpp +++ b/xpcom/tests/gtest/TestTArray2.cpp @@ -382,6 +382,25 @@ TEST(TArray, test_move_array) { differentAllocatorMoveableArray2 = std::move(autoMoveableArray2); ASSERT_EQ(Moveable::Count(), 8); + + AutoTArray moveableAutoArray; + for (uint32_t i = 0; i < 4; ++i) { + ASSERT_TRUE(moveableAutoArray.AppendElement(Moveable())); + } + + ASSERT_EQ(Moveable::Count(), 12); + + const AutoTArray& constRefMoveableAutoArray = moveableAutoArray; + + ASSERT_EQ(Moveable::Count(), 12); + + AutoTArray copyMoveableAutoArray(constRefMoveableAutoArray); + + ASSERT_EQ(Moveable::Count(), 16); + + AutoTArray movedMoveableAutoArray(std::move(moveableAutoArray)); + + ASSERT_EQ(Moveable::Count(), 16); } //---- From f61df5dc45aff26ee0677bfeac3778e5a6d87b91 Mon Sep 17 00:00:00 2001 From: Ciure Andrei Date: Sat, 7 Jul 2018 03:12:10 +0300 Subject: [PATCH 09/10] Backed out 4 changesets (bug 1461450, bug 1471726) for linting failure xpidl.py CLOSED TREE Backed out changeset 6e8148c1ca7f (bug 1461450) Backed out changeset 2a02d86bc113 (bug 1461450) Backed out changeset 1907567a85c5 (bug 1471726) Backed out changeset c4df8eab6d1c (bug 1471726) --- .../tests/components/js/xpctest_params.js | 1 - .../components/native/xpctest_params.cpp | 7 - js/xpconnect/tests/idl/xpctest_params.idl | 6 - js/xpconnect/tests/unit/test_params.js | 2 - xpcom/ds/nsTArray.h | 13 -- xpcom/idl-parser/xpidl/xpidl.py | 133 +++++++++--------- xpcom/rust/xpcom/src/reexports.rs | 2 +- xpcom/rust/xpcom/xpcom_macros/src/lib.rs | 4 +- xpcom/tests/gtest/TestTArray2.cpp | 19 --- 9 files changed, 65 insertions(+), 122 deletions(-) diff --git a/js/xpconnect/tests/components/js/xpctest_params.js b/js/xpconnect/tests/components/js/xpctest_params.js index 7f7e04d5fb2d..f8eaa2083858 100644 --- a/js/xpconnect/tests/components/js/xpctest_params.js +++ b/js/xpconnect/tests/components/js/xpctest_params.js @@ -69,7 +69,6 @@ TestParams.prototype = { testStringArray: f_is, testWstringArray: f_is, testInterfaceArray: f_is, - testJsvalArray: f_is, testSizedString: f_is, testSizedWstring: f_is, testInterfaceIs: f_is, diff --git a/js/xpconnect/tests/components/native/xpctest_params.cpp b/js/xpconnect/tests/components/native/xpctest_params.cpp index 1e2a8aea8deb..e88746d89375 100644 --- a/js/xpconnect/tests/components/native/xpctest_params.cpp +++ b/js/xpconnect/tests/components/native/xpctest_params.cpp @@ -223,13 +223,6 @@ NS_IMETHODIMP nsXPCTestParams::TestInterfaceArray(uint32_t aLength, nsIXPCTestIn BUFFER_METHOD_IMPL(nsIXPCTestInterfaceA*, 0, TAKE_OWNERSHIP_INTERFACE); } -NS_IMETHODIMP nsXPCTestParams::TestJsvalArray(uint32_t aLength, JS::Value *a, - uint32_t* bLength, JS::Value **b, - uint32_t* rvLength, JS::Value **rv) -{ - BUFFER_METHOD_IMPL(JS::Value, 0, TAKE_OWNERSHIP_NOOP); -} - NS_IMETHODIMP nsXPCTestParams::TestSizedString(uint32_t aLength, const char * a, uint32_t* bLength, char * *b, uint32_t* rvLength, char * *rv) diff --git a/js/xpconnect/tests/idl/xpctest_params.idl b/js/xpconnect/tests/idl/xpctest_params.idl index fcbc690a4e5a..f324a4595a4b 100644 --- a/js/xpconnect/tests/idl/xpctest_params.idl +++ b/js/xpconnect/tests/idl/xpctest_params.idl @@ -82,12 +82,6 @@ interface nsIXPCTestParams : nsISupports { out unsigned long rvLength, out nsIIDPtr rvIID, [retval, array, size_is(rvLength), iid_is(rvIID)] out nsQIResult rv); - // Test arrays of jsvals - void testJsvalArray(in unsigned long aLength, [array, size_is(aLength)] in jsval a, - inout unsigned long bLength, [array, size_is(bLength)] inout jsval b, - out unsigned long rvLength, [retval, array, size_is(rvLength)] out jsval rv); - - // Test for out dipper parameters void testOutAString(out AString o); diff --git a/js/xpconnect/tests/unit/test_params.js b/js/xpconnect/tests/unit/test_params.js index 7bd1a2480dce..2058c3d1f0b3 100644 --- a/js/xpconnect/tests/unit/test_params.js +++ b/js/xpconnect/tests/unit/test_params.js @@ -163,8 +163,6 @@ function test_component(contractid) { ["we", "are", "being", "sooo", "international", "right", "now"], 7, arrayComparator(standardComparator)); doIsTest("testInterfaceArray", [makeA(), makeA()], 2, [makeA(), makeA(), makeA(), makeA(), makeA(), makeA()], 6, arrayComparator(interfaceComparator)); - doIsTest("testJsvalArray", [{ cheese: 'whiz', apple: 8 }, [1, 5, '3'], /regex/], 3, - ['apple', 2.2e10, 3.3e30, { only: "wheedle", except: {} }], 4, arrayComparator(standardComparator)); // Test typed arrays and ArrayBuffer aliasing. var arrayBuffer = new ArrayBuffer(16); diff --git a/xpcom/ds/nsTArray.h b/xpcom/ds/nsTArray.h index dd6c66804dc6..87788f05c7b8 100644 --- a/xpcom/ds/nsTArray.h +++ b/xpcom/ds/nsTArray.h @@ -2460,13 +2460,6 @@ public: this->AppendElements(aOther); } - AutoTArray(self_type&& aOther) - : nsTArray() - { - Init(); - this->SwapElements(aOther); - } - explicit AutoTArray(const base_type& aOther) : mAlign() { @@ -2501,12 +2494,6 @@ public: return *this; } - self_type& operator=(self_type&& aOther) - { - base_type::operator=(std::move(aOther)); - return *this; - } - template self_type& operator=(const nsTArray_Impl& aOther) { diff --git a/xpcom/idl-parser/xpidl/xpidl.py b/xpcom/idl-parser/xpidl/xpidl.py index b9e978df12bc..6939537214b8 100755 --- a/xpcom/idl-parser/xpidl/xpidl.py +++ b/xpcom/idl-parser/xpidl/xpidl.py @@ -20,7 +20,7 @@ from ply import yacc def nativeType(self, calltype): 'returns a string representation of the native type - calltype must be 'in', 'out', 'inout', or 'element' + calltype must be 'in', 'out', or 'inout' Interface members const/method/attribute conform to the following pattern: @@ -144,7 +144,7 @@ class Builtin(object): else: const = '' return "%s%s %s" % (const, self.nativename, - '*' if 'out' in calltype else '') + calltype != 'in' and '*' or '') def rustType(self, calltype, shared=False, const=False): # We want to rewrite any *mut pointers to *const pointers if constness @@ -400,7 +400,8 @@ class Typedef(object): return self.realtype.isScriptable() def nativeType(self, calltype): - return "%s %s" % (self.name, '*' if 'out' in calltype else '') + return "%s %s" % (self.name, + calltype != 'in' and '*' or '') def rustType(self, calltype): return "%s%s" % (calltype != 'in' and '*mut ' or '', @@ -439,7 +440,8 @@ class Forward(object): return True def nativeType(self, calltype): - return "%s *%s" % (self.name, '*' if 'out' in calltype else '') + return "%s %s" % (self.name, + calltype != 'in' and '* *' or '*') def rustType(self, calltype): if rustBlacklistedForward(self.name): @@ -457,19 +459,29 @@ class Native(object): modifier = None specialtype = None - # A tuple type here means that a custom value is used for each calltype: - # (in, out/inout, array element) respectively. - # A `None` here means that the written type should be used as-is. specialtypes = { 'nsid': None, - 'domstring': ('const nsAString&', 'nsAString&', 'nsString'), - 'utf8string': ('const nsACString&', 'nsACString&', 'nsCString'), - 'cstring': ('const nsACString&', 'nsACString&', 'nsCString'), - 'astring': ('const nsAString&', 'nsAString&', 'nsString'), - 'jsval': ('JS::HandleValue', 'JS::MutableHandleValue', 'JS::Value'), + 'domstring': 'nsAString', + 'utf8string': 'nsACString', + 'cstring': 'nsACString', + 'astring': 'nsAString', + 'jsval': 'JS::Value', 'promise': '::mozilla::dom::Promise', } + # Mappings from C++ native name types to rust native names. Types which + # aren't listed here are incompatible with rust code. + rust_nativenames = { + 'void': "libc::c_void", + 'char': "u8", + 'char16_t': "u16", + 'nsID': "nsID", + 'nsIID': "nsIID", + 'nsCID': "nsCID", + 'nsAString': "::nsstring::nsAString", + 'nsACString': "::nsstring::nsACString", + } + def __init__(self, name, nativename, attlist, location): self.name = name self.nativename = nativename @@ -524,57 +536,44 @@ class Native(object): raise IDLError("[shared] only applies to out parameters.") const = True - if isinstance(self.nativename, tuple): - if calltype == 'in': - return self.nativename[0] + ' ' - elif 'out' in calltype: - return self.nativename[1] + ' ' - else: - return self.nativename[2] + ' ' - - # 'in' nsid parameters should be made 'const' - if self.specialtype == 'nsid' and calltype == 'in': + if self.specialtype not in [None, 'promise'] and calltype == 'in': const = True + if self.specialtype == 'jsval': + if calltype == 'out' or calltype == 'inout': + return "JS::MutableHandleValue " + return "JS::HandleValue " + if self.isRef(calltype): - m = '& ' # [ref] is always passed with a single indirection + m = '& ' + elif self.isPtr(calltype): + m = '*' + ((self.modifier == 'ptr' and calltype != 'in') and '*' or '') else: - m = '* ' if 'out' in calltype else '' - if self.isPtr(calltype): - m += '* ' + m = calltype != 'in' and '*' or '' return "%s%s %s" % (const and 'const ' or '', self.nativename, m) def rustType(self, calltype, const=False, shared=False): - # For the most part, 'native' types don't make sense in rust, as they - # are native C++ types. However, we can support a few types here, as - # they're important. - # - # NOTE: This code doesn't try to perfectly match C++ constness, as - # constness doesn't affect ABI, and raw pointers are already unsafe. + if shared: + if calltype != 'out': + raise IDLError("[shared] only applies to out parameters.") + const = True - if self.modifier not in ['ptr', 'ref']: - raise RustNoncompat('Rust only supports [ref] / [ptr] native types') + if self.specialtype is not None and calltype == 'in': + const = True - prefix = '*mut ' if 'out' in calltype else '*const ' - if 'out' in calltype and self.modifier == 'ptr': - prefix += '*mut ' + if self.nativename not in self.rust_nativenames: + raise RustNoncompat("native type %s is unsupported" % self.nativename) + name = self.rust_nativenames[self.nativename] - if self.specialtype == 'nsid': - return prefix + self.nativename - if self.specialtype in ['cstring', 'utf8string']: - if calltype == 'element': - return '::nsstring::nsCString' - return prefix + '::nsstring::nsACString' - if self.specialtype in ['astring', 'domstring']: - if calltype == 'element': - return '::nsstring::nsString' - return prefix + '::nsstring::nsAString' - if self.nativename == 'void': - return prefix + 'libc::c_void' - - if self.specialtype: - raise RustNoncompat("specialtype %s unsupported" % self.specialtype) - raise RustNoncompat("native type %s unsupported" % self.nativename) + if self.isRef(calltype): + m = const and '&' or '&mut ' + elif self.isPtr(calltype): + m = (const and '*const ' or '*mut ') + if self.modifier == 'ptr' and calltype != 'in': + m += '*mut ' + else: + m = calltype != 'in' and '*mut ' or '' + return "%s%s" % (m, name) def __str__(self): return "native %s(%s)\n" % (self.name, self.nativename) @@ -614,11 +613,11 @@ class WebIDL(object): return True # All DOM objects are script exposed. def nativeType(self, calltype): - return "%s *%s" % (self.native, '*' if 'out' in calltype else '') + return "%s %s" % (self.native, calltype != 'in' and '* *' or '*') def rustType(self, calltype): # Just expose the type as a void* - we can't do any better. - return "%s*const libc::c_void" % ('*mut ' if 'out' in calltype else '') + return "%s*const libc::c_void" % (calltype != 'in' and '*mut ' or '') def __str__(self): return "webidl %s\n" % self.name @@ -714,11 +713,12 @@ class Interface(object): return True def nativeType(self, calltype, const=False): - return "%s%s *%s" % ('const ' if const else '', self.name, - '*' if 'out' in calltype else '') + return "%s%s %s" % (const and 'const ' or '', + self.name, + calltype != 'in' and '* *' or '*') - def rustType(self, calltype, const=False): - return "%s*const %s" % ('*mut ' if 'out' in calltype else '', + def rustType(self, calltype): + return "%s*const %s" % (calltype != 'in' and '*mut ' or '', self.name) def __str__(self): @@ -1219,19 +1219,12 @@ class Array(object): return self.type.isScriptable() def nativeType(self, calltype, const=False): - # For legacy reasons, we have to add a 'const ' to builtin pointer array - # types. (`[array] in string` and `[array] in wstring` parameters) - if calltype == 'in' and isinstance(self.type, Builtin) and self.type.isPointer(): - const = True - - return "%s%s*%s" % ('const ' if const else '', - self.type.nativeType('element'), - '*' if 'out' in calltype else '') + return "%s%s*" % (const and 'const ' or '', + self.type.nativeType(calltype)) def rustType(self, calltype, const=False): - return "%s%s%s" % ('*mut ' if 'out' in calltype else '', - '*const ' if const else '*mut ', - self.type.rustType('element')) + return "%s %s" % (const and '*const' or '*mut', + self.type.rustType(calltype)) class IDLParser(object): diff --git a/xpcom/rust/xpcom/src/reexports.rs b/xpcom/rust/xpcom/src/reexports.rs index 623e8a44580e..5673c0d6d5ef 100644 --- a/xpcom/rust/xpcom/src/reexports.rs +++ b/xpcom/rust/xpcom/src/reexports.rs @@ -11,7 +11,7 @@ // re-export libc so it can be used by the procedural macro. pub extern crate libc; -pub use nsstring::{nsACString, nsAString, nsCString, nsString}; +pub use nsstring::{nsACString, nsAString}; pub use nserror::{nsresult, NsresultExt, NS_ERROR_NO_INTERFACE, NS_OK}; diff --git a/xpcom/rust/xpcom/xpcom_macros/src/lib.rs b/xpcom/rust/xpcom/xpcom_macros/src/lib.rs index 260d4ca64b18..7b576b1ca568 100644 --- a/xpcom/rust/xpcom/xpcom_macros/src/lib.rs +++ b/xpcom/rust/xpcom/xpcom_macros/src/lib.rs @@ -563,9 +563,7 @@ fn xpcom(init: DeriveInput) -> Result> { #[allow(unused_imports)] use ::xpcom::interfaces::*; #[allow(unused_imports)] - use ::xpcom::reexports::{ - libc, nsACString, nsAString, nsCString, nsString, nsresult - }; + use ::xpcom::reexports::{libc, nsACString, nsAString, nsresult}; unsafe { // NOTE: This is split into multiple lines to make the diff --git a/xpcom/tests/gtest/TestTArray2.cpp b/xpcom/tests/gtest/TestTArray2.cpp index f20e207b0bbb..a228007acab5 100644 --- a/xpcom/tests/gtest/TestTArray2.cpp +++ b/xpcom/tests/gtest/TestTArray2.cpp @@ -382,25 +382,6 @@ TEST(TArray, test_move_array) { differentAllocatorMoveableArray2 = std::move(autoMoveableArray2); ASSERT_EQ(Moveable::Count(), 8); - - AutoTArray moveableAutoArray; - for (uint32_t i = 0; i < 4; ++i) { - ASSERT_TRUE(moveableAutoArray.AppendElement(Moveable())); - } - - ASSERT_EQ(Moveable::Count(), 12); - - const AutoTArray& constRefMoveableAutoArray = moveableAutoArray; - - ASSERT_EQ(Moveable::Count(), 12); - - AutoTArray copyMoveableAutoArray(constRefMoveableAutoArray); - - ASSERT_EQ(Moveable::Count(), 16); - - AutoTArray movedMoveableAutoArray(std::move(moveableAutoArray)); - - ASSERT_EQ(Moveable::Count(), 16); } //---- From 610a1f38df181155aa63f74897caf711cff09e39 Mon Sep 17 00:00:00 2001 From: sotaro Date: Sat, 7 Jul 2018 09:30:50 +0900 Subject: [PATCH 10/10] Bug 1473815 - Simplify WebRenderBridgeParent::mAnimStorage iteration code r=nical --- gfx/layers/wr/WebRenderBridgeParent.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index ea3cbfe56ed1..89c499b982f1 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -1155,8 +1155,8 @@ WebRenderBridgeParent::RecvClearCachedResources() // Schedule generate frame to clean up Pipeline ScheduleGenerateFrame(); // Remove animations. - for (std::unordered_set::iterator iter = mActiveAnimations.begin(); iter != mActiveAnimations.end(); iter++) { - mAnimStorage->ClearById(*iter); + for (const auto& id : mActiveAnimations) { + mAnimStorage->ClearById(id); } mActiveAnimations.clear(); std::queue().swap(mCompositorAnimationsToDelete); // clear queue @@ -1680,8 +1680,8 @@ WebRenderBridgeParent::ClearResources() mApi->SendTransaction(txn); - for (std::unordered_set::iterator iter = mActiveAnimations.begin(); iter != mActiveAnimations.end(); iter++) { - mAnimStorage->ClearById(*iter); + for (const auto& id : mActiveAnimations) { + mAnimStorage->ClearById(id); } mActiveAnimations.clear(); std::queue().swap(mCompositorAnimationsToDelete); // clear queue