diff --git a/dom/ipc/FilePickerParent.cpp b/dom/ipc/FilePickerParent.cpp index 1438e374fe..0271890758 100644 --- a/dom/ipc/FilePickerParent.cpp +++ b/dom/ipc/FilePickerParent.cpp @@ -286,6 +286,7 @@ FilePickerParent::RecvOpen(const int16_t& aSelectedType, } } + MOZ_ASSERT(!mCallback); mCallback = new FilePickerShownCallback(this); mFilePicker->Open(mCallback); diff --git a/dom/ipc/FilePickerParent.h b/dom/ipc/FilePickerParent.h index 332007a715..7ab2f7dab1 100644 --- a/dom/ipc/FilePickerParent.h +++ b/dom/ipc/FilePickerParent.h @@ -69,7 +69,7 @@ class FilePickerParent : public PFilePickerParent private: virtual ~FilePickerShownCallback() {} - FilePickerParent* mFilePickerParent; + RefPtr mFilePickerParent; }; private: @@ -78,7 +78,7 @@ class FilePickerParent : public PFilePickerParent // This runnable is used to do some I/O operation on a separate thread. class IORunnable : public Runnable { - FilePickerParent* mFilePickerParent; + RefPtr mFilePickerParent; nsTArray> mFiles; nsTArray mResults; nsCOMPtr mEventTarget; diff --git a/dom/notification/Notification.cpp b/dom/notification/Notification.cpp index 9a7c833794..5439a4fe59 100644 --- a/dom/notification/Notification.cpp +++ b/dom/notification/Notification.cpp @@ -1688,6 +1688,11 @@ Notification::GetPermissionInternal(nsISupports* aGlobal, ErrorResult& aRv) } nsCOMPtr principal = sop->GetPrincipal(); + if (!principal) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return NotificationPermission::Denied; + } + return GetPermissionInternal(principal, aRv); } diff --git a/gfx/gl/SharedSurfaceGL.cpp b/gfx/gl/SharedSurfaceGL.cpp index adb4429ae8..2639d64afa 100644 --- a/gfx/gl/SharedSurfaceGL.cpp +++ b/gfx/gl/SharedSurfaceGL.cpp @@ -94,7 +94,8 @@ SharedSurface_Basic::~SharedSurface_Basic() mGL->fDeleteFramebuffers(1, &mFB); if (mOwnsTex) - mGL->fDeleteTextures(1, &mTex); + if (mTex) + mGL->fDeleteTextures(1, &mTex); } diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index cb249c254c..462edfd91e 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -7754,10 +7754,23 @@ bool BytecodeEmitter::emitLeftAssociative(ListNode* node) { // Left-associative operator chain. - if (!emitTree(node->head())) - return false; JSOp op = node->getOp(); - ParseNode* nextExpr = node->head()->pn_next; + ParseNode* headExpr = node->head(); + if (op == JSOP_IN && headExpr->isKind(PNK_NAME) && headExpr->as().isPrivateName()) { + // {Goanna} The only way a "naked" private name can show up as the leftmost side of an in-chain + // is from an ergonomic brand check (`this.#x in ...` would be a PNK_DOT child node). + // Instead of going through the emitTree machinery, we pretend that this identifier + // reference is actually a string, which allows us to use the JSOP_IN interpreter routines. + // This erroneously doesn't call updateLineNumberNotes, but this is not a big issue: + // the begin pos is correct as we're on the start of the current tree, the end is on the + // same line anyway. + if (!emitAtomOp(headExpr->as().atom(), JSOP_STRING)) + return false; + } else { + if (!emitTree(headExpr)) + return false; + } + ParseNode* nextExpr = headExpr->pn_next; do { if (!emitTree(nextExpr)) return false; diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index e27b9f540a..d2c8bbc2df 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -965,6 +965,10 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return node->isKind(PNK_NAME); } + bool isPrivateName(Node node) { + return node->isKind(PNK_NAME) && node->as().isPrivateName(); + } + bool isArgumentsAnyParentheses(Node node, ExclusiveContext* cx) { return node->isKind(PNK_NAME) && node->as().atom() == cx->names().arguments; } diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index b1fcab0735..439a6d8937 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -953,6 +953,10 @@ class NameNode : public ParseNode JSAtom* atom() const { return pn_u.name.atom; } + + bool isPrivateName() const { + return atom()->asPropertyName()->latin1OrTwoByteChar(0) == '#'; + } ParseNode* initializer() const { return pn_u.name.initOrStmt; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 2f2d95cca8..7bbfdca926 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -8951,6 +8951,15 @@ Parser::orExpr1(InHandling inHandling, YieldHandling yieldHandling if (!tokenStream.getToken(&tok)) return null(); + // Ensure that if we have a private name lhs we are legally constructing a + // `#x in obj` expression: + if (handler.isPrivateName(pn)) { + if (tok != TOK_IN) { + error(JSMSG_ILLEGAL_PRIVATE_NAME); + return null(); + } + } + ParseNodeKind pnk; if (tok == TOK_IN ? inHandling == InAllowed : TokenKindIsBinaryOp(tok)) { // We're definitely not in a destructuring context, so report any @@ -8987,7 +8996,20 @@ Parser::orExpr1(InHandling inHandling, YieldHandling yieldHandling // If we have not detected a mixing error at this point, record that // we have an unparenthesized expression, in case we have one later. unparenthesizedExpression = EnforcedParentheses::CoalesceExpr; - break; + break; + case TOK_IN: + // if the LHS is a private name, and the operator is In, + // ensure we're construcing an ergonomic brand check of + // '#x in y', rather than having a higher precedence operator + // like + cause a different reduction, such as + // 1 + #x in y. + if (handler.isPrivateName(pn)) { + if (depth > 0 && Precedence(kindStack[depth - 1]) >= Precedence(PNK_IN)) { + error(JSMSG_ILLEGAL_PRIVATE_NAME); + return null(); + } + } + break; default: // Do nothing in other cases. break; diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index 818530cfe9..80ca13ce45 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -104,6 +104,9 @@ class SyntaxParseHandler // Node representing the "async" name, which may actually be a // contextual keyword. NodePotentialAsyncKeyword, + + // Node representing a private name. Handled mostly like NodeUnparenthesizedName. + NodePrivateName, // Valuable for recognizing potential destructuring patterns. NodeUnparenthesizedArray, @@ -212,6 +215,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return NodePotentialAsyncKeyword; if (name == cx->names().eval) return NodeUnparenthesizedEvalName; + if (name->length() >= 1 && name->latin1OrTwoByteChar(0) == '#') + return NodePrivateName; return NodeUnparenthesizedName; } @@ -614,7 +619,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return node == NodeUnparenthesizedArgumentsName || node == NodeUnparenthesizedEvalName || node == NodeUnparenthesizedName || - node == NodePotentialAsyncKeyword; + node == NodePotentialAsyncKeyword || + node == NodePrivateName; } bool isNameAnyParentheses(Node node) { @@ -625,6 +631,10 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) node == NodeParenthesizedName; } + bool isPrivateName(Node node) { + return node == NodePrivateName; + } + bool isArgumentsAnyParentheses(Node node, ExclusiveContext* cx) { return node == NodeUnparenthesizedArgumentsName || node == NodeParenthesizedArgumentsName; } diff --git a/js/src/js.msg b/js/src/js.msg index 1cb571d189..340cfd6ad2 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -364,6 +364,7 @@ MSG_DEF(JSMSG_BAD_NEW_OPTIONAL, 0, JSEXN_SYNTAXERR, "new keyword cannot b MSG_DEF(JSMSG_BAD_OPTIONAL_TEMPLATE, 0, JSEXN_SYNTAXERR, "tagged template cannot be used with optional chain") MSG_DEF(JSMSG_ESCAPED_KEYWORD, 0, JSEXN_SYNTAXERR, "keywords must be written literally, without embedded escapes") MSG_DEF(JSMSG_FIELDS_NOT_SUPPORTED, 0, JSEXN_SYNTAXERR, "fields are not currently supported") +MSG_DEF(JSMSG_ILLEGAL_PRIVATE_NAME, 0, JSEXN_SYNTAXERR, "private names aren't valid in this context") // asm.js MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL, 1, JSEXN_TYPEERR, "asm.js type error: {0}") diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index fa4cd1beb9..0694817515 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -373,7 +373,7 @@ CSS_PROP_DISPLAY( AnimationDelay, CSS_PROPERTY_PARSE_VALUE_LIST | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, - "", + "layout.css.animation.enabled", VARIANT_TIME, // used by list parsing nullptr, CSS_PROP_NO_OFFSET, @@ -384,7 +384,7 @@ CSS_PROP_DISPLAY( AnimationDirection, CSS_PROPERTY_PARSE_VALUE_LIST | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, - "", + "layout.css.animation.enabled", VARIANT_KEYWORD, // used by list parsing kAnimationDirectionKTable, CSS_PROP_NO_OFFSET, @@ -395,7 +395,7 @@ CSS_PROP_DISPLAY( AnimationDuration, CSS_PROPERTY_PARSE_VALUE_LIST | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, - "", + "layout.css.animation.enabled", VARIANT_TIME | VARIANT_NONNEGATIVE_DIMENSION, // used by list parsing nullptr, CSS_PROP_NO_OFFSET, @@ -406,7 +406,7 @@ CSS_PROP_DISPLAY( AnimationFillMode, CSS_PROPERTY_PARSE_VALUE_LIST | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, - "", + "layout.css.animation.enabled", VARIANT_KEYWORD, // used by list parsing kAnimationFillModeKTable, CSS_PROP_NO_OFFSET, @@ -420,7 +420,7 @@ CSS_PROP_DISPLAY( // http://lists.w3.org/Archives/Public/www-style/2011Mar/0355.html CSS_PROPERTY_VALUE_NONNEGATIVE | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, - "", + "layout.css.animation.enabled", VARIANT_KEYWORD | VARIANT_NUMBER, // used by list parsing kAnimationIterationCountKTable, CSS_PROP_NO_OFFSET, @@ -431,7 +431,7 @@ CSS_PROP_DISPLAY( AnimationName, CSS_PROPERTY_PARSE_VALUE_LIST | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, - "", + "layout.css.animation.enabled", // FIXME: The spec should say something about 'inherit' and 'initial' // not being allowed. VARIANT_NONE | VARIANT_IDENTIFIER_NO_INHERIT, // used by list parsing @@ -444,7 +444,7 @@ CSS_PROP_DISPLAY( AnimationPlayState, CSS_PROPERTY_PARSE_VALUE_LIST | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, - "", + "layout.css.animation.enabled", VARIANT_KEYWORD, // used by list parsing kAnimationPlayStateKTable, CSS_PROP_NO_OFFSET, @@ -455,7 +455,7 @@ CSS_PROP_DISPLAY( AnimationTimingFunction, CSS_PROPERTY_PARSE_VALUE_LIST | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, - "", + "layout.css.animation.enabled", VARIANT_KEYWORD | VARIANT_TIMING_FUNCTION, // used by list parsing kTransitionTimingFunctionKTable, CSS_PROP_NO_OFFSET, @@ -4284,7 +4284,7 @@ CSS_PROP_DISPLAY( TransitionDelay, CSS_PROPERTY_PARSE_VALUE_LIST | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, - "", + "layout.css.transition.enabled", VARIANT_TIME, // used by list parsing nullptr, CSS_PROP_NO_OFFSET, @@ -4295,7 +4295,7 @@ CSS_PROP_DISPLAY( TransitionDuration, CSS_PROPERTY_PARSE_VALUE_LIST | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, - "", + "layout.css.transition.enabled", VARIANT_TIME | VARIANT_NONNEGATIVE_DIMENSION, // used by list parsing nullptr, CSS_PROP_NO_OFFSET, @@ -4306,7 +4306,7 @@ CSS_PROP_DISPLAY( TransitionProperty, CSS_PROPERTY_PARSE_FUNCTION | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, - "", + "layout.css.transition.enabled", VARIANT_IDENTIFIER | VARIANT_NONE | VARIANT_ALL, // used only in shorthand nullptr, CSS_PROP_NO_OFFSET, @@ -4317,7 +4317,7 @@ CSS_PROP_DISPLAY( TransitionTimingFunction, CSS_PROPERTY_PARSE_VALUE_LIST | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, - "", + "layout.css.transition.enabled", VARIANT_KEYWORD | VARIANT_TIMING_FUNCTION, // used by list parsing kTransitionTimingFunctionKTable, CSS_PROP_NO_OFFSET, diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 742fde5568..6dd82c9bf5 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2486,6 +2486,12 @@ pref("layout.css.mix-blend-mode.enabled", true); // Is support for isolation enabled? pref("layout.css.isolation.enabled", true); +// Is support for CSS animation properties enabled? +pref("layout.css.animation.enabled", true); + +// Is support for CSS transition properties enabled? +pref("layout.css.transition.enabled", true); + // Is support for CSS Filters enabled? pref("layout.css.filters.enabled", true); diff --git a/netwerk/protocol/websocket/WebSocketChannel.cpp b/netwerk/protocol/websocket/WebSocketChannel.cpp index 058dc46417..9fca09a087 100644 --- a/netwerk/protocol/websocket/WebSocketChannel.cpp +++ b/netwerk/protocol/websocket/WebSocketChannel.cpp @@ -520,7 +520,7 @@ private: ~nsOpenConn() { MOZ_COUNT_DTOR(nsOpenConn); } nsCString mAddress; - WebSocketChannel *mChannel; + RefPtr mChannel; }; void ConnectNext(nsCString &hostName) @@ -1191,6 +1191,7 @@ WebSocketChannel::WebSocketChannel() : mBufferSize(kIncomingBufferInitialSize), mCurrentOut(nullptr), mCurrentOutSent(0), + mCompressorMutex("WebSocketChannel::mCompressorMutex"), mDynamicOutputSize(0), mDynamicOutput(nullptr), mPrivateBrowsing(false), @@ -1627,6 +1628,7 @@ WebSocketChannel::ProcessInput(uint8_t *buffer, uint32_t count) if (rsvBits) { // PMCE sets RSV1 bit in the first fragment when the non-control frame // is deflated + MutexAutoLock lock(mCompressorMutex); if (mPMCECompressor && rsvBits == kRsv1Bit && mFragmentAccumulator == 0 && !(opcode & kControlFrameMask)) { mPMCECompressor->SetMessageDeflated(); @@ -1700,25 +1702,28 @@ WebSocketChannel::ProcessInput(uint8_t *buffer, uint32_t count) LOG(("WebSocketChannel:: ignoring read frame code %d after completion\n", opcode)); } else if (opcode == nsIWebSocketFrame::OPCODE_TEXT) { - bool isDeflated = mPMCECompressor && mPMCECompressor->IsMessageDeflated(); - LOG(("WebSocketChannel:: %stext frame received\n", - isDeflated ? "deflated " : "")); - if (mListenerMT) { nsCString utf8Data; - if (isDeflated) { - rv = mPMCECompressor->Inflate(payload, payloadLength, utf8Data); - if (NS_FAILED(rv)) { - return rv; - } - LOG(("WebSocketChannel:: message successfully inflated " - "[origLength=%d, newLength=%d]\n", payloadLength, - utf8Data.Length())); - } else { - if (!utf8Data.Assign((const char *)payload, payloadLength, - mozilla::fallible)) { - return NS_ERROR_OUT_OF_MEMORY; + { // lockscope + MutexAutoLock lock(mCompressorMutex); + bool isDeflated = mPMCECompressor && mPMCECompressor->IsMessageDeflated(); + LOG(("WebSocketChannel:: %stext frame received\n", + isDeflated ? "deflated " : "")); + + if (isDeflated) { + rv = mPMCECompressor->Inflate(payload, payloadLength, utf8Data); + if (NS_FAILED(rv)) { + return rv; + } + LOG(("WebSocketChannel:: message successfully inflated " + "[origLength=%d, newLength=%d]\n", payloadLength, + utf8Data.Length())); + } else { + if (!utf8Data.Assign((const char *)payload, payloadLength, + mozilla::fallible)) { + return NS_ERROR_OUT_OF_MEMORY; + } } } @@ -1835,25 +1840,28 @@ WebSocketChannel::ProcessInput(uint8_t *buffer, uint32_t count) mService->FrameReceived(mSerial, mInnerWindowID, frame.forget()); } } else if (opcode == nsIWebSocketFrame::OPCODE_BINARY) { - bool isDeflated = mPMCECompressor && mPMCECompressor->IsMessageDeflated(); - LOG(("WebSocketChannel:: %sbinary frame received\n", - isDeflated ? "deflated " : "")); - if (mListenerMT) { nsCString binaryData; - if (isDeflated) { - rv = mPMCECompressor->Inflate(payload, payloadLength, binaryData); - if (NS_FAILED(rv)) { - return rv; - } - LOG(("WebSocketChannel:: message successfully inflated " - "[origLength=%d, newLength=%d]\n", payloadLength, - binaryData.Length())); - } else { - if (!binaryData.Assign((const char *)payload, payloadLength, - mozilla::fallible)) { - return NS_ERROR_OUT_OF_MEMORY; + { //lockscope + MutexAutoLock lock(mCompressorMutex); + bool isDeflated = mPMCECompressor && mPMCECompressor->IsMessageDeflated(); + LOG(("WebSocketChannel:: %sbinary frame received\n", + isDeflated ? "deflated " : "")); + + if (isDeflated) { + rv = mPMCECompressor->Inflate(payload, payloadLength, binaryData); + if (NS_FAILED(rv)) { + return rv; + } + LOG(("WebSocketChannel:: message successfully inflated " + "[origLength=%d, newLength=%d]\n", payloadLength, + binaryData.Length())); + } else { + if (!binaryData.Assign((const char *)payload, payloadLength, + mozilla::fallible)) { + return NS_ERROR_OUT_OF_MEMORY; + } } } @@ -2156,6 +2164,7 @@ WebSocketChannel::PrimeNewOutgoingMessage() } // deflate the payload if PMCE is negotiated + MutexAutoLock lock(mCompressorMutex); if (mPMCECompressor && (msgType == kMsgTypeString || msgType == kMsgTypeBinaryString)) { if (mCurrentOut->DeflatePayload(mPMCECompressor)) { @@ -2447,7 +2456,10 @@ WebSocketChannel::StopSession(nsresult reason) mCancelable = nullptr; } - mPMCECompressor = nullptr; + { + MutexAutoLock lock(mCompressorMutex); + mPMCECompressor = nullptr; + } if (!mCalledOnStop) { mCalledOnStop = 1; @@ -2702,6 +2714,7 @@ WebSocketChannel::HandleExtensions() serverMaxWindowBits = 15; } + MutexAutoLock lock(mCompressorMutex); mPMCECompressor = new PMCECompression(clientNoContextTakeover, clientMaxWindowBits, serverMaxWindowBits); @@ -3678,6 +3691,7 @@ WebSocketChannel::OnTransportAvailable(nsISocketTransport *aTransport, serverMaxWindowBits = 15; } + MutexAutoLock lock(mCompressorMutex); mPMCECompressor = new PMCECompression(serverNoContextTakeover, serverMaxWindowBits, clientMaxWindowBits); diff --git a/netwerk/protocol/websocket/WebSocketChannel.h b/netwerk/protocol/websocket/WebSocketChannel.h index bd75ca3a81..bd9717d529 100644 --- a/netwerk/protocol/websocket/WebSocketChannel.h +++ b/netwerk/protocol/websocket/WebSocketChannel.h @@ -18,6 +18,7 @@ #include "nsIChannelEventSink.h" #include "nsIHttpChannelInternal.h" #include "nsIStringStream.h" +#include "mozilla/Mutex.h" #include "BaseWebSocketChannel.h" #include "nsCOMPtr.h" @@ -288,6 +289,7 @@ private: uint32_t mHdrOutToSend; uint8_t *mHdrOut; uint8_t mOutHeader[kCopyBreak + 16]; + Mutex mCompressorMutex; nsAutoPtr mPMCECompressor; uint32_t mDynamicOutputSize; uint8_t *mDynamicOutput; diff --git a/python/mozbuild/mozbuild/backend/common.py b/python/mozbuild/mozbuild/backend/common.py index 12b2a27c45..2e8a161815 100644 --- a/python/mozbuild/mozbuild/backend/common.py +++ b/python/mozbuild/mozbuild/backend/common.py @@ -29,6 +29,7 @@ from mozbuild.frontend.data import ( FinalTargetFiles, GeneratedEventWebIDLFile, GeneratedWebIDLFile, + PreprocessedIPDLFile, PreprocessedTestWebIDLFile, PreprocessedWebIDLFile, SharedLibrary, @@ -215,6 +216,21 @@ class BinariesCollection(object): self.shared_libraries = [] self.programs = [] +class IPDLCollection(object): + """Collects IPDL files during the build.""" + + def __init__(self): + self.sources = set() + self.preprocessed_sources = set() + + def all_sources(self): + return self.sources | self.preprocessed_sources + + def all_regular_sources(self): + return self.sources + + def all_preprocessed_sources(self): + return self.preprocessed_sources class CommonBackend(BuildBackend): """Holds logic common to all build backends.""" @@ -225,7 +241,7 @@ class CommonBackend(BuildBackend): self._webidls = WebIDLCollection() self._binaries = BinariesCollection() self._configs = set() - self._ipdl_sources = set() + self._ipdls = IPDLCollection() def consume_object(self, obj): self._configs.add(obj.config) @@ -290,6 +306,10 @@ class CommonBackend(BuildBackend): self._webidls.generated_sources.add(mozpath.join(obj.srcdir, obj.basename)) + elif isinstance(obj, PreprocessedIPDLFile): + self._ipdls.preprocessed_sources.add(mozpath.join( + obj.srcdir, obj.basename)) + elif isinstance(obj, PreprocessedWebIDLFile): # WebIDL isn't relevant to artifact builds. if self.environment.is_artifact_build: @@ -310,7 +330,7 @@ class CommonBackend(BuildBackend): if self.environment.is_artifact_build: return True - self._ipdl_sources.add(mozpath.join(obj.srcdir, obj.basename)) + self._ipdls.sources.add(mozpath.join(obj.srcdir, obj.basename)) elif isinstance(obj, UnifiedSources): # Unified sources aren't relevant to artifact builds. @@ -341,7 +361,9 @@ class CommonBackend(BuildBackend): self._handle_webidl_collection(self._webidls) - sorted_ipdl_sources = list(sorted(self._ipdl_sources)) + sorted_ipdl_sources = list(sorted(self._ipdls.all_sources())) + sorted_nonstatic_ipdl_sources = list(sorted(self._ipdls.all_preprocessed_sources())) + sorted_static_ipdl_sources = list(sorted(self._ipdls.all_regular_sources())) def files_from(ipdl): base = mozpath.basename(ipdl) @@ -364,7 +386,8 @@ class CommonBackend(BuildBackend): files_per_unified_file=16)) self._write_unified_files(unified_source_mapping, ipdl_dir, poison_windows_h=False) - self._handle_ipdl_sources(ipdl_dir, sorted_ipdl_sources, unified_source_mapping) + self._handle_ipdl_sources(ipdl_dir, sorted_ipdl_sources, sorted_nonstatic_ipdl_sources, + sorted_static_ipdl_sources, unified_source_mapping) for config in self._configs: self.backend_input_files.add(config.source) diff --git a/python/mozbuild/mozbuild/backend/recursivemake.py b/python/mozbuild/mozbuild/backend/recursivemake.py index a314124f44..5621bc7e92 100644 --- a/python/mozbuild/mozbuild/backend/recursivemake.py +++ b/python/mozbuild/mozbuild/backend/recursivemake.py @@ -1407,18 +1407,32 @@ class RecursiveMakeBackend(CommonBackend): self._makefile_out_count += 1 - def _handle_ipdl_sources(self, ipdl_dir, sorted_ipdl_sources, - unified_ipdl_cppsrcs_mapping): + def _handle_ipdl_sources(self, ipdl_dir, sorted_ipdl_sources, sorted_nonstatic_ipdl_sources, + sorted_static_ipdl_sources, unified_ipdl_cppsrcs_mapping): # Write out a master list of all IPDL source files. mk = Makefile() - mk.add_statement('ALL_IPDLSRCS := %s' % ' '.join(sorted_ipdl_sources)) + sorted_nonstatic_ipdl_basenames = list() + for source in sorted_nonstatic_ipdl_sources: + basename = os.path.basename(source) + sorted_nonstatic_ipdl_basenames.append(basename) + rule = mk.create_rule([basename]) + rule.add_dependencies([source]) + rule.add_commands([ + '$(RM) $@', + '$(call py_action,preprocessor,$(DEFINES) $(ACDEFINES) ' + '$< -o $@)' + ]) + + mk.add_statement('ALL_IPDLSRCS := %s %s' % (' '.join(sorted_nonstatic_ipdl_basenames), + ' '.join(sorted_static_ipdl_sources))) self._add_unified_build_rules(mk, unified_ipdl_cppsrcs_mapping, unified_files_makefile_variable='CPPSRCS') - mk.add_statement('IPDLDIRS := %s' % ' '.join(sorted(set(mozpath.dirname(p) - for p in self._ipdl_sources)))) + # Preprocessed ipdl files are generated in ipdl_dir. + mk.add_statement('IPDLDIRS := %s %s' % (ipdl_dir, ' '.join(sorted(set(mozpath.dirname(p) + for p in sorted_static_ipdl_sources))))) with self._write_file(mozpath.join(ipdl_dir, 'ipdlsrcs.mk')) as ipdls: mk.dump(ipdls, removal_guard=False) diff --git a/python/mozbuild/mozbuild/backend/tup.py b/python/mozbuild/mozbuild/backend/tup.py index 0f7250eb01..b148532c89 100644 --- a/python/mozbuild/mozbuild/backend/tup.py +++ b/python/mozbuild/mozbuild/backend/tup.py @@ -298,8 +298,8 @@ class TupOnly(CommonBackend, PartialBackend): outputs=[output], ) - def _handle_ipdl_sources(self, ipdl_dir, sorted_ipdl_sources, - unified_ipdl_cppsrcs_mapping): + def _handle_ipdl_sources(self, ipdl_dir, sorted_ipdl_sources, sorted_nonstatic_ipdl_sources, + sorted_static_ipdl_sources, unified_ipdl_cppsrcs_mapping): # TODO: This isn't implemented yet in the tup backend, but it is called # by the CommonBackend. pass diff --git a/python/mozbuild/mozbuild/compilation/database.py b/python/mozbuild/mozbuild/compilation/database.py index 4193e1bcf4..20b09df488 100644 --- a/python/mozbuild/mozbuild/compilation/database.py +++ b/python/mozbuild/mozbuild/compilation/database.py @@ -177,8 +177,8 @@ class CompileDBBackend(CommonBackend): def _handle_idl_manager(self, idl_manager): pass - def _handle_ipdl_sources(self, ipdl_dir, sorted_ipdl_sources, - unified_ipdl_cppsrcs_mapping): + def _handle_ipdl_sources(self, ipdl_dir, sorted_ipdl_sources, sorted_nonstatic_ipdl_sources, + sorted_static_ipdl_sources, unified_ipdl_cppsrcs_mapping): for f in unified_ipdl_cppsrcs_mapping: self._build_db_line(ipdl_dir, None, self.environment, f[0], '.cpp') diff --git a/python/mozbuild/mozbuild/frontend/context.py b/python/mozbuild/mozbuild/frontend/context.py index eb501dc666..ef9406ea5b 100644 --- a/python/mozbuild/mozbuild/frontend/context.py +++ b/python/mozbuild/mozbuild/frontend/context.py @@ -1441,6 +1441,13 @@ VARIABLES = { not use this flag. """), + 'PREPROCESSED_IPDL_SOURCES': (StrictOrderingOnAppendList, list, + """Preprocessed IPDL source files. + + These files will be preprocessed, then parsed and converted to + ``.cpp`` files. + """), + 'IPDL_SOURCES': (StrictOrderingOnAppendList, list, """IPDL source files. diff --git a/python/mozbuild/mozbuild/frontend/data.py b/python/mozbuild/mozbuild/frontend/data.py index fb0bf2405c..759469d233 100644 --- a/python/mozbuild/mozbuild/frontend/data.py +++ b/python/mozbuild/mozbuild/frontend/data.py @@ -218,6 +218,18 @@ class IPDLFile(ContextDerived): self.basename = path +class PreprocessedIPDLFile(ContextDerived): + """Describes an individual .ipdl source file that requires preprocessing.""" + + __slots__ = ( + 'basename', + ) + + def __init__(self, context, path): + ContextDerived.__init__(self, context) + + self.basename = path + class WebIDLFile(ContextDerived): """Describes an individual .webidl source file.""" diff --git a/python/mozbuild/mozbuild/frontend/emitter.py b/python/mozbuild/mozbuild/frontend/emitter.py index 25c5826626..6220cd4b4b 100644 --- a/python/mozbuild/mozbuild/frontend/emitter.py +++ b/python/mozbuild/mozbuild/frontend/emitter.py @@ -58,6 +58,7 @@ from .data import ( ObjdirFiles, ObjdirPreprocessedFiles, PerSourceFlag, + PreprocessedIPDLFile, PreprocessedTestWebIDLFile, PreprocessedWebIDLFile, Program, @@ -872,6 +873,7 @@ class TreeMetadataEmitter(LoggingMixin): ('GENERATED_EVENTS_WEBIDL_FILES', GeneratedEventWebIDLFile), ('GENERATED_WEBIDL_FILES', GeneratedWebIDLFile), ('IPDL_SOURCES', IPDLFile), + ('PREPROCESSED_IPDL_SOURCES', PreprocessedIPDLFile), ('PREPROCESSED_TEST_WEBIDL_FILES', PreprocessedTestWebIDLFile), ('PREPROCESSED_WEBIDL_FILES', PreprocessedWebIDLFile), ('TEST_WEBIDL_FILES', TestWebIDLFile), diff --git a/python/mozbuild/mozbuild/test/backend/data/ipdl_sources/bar/moz.build b/python/mozbuild/mozbuild/test/backend/data/ipdl_sources/bar/moz.build index eb37725230..126854c383 100644 --- a/python/mozbuild/mozbuild/test/backend/data/ipdl_sources/bar/moz.build +++ b/python/mozbuild/mozbuild/test/backend/data/ipdl_sources/bar/moz.build @@ -3,6 +3,10 @@ # 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/. +PREPROCESSED_IPDL_SOURCES += [ + 'bar1.ipdl', +] + IPDL_SOURCES += [ 'bar.ipdl', 'bar2.ipdlh', diff --git a/python/mozbuild/mozbuild/test/backend/data/ipdl_sources/foo/moz.build b/python/mozbuild/mozbuild/test/backend/data/ipdl_sources/foo/moz.build index 84d40ac1d3..4047c31216 100644 --- a/python/mozbuild/mozbuild/test/backend/data/ipdl_sources/foo/moz.build +++ b/python/mozbuild/mozbuild/test/backend/data/ipdl_sources/foo/moz.build @@ -3,6 +3,10 @@ # 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/. +PREPROCESSED_IPDL_SOURCES += [ + 'foo1.ipdl', +] + IPDL_SOURCES += [ 'foo.ipdl', 'foo2.ipdlh', diff --git a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py index 87f50f4973..a592ab55a3 100644 --- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py +++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py @@ -656,7 +656,7 @@ class TestRecursiveMakeBackend(BackendTester): self.assertEqual(m, m2) def test_ipdl_sources(self): - """Test that IPDL_SOURCES are written to ipdlsrcs.mk correctly.""" + """Test that PREPROCESSED_IPDL_SOURCES and IPDL_SOURCES are written to ipdlsrcs.mk correctly.""" env = self._consume('ipdl_sources', RecursiveMakeBackend) manifest_path = mozpath.join(env.topobjdir, @@ -667,9 +667,9 @@ class TestRecursiveMakeBackend(BackendTester): topsrcdir = env.topsrcdir.replace(os.sep, '/') expected = [ - "ALL_IPDLSRCS := %s/bar/bar.ipdl %s/bar/bar2.ipdlh %s/foo/foo.ipdl %s/foo/foo2.ipdlh" % tuple([topsrcdir] * 4), + "ALL_IPDLSRCS := bar1.ipdl foo1.ipdl %s/bar/bar.ipdl %s/bar/bar2.ipdlh %s/foo/foo.ipdl %s/foo/foo2.ipdlh" % tuple([topsrcdir] * 4), "CPPSRCS := UnifiedProtocols0.cpp", - "IPDLDIRS := %s/bar %s/foo" % (topsrcdir, topsrcdir), + "IPDLDIRS := %s/ipc/ipdl %s/bar %s/foo" % (env.topobjdir, topsrcdir, topsrcdir), ] found = [str for str in lines if str.startswith(('ALL_IPDLSRCS', diff --git a/python/mozbuild/mozbuild/test/frontend/data/ipdl_sources/bar/moz.build b/python/mozbuild/mozbuild/test/frontend/data/ipdl_sources/bar/moz.build index eb37725230..126854c383 100644 --- a/python/mozbuild/mozbuild/test/frontend/data/ipdl_sources/bar/moz.build +++ b/python/mozbuild/mozbuild/test/frontend/data/ipdl_sources/bar/moz.build @@ -3,6 +3,10 @@ # 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/. +PREPROCESSED_IPDL_SOURCES += [ + 'bar1.ipdl', +] + IPDL_SOURCES += [ 'bar.ipdl', 'bar2.ipdlh', diff --git a/python/mozbuild/mozbuild/test/frontend/data/ipdl_sources/foo/moz.build b/python/mozbuild/mozbuild/test/frontend/data/ipdl_sources/foo/moz.build index 84d40ac1d3..4047c31216 100644 --- a/python/mozbuild/mozbuild/test/frontend/data/ipdl_sources/foo/moz.build +++ b/python/mozbuild/mozbuild/test/frontend/data/ipdl_sources/foo/moz.build @@ -3,6 +3,10 @@ # 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/. +PREPROCESSED_IPDL_SOURCES += [ + 'foo1.ipdl', +] + IPDL_SOURCES += [ 'foo.ipdl', 'foo2.ipdlh', diff --git a/python/mozbuild/mozbuild/test/frontend/test_emitter.py b/python/mozbuild/mozbuild/test/frontend/test_emitter.py index 191727381d..e1e3fa5ce2 100644 --- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py +++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py @@ -30,6 +30,7 @@ from mozbuild.frontend.data import ( JARManifest, LinkageMultipleRustLibrariesError, LocalInclude, + PreprocessedIPDLFile, Program, SdkFiles, SharedLibrary, @@ -688,9 +689,12 @@ class TestEmitterBasic(unittest.TestCase): objs = self.read_topsrcdir(reader) ipdls = [] + nonstatic_ipdls = [] for o in objs: if isinstance(o, IPDLFile): ipdls.append('%s/%s' % (o.relativedir, o.basename)) + elif isinstance(o, PreprocessedIPDLFile): + nonstatic_ipdls.append('%s/%s' % (o.relativedir, o.basename)) expected = [ 'bar/bar.ipdl', @@ -699,7 +703,12 @@ class TestEmitterBasic(unittest.TestCase): 'foo/foo2.ipdlh', ] - self.assertEqual(ipdls, expected) + expected = [ + 'bar/bar1.ipdl', + 'foo/foo1.ipdl', + ] + + self.assertEqual(nonstatic_ipdls, expected) def test_local_includes(self): """Test that LOCAL_INCLUDES is emitted correctly.""" diff --git a/xpcom/io/nsLocalFileWin.cpp b/xpcom/io/nsLocalFileWin.cpp index 5182b71f6f..5210885dd9 100644 --- a/xpcom/io/nsLocalFileWin.cpp +++ b/xpcom/io/nsLocalFileWin.cpp @@ -3090,7 +3090,8 @@ nsLocalFile::IsExecutable(bool* aResult) "ws", "wsc", "wsf", - "wsh" + "wsh", + "xll" // MS Excel dynamic link library }; nsDependentSubstring ext = Substring(path, dotIdx + 1); for (size_t i = 0; i < ArrayLength(executableExts); ++i) {