From owner-svn-ports-head@freebsd.org Thu May 24 00:53:48 2018 Return-Path: Delivered-To: svn-ports-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 5B3BFEEF3CD; Thu, 24 May 2018 00:53:48 +0000 (UTC) (envelope-from jbeich@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 0EC456803D; Thu, 24 May 2018 00:53:48 +0000 (UTC) (envelope-from jbeich@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id E3AF927F7; Thu, 24 May 2018 00:53:47 +0000 (UTC) (envelope-from jbeich@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w4O0rlFs093325; Thu, 24 May 2018 00:53:47 GMT (envelope-from jbeich@FreeBSD.org) Received: (from jbeich@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w4O0rlED093319; Thu, 24 May 2018 00:53:47 GMT (envelope-from jbeich@FreeBSD.org) Message-Id: <201805240053.w4O0rlED093319@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jbeich set sender to jbeich@FreeBSD.org using -f From: Jan Beich Date: Thu, 24 May 2018 00:53:47 +0000 (UTC) To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r470749 - in head/www/waterfox: . files X-SVN-Group: ports-head X-SVN-Commit-Author: jbeich X-SVN-Commit-Paths: in head/www/waterfox: . files X-SVN-Commit-Revision: 470749 X-SVN-Commit-Repository: ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-ports-head@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: SVN commit messages for the ports tree for head List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 May 2018 00:53:48 -0000 Author: jbeich Date: Thu May 24 00:53:46 2018 New Revision: 470749 URL: https://svnweb.freebsd.org/changeset/ports/470749 Log: www/waterfox: apply some FF61 fixes Added: head/www/waterfox/files/patch-bug1412882 (contents, props changed) head/www/waterfox/files/patch-bug1454285 (contents, props changed) head/www/waterfox/files/patch-bug1456189 (contents, props changed) head/www/waterfox/files/patch-bug1456512 (contents, props changed) head/www/waterfox/files/patch-bug1462912 (contents, props changed) Modified: head/www/waterfox/Makefile (contents, props changed) Modified: head/www/waterfox/Makefile ============================================================================== --- head/www/waterfox/Makefile Thu May 24 00:53:30 2018 (r470748) +++ head/www/waterfox/Makefile Thu May 24 00:53:46 2018 (r470749) @@ -3,7 +3,7 @@ PORTNAME= waterfox DISTVERSION= 56.2.0-13 DISTVERSIONSUFFIX= -gd2cdd42f4115b -PORTREVISION= 3 +PORTREVISION= 4 CATEGORIES= www ipv6 MAINTAINER= jbeich@FreeBSD.org Added: head/www/waterfox/files/patch-bug1412882 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/waterfox/files/patch-bug1412882 Thu May 24 00:53:46 2018 (r470749) @@ -0,0 +1,192 @@ +commit 7513891383a1 +Author: Jonathan Kew +Date: Sat May 19 08:32:22 2018 +0100 + + Bug 1412882 - Rework gfxFontUtils::MapCharToGlyphFormat4 to be more robust. r=lsalzman, a=RyanVM + + --HG-- + extra : source : e96eaa6603005c3e2361d9d32ef59adb718d4203 +--- + gfx/thebes/gfxFontUtils.cpp | 89 ++++++++++++++++++++++------------------ + gfx/thebes/gfxFontUtils.h | 2 +- + gfx/thebes/gfxHarfBuzzShaper.cpp | 8 +++- + 3 files changed, 57 insertions(+), 42 deletions(-) + +diff --git gfx/thebes/gfxFontUtils.cpp gfx/thebes/gfxFontUtils.cpp +index b3c1cae1bbb67..1590fb52ab6b7 100644 +--- gfx/thebes/gfxFontUtils.cpp ++++ gfx/thebes/gfxFontUtils.cpp +@@ -569,55 +569,64 @@ typedef struct { + #pragma pack() + + uint32_t +-gfxFontUtils::MapCharToGlyphFormat4(const uint8_t *aBuf, char16_t aCh) ++gfxFontUtils::MapCharToGlyphFormat4(const uint8_t* aBuf, uint32_t aLength, ++ char16_t aCh) + { + const Format4Cmap *cmap4 = reinterpret_cast(aBuf); +- uint16_t segCount; +- const AutoSwap_PRUint16 *endCodes; +- const AutoSwap_PRUint16 *startCodes; +- const AutoSwap_PRUint16 *idDelta; +- const AutoSwap_PRUint16 *idRangeOffset; +- uint16_t probe; +- uint16_t rangeShiftOver2; +- uint16_t index; +- +- segCount = (uint16_t)(cmap4->segCountX2) / 2; +- +- endCodes = &cmap4->arrays[0]; +- startCodes = &cmap4->arrays[segCount + 1]; // +1 for reserved word between arrays +- idDelta = &startCodes[segCount]; +- idRangeOffset = &idDelta[segCount]; +- +- probe = 1 << (uint16_t)(cmap4->entrySelector); +- rangeShiftOver2 = (uint16_t)(cmap4->rangeShift) / 2; +- +- if ((uint16_t)(startCodes[rangeShiftOver2]) <= aCh) { +- index = rangeShiftOver2; +- } else { +- index = 0; +- } +- +- while (probe > 1) { +- probe >>= 1; +- if ((uint16_t)(startCodes[index + probe]) <= aCh) { +- index += probe; ++ ++ uint16_t segCount = (uint16_t)(cmap4->segCountX2) / 2; ++ ++ const AutoSwap_PRUint16* endCodes = &cmap4->arrays[0]; ++ const AutoSwap_PRUint16* startCodes = &cmap4->arrays[segCount + 1]; ++ const AutoSwap_PRUint16* idDelta = &startCodes[segCount]; ++ const AutoSwap_PRUint16* idRangeOffset = &idDelta[segCount]; ++ ++ // Sanity-check that the fixed-size arrays don't exceed the buffer. ++ const uint8_t* const limit = aBuf + aLength; ++ if ((const uint8_t*)(&idRangeOffset[segCount]) > limit) { ++ return 0; // broken font, just bail out safely ++ } ++ ++ // For most efficient binary search, we want to work on a range of segment ++ // indexes that is a power of 2 so that we can always halve it by shifting. ++ // So we find the largest power of 2 that is <= segCount. ++ // We will offset this range by segOffset so as to reach the end ++ // of the table, provided that doesn't put us beyond the target ++ // value from the outset. ++ uint32_t powerOf2 = mozilla::FindHighestBit(segCount); ++ uint32_t segOffset = segCount - powerOf2; ++ uint32_t idx = 0; ++ ++ if (uint16_t(startCodes[segOffset]) <= aCh) { ++ idx = segOffset; ++ } ++ ++ // Repeatedly halve the size of the range until we find the target group ++ while (powerOf2 > 1) { ++ powerOf2 >>= 1; ++ if (uint16_t(startCodes[idx + powerOf2]) <= aCh) { ++ idx += powerOf2; + } + } + +- if (aCh >= (uint16_t)(startCodes[index]) && aCh <= (uint16_t)(endCodes[index])) { ++ if (aCh >= uint16_t(startCodes[idx]) && aCh <= uint16_t(endCodes[idx])) { + uint16_t result; +- if ((uint16_t)(idRangeOffset[index]) == 0) { ++ if (uint16_t(idRangeOffset[idx]) == 0) { + result = aCh; + } else { +- uint16_t offset = aCh - (uint16_t)(startCodes[index]); +- const AutoSwap_PRUint16 *glyphIndexTable = +- (const AutoSwap_PRUint16*)((const char*)&idRangeOffset[index] + +- (uint16_t)(idRangeOffset[index])); ++ uint16_t offset = aCh - uint16_t(startCodes[idx]); ++ const AutoSwap_PRUint16* glyphIndexTable = ++ (const AutoSwap_PRUint16*)((const char*)&idRangeOffset[idx] + ++ uint16_t(idRangeOffset[idx])); ++ if ((const uint8_t*)(glyphIndexTable + offset + 1) > limit) { ++ return 0; // broken font, just bail out safely ++ } + result = glyphIndexTable[offset]; + } + +- // note that this is unsigned 16-bit arithmetic, and may wrap around +- result += (uint16_t)(idDelta[index]); ++ // Note that this is unsigned 16-bit arithmetic, and may wrap around ++ // (which is required behavior per spec) ++ result += uint16_t(idDelta[idx]); + return result; + } + +@@ -761,7 +770,8 @@ gfxFontUtils::MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength, + switch (format) { + case 4: + gid = aUnicode < UNICODE_BMP_LIMIT ? +- MapCharToGlyphFormat4(aCmapBuf + offset, char16_t(aUnicode)) : 0; ++ MapCharToGlyphFormat4(aCmapBuf + offset, aBufLength - offset, ++ char16_t(aUnicode)) : 0; + break; + case 10: + gid = MapCharToGlyphFormat10(aCmapBuf + offset, aUnicode); +@@ -786,6 +796,7 @@ gfxFontUtils::MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength, + case 4: + if (aUnicode < UNICODE_BMP_LIMIT) { + varGID = MapCharToGlyphFormat4(aCmapBuf + offset, ++ aBufLength - offset, + char16_t(aUnicode)); + } + break; +diff --git gfx/thebes/gfxFontUtils.h gfx/thebes/gfxFontUtils.h +index 250df442c3a2e..be2f54a9a7026 100644 +--- gfx/thebes/gfxFontUtils.h ++++ gfx/thebes/gfxFontUtils.h +@@ -804,7 +804,7 @@ public: + uint32_t& aUVSOffset); + + static uint32_t +- MapCharToGlyphFormat4(const uint8_t *aBuf, char16_t aCh); ++ MapCharToGlyphFormat4(const uint8_t *aBuf, uint32_t aLength, char16_t aCh); + + static uint32_t + MapCharToGlyphFormat10(const uint8_t *aBuf, uint32_t aCh); +diff --git gfx/thebes/gfxHarfBuzzShaper.cpp gfx/thebes/gfxHarfBuzzShaper.cpp +index c57504a4d9db4..ff638dcef73ad 100644 +--- gfx/thebes/gfxHarfBuzzShaper.cpp ++++ gfx/thebes/gfxHarfBuzzShaper.cpp +@@ -116,13 +116,15 @@ gfxHarfBuzzShaper::GetNominalGlyph(hb_codepoint_t unicode) const + NS_ASSERTION(mCmapTable && (mCmapFormat > 0) && (mSubtableOffset > 0), + "cmap data not correctly set up, expect disaster"); + ++ uint32_t length; + const uint8_t* data = +- (const uint8_t*)hb_blob_get_data(mCmapTable, nullptr); ++ (const uint8_t*)hb_blob_get_data(mCmapTable, &length); + + switch (mCmapFormat) { + case 4: + gid = unicode < UNICODE_BMP_LIMIT ? + gfxFontUtils::MapCharToGlyphFormat4(data + mSubtableOffset, ++ length - mSubtableOffset, + unicode) : 0; + break; + case 10: +@@ -164,8 +166,9 @@ gfxHarfBuzzShaper::GetVariationGlyph(hb_codepoint_t unicode, + NS_ASSERTION(mCmapTable && (mCmapFormat > 0) && (mSubtableOffset > 0), + "cmap data not correctly set up, expect disaster"); + ++ uint32_t length; + const uint8_t* data = +- (const uint8_t*)hb_blob_get_data(mCmapTable, nullptr); ++ (const uint8_t*)hb_blob_get_data(mCmapTable, &length); + + if (mUVSTableOffset) { + hb_codepoint_t gid = +@@ -183,6 +186,7 @@ gfxHarfBuzzShaper::GetVariationGlyph(hb_codepoint_t unicode, + case 4: + if (compat < UNICODE_BMP_LIMIT) { + return gfxFontUtils::MapCharToGlyphFormat4(data + mSubtableOffset, ++ length - mSubtableOffset, + compat); + } + break; Added: head/www/waterfox/files/patch-bug1454285 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/waterfox/files/patch-bug1454285 Thu May 24 00:53:46 2018 (r470749) @@ -0,0 +1,713 @@ +commit 58db23895d95 +Author: Tooru Fujisawa +Date: Tue May 22 18:10:28 2018 +0900 + + Bug 1454285 - Part 1: Specify the current scope when emitting await and .generator. r=jwalden, a=RyanVM + + --HG-- + extra : source : 6ca6ced5189a5760c96afa31a6575cd3d3f56639 +--- + js/src/frontend/BytecodeEmitter.cpp | 104 +++++++++++++++++++++--------------- + js/src/frontend/BytecodeEmitter.h | 25 ++++++--- + 2 files changed, 81 insertions(+), 48 deletions(-) + +diff --git js/src/frontend/BytecodeEmitter.cpp js/src/frontend/BytecodeEmitter.cpp +index df999dfb2b0dc..e8edc66658804 100644 +--- js/src/frontend/BytecodeEmitter.cpp ++++ js/src/frontend/BytecodeEmitter.cpp +@@ -2004,6 +2004,8 @@ class MOZ_STACK_CLASS IfThenElseEmitter + + class ForOfLoopControl : public LoopControl + { ++ using EmitterScope = BytecodeEmitter::EmitterScope; ++ + // The stack depth of the iterator. + int32_t iterDepth_; + +@@ -2096,8 +2098,8 @@ class ForOfLoopControl : public LoopControl + MOZ_ASSERT(slotFromTop == unsigned(bce->stackDepth - iterDepth_)); + if (!bce->emitDupAt(slotFromTop)) // ITER ... EXCEPTION ITER + return false; +- if (!emitIteratorClose(bce, CompletionKind::Throw)) // ITER ... EXCEPTION +- return false; ++ if (!emitIteratorCloseInInnermostScope(bce, CompletionKind::Throw)) ++ return false; // ITER ... EXCEPTION + + if (!ifIteratorIsNotClosed.emitEnd()) // ITER ... EXCEPTION + return false; +@@ -2120,8 +2122,8 @@ class ForOfLoopControl : public LoopControl + return false; + if (!bce->emitDupAt(slotFromTop + 1)) // ITER ... FTYPE FVALUE ITER + return false; +- if (!emitIteratorClose(bce, CompletionKind::Normal)) // ITER ... FTYPE FVALUE +- return false; ++ if (!emitIteratorCloseInInnermostScope(bce, CompletionKind::Normal)) ++ return false; // ITER ... FTYPE FVALUE + if (!ifGeneratorClosing.emitEnd()) // ITER ... FTYPE FVALUE + return false; + } +@@ -2135,16 +2137,27 @@ class ForOfLoopControl : public LoopControl + return true; + } + +- bool emitIteratorClose(BytecodeEmitter* bce, +- CompletionKind completionKind = CompletionKind::Normal) { ++ bool emitIteratorCloseInInnermostScope(BytecodeEmitter* bce, ++ CompletionKind completionKind = CompletionKind::Normal) { ++ return emitIteratorCloseInScope(bce, *bce->innermostEmitterScope, completionKind); ++ } ++ ++ bool emitIteratorCloseInScope(BytecodeEmitter* bce, ++ EmitterScope& currentScope, ++ CompletionKind completionKind = CompletionKind::Normal) { + ptrdiff_t start = bce->offset(); +- if (!bce->emitIteratorClose(iterKind_, completionKind, allowSelfHosted_)) ++ if (!bce->emitIteratorCloseInScope(currentScope, iterKind_, completionKind, ++ allowSelfHosted_)) ++ { + return false; ++ } + ptrdiff_t end = bce->offset(); + return bce->tryNoteList.append(JSTRY_FOR_OF_ITERCLOSE, 0, start, end); + } + +- bool emitPrepareForNonLocalJump(BytecodeEmitter* bce, bool isTarget) { ++ bool emitPrepareForNonLocalJumpFromScope(BytecodeEmitter* bce, ++ EmitterScope& currentScope, ++ bool isTarget) { + // Pop unnecessary value from the stack. Effectively this means + // leaving try-catch block. However, the performing IteratorClose can + // reach the depth for try-catch, and effectively re-enter the +@@ -2159,7 +2172,7 @@ class ForOfLoopControl : public LoopControl + if (!bce->emit1(JSOP_SWAP)) // UNDEF ITER + return false; + +- if (!emitIteratorClose(bce)) // UNDEF ++ if (!emitIteratorCloseInScope(bce, currentScope, CompletionKind::Normal)) // UNDEF + return false; + + if (isTarget) { +@@ -2843,8 +2856,11 @@ NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* ta + return false; + + ForOfLoopControl& loopinfo = control->as(); +- if (!loopinfo.emitPrepareForNonLocalJump(bce_, /* isTarget = */ false)) // ... ++ if (!loopinfo.emitPrepareForNonLocalJumpFromScope(bce_, *es, ++ /* isTarget = */ false)) ++ { // ... + return false; ++ } + } else { + npops += 2; + } +@@ -2871,8 +2887,9 @@ NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* ta + + if (target && emitIteratorCloseAtTarget && target->is()) { + ForOfLoopControl& loopinfo = target->as(); +- if (!loopinfo.emitPrepareForNonLocalJump(bce_, /* isTarget = */ true)) // ... UNDEF UNDEF ++ if (!loopinfo.emitPrepareForNonLocalJumpFromScope(bce_, *es, /* isTarget = */ true)) { // ... UNDEF UNDEF + return false; ++ } + } + + EmitterScope* targetEmitterScope = target ? target->emitterScope() : bce_->varEmitterScope; +@@ -5325,7 +5342,7 @@ BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = Iter + return false; + + if (iterKind == IteratorKind::Async) { +- if (!emitAwait()) // ... RESULT ++ if (!emitAwaitInInnermostScope()) // ... RESULT + return false; + } + +@@ -5336,9 +5353,10 @@ BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = Iter + } + + bool +-BytecodeEmitter::emitIteratorClose(IteratorKind iterKind /* = IteratorKind::Sync */, +- CompletionKind completionKind /* = CompletionKind::Normal */, +- bool allowSelfHosted /* = false */) ++BytecodeEmitter::emitIteratorCloseInScope(EmitterScope& currentScope, ++ IteratorKind iterKind /* = IteratorKind::Sync */, ++ CompletionKind completionKind /* = CompletionKind::Normal */, ++ bool allowSelfHosted /* = false */) + { + MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting, + ".close() on iterators is prohibited in self-hosted code because it " +@@ -5430,7 +5448,7 @@ BytecodeEmitter::emitIteratorClose(IteratorKind iterKind /* = IteratorKind::Sync + if (!emit1(JSOP_SWAP)) // ... ... RVAL RESULT + return false; + } +- if (!emitAwait()) // ... ... RVAL? RESULT ++ if (!emitAwaitInScope(currentScope)) // ... ... RVAL? RESULT + return false; + } + +@@ -5690,7 +5708,7 @@ BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlav + // For an empty pattern [], call IteratorClose unconditionally. Nothing + // else needs to be done. + if (!pattern->pn_head) +- return emitIteratorClose(); // ... OBJ ++ return emitIteratorCloseInInnermostScope(); // ... OBJ + + // Push an initial FALSE value for DONE. + if (!emit1(JSOP_FALSE)) // ... OBJ ITER FALSE +@@ -5886,7 +5904,7 @@ BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlav + return false; + if (!ifDone.emitElse()) // ... OBJ ITER + return false; +- if (!emitIteratorClose()) // ... OBJ ++ if (!emitIteratorCloseInInnermostScope()) // ... OBJ + return false; + if (!ifDone.emitEnd()) + return false; +@@ -8682,9 +8700,9 @@ BytecodeEmitter::emitReturn(ParseNode* pn) + } + + bool +-BytecodeEmitter::emitGetDotGenerator() ++BytecodeEmitter::emitGetDotGeneratorInScope(EmitterScope& currentScope) + { +- NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator); ++ NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator, ¤tScope); + return emitGetNameAtLocation(cx->names().dotGenerator, loc); + } + +@@ -8726,7 +8744,7 @@ BytecodeEmitter::emitYield(ParseNode* pn) + return false; + } + +- if (!emitGetDotGenerator()) ++ if (!emitGetDotGeneratorInInnermostScope()) + return false; + + if (!emitYieldOp(JSOP_YIELD)) +@@ -8736,24 +8754,24 @@ BytecodeEmitter::emitYield(ParseNode* pn) + } + + bool +-BytecodeEmitter::emitAwait() ++BytecodeEmitter::emitAwaitInInnermostScope(ParseNode* pn) + { +- if (!emitGetDotGenerator()) +- return false; +- if (!emitYieldOp(JSOP_AWAIT)) ++ MOZ_ASSERT(sc->isFunctionBox()); ++ MOZ_ASSERT(pn->getOp() == JSOP_AWAIT); ++ ++ if (!emitTree(pn->pn_kid)) + return false; +- return true; ++ return emitAwaitInInnermostScope(); + } + + bool +-BytecodeEmitter::emitAwait(ParseNode* pn) ++BytecodeEmitter::emitAwaitInScope(EmitterScope& currentScope) + { +- MOZ_ASSERT(sc->isFunctionBox()); +- MOZ_ASSERT(pn->getOp() == JSOP_AWAIT); +- +- if (!emitTree(pn->pn_kid)) ++ if (!emitGetDotGeneratorInScope(currentScope)) + return false; +- return emitAwait(); ++ if (!emitYieldOp(JSOP_AWAIT)) ++ return false; ++ return true; + } + + bool +@@ -8794,7 +8812,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + MOZ_ASSERT(this->stackDepth == startDepth); + + // Load the generator object. +- if (!emitGetDotGenerator()) // ITER RESULT GENOBJ ++ if (!emitGetDotGeneratorInInnermostScope()) // ITER RESULT GENOBJ + return false; + + // Yield RESULT as-is, without re-boxing. +@@ -8831,7 +8849,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + // If the iterator does not have a "throw" method, it calls IteratorClose + // and then throws a TypeError. + IteratorKind iterKind = isAsyncGenerator ? IteratorKind::Async : IteratorKind::Sync; +- if (!emitIteratorClose(iterKind)) // ITER RESULT EXCEPTION ++ if (!emitIteratorCloseInInnermostScope(iterKind)) // ITER RESULT EXCEPTION + return false; + if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_ITERATOR_NO_THROW)) // throw + return false; +@@ -8849,7 +8867,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + checkTypeSet(JSOP_CALL); + + if (isAsyncGenerator) { +- if (!emitAwait()) // ITER OLDRESULT RESULT ++ if (!emitAwaitInInnermostScope()) // ITER OLDRESULT RESULT + return false; + } + +@@ -8920,7 +8938,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + checkTypeSet(JSOP_CALL); + + if (iterKind == IteratorKind::Async) { +- if (!emitAwait()) // ... FTYPE FVALUE RESULT ++ if (!emitAwaitInInnermostScope()) // ... FTYPE FVALUE RESULT + return false; + } + +@@ -8943,7 +8961,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + return false; + + if (isAsyncGenerator) { +- if (!emitAwait()) // ITER OLDRESULT FTYPE FVALUE VALUE ++ if (!emitAwaitInInnermostScope()) // ITER OLDRESULT FTYPE FVALUE VALUE + return false; + } + +@@ -9005,7 +9023,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + checkTypeSet(JSOP_CALL); + + if (isAsyncGenerator) { +- if (!emitAwait()) // ITER RESULT RESULT ++ if (!emitAwaitInInnermostScope()) // ITER RESULT RESULT + return false; + } + +@@ -9038,7 +9056,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + return false; + + if (isAsyncGenerator) { +- if (!emitAwait()) // VALUE ++ if (!emitAwaitInInnermostScope()) // VALUE + return false; + } + +@@ -10592,7 +10610,7 @@ BytecodeEmitter::emitFunctionBody(ParseNode* funBody) + if (!emit1(JSOP_SETRVAL)) + return false; + +- if (!emitGetDotGenerator()) ++ if (!emitGetDotGeneratorInInnermostScope()) + return false; + + // No need to check for finally blocks, etc as in EmitReturn. +@@ -10954,7 +10972,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: + break; + + case PNK_AWAIT: +- if (!emitAwait(pn)) ++ if (!emitAwaitInInnermostScope(pn)) + return false; + break; + +diff --git js/src/frontend/BytecodeEmitter.h js/src/frontend/BytecodeEmitter.h +index f238cc12c0247..039d271e4d965 100644 +--- js/src/frontend/BytecodeEmitter.h ++++ js/src/frontend/BytecodeEmitter.h +@@ -634,14 +634,20 @@ struct MOZ_STACK_CLASS BytecodeEmitter + MOZ_MUST_USE bool iteratorResultShape(unsigned* shape); + MOZ_MUST_USE bool emitToIteratorResult(bool done); + +- MOZ_MUST_USE bool emitGetDotGenerator(); ++ MOZ_MUST_USE bool emitGetDotGeneratorInInnermostScope() { ++ return emitGetDotGeneratorInScope(*innermostEmitterScope); ++ } ++ MOZ_MUST_USE bool emitGetDotGeneratorInScope(EmitterScope& currentScope); + + MOZ_MUST_USE bool emitInitialYield(ParseNode* pn); + MOZ_MUST_USE bool emitYield(ParseNode* pn); + MOZ_MUST_USE bool emitYieldOp(JSOp op); + MOZ_MUST_USE bool emitYieldStar(ParseNode* iter); +- MOZ_MUST_USE bool emitAwait(); +- MOZ_MUST_USE bool emitAwait(ParseNode* pn); ++ MOZ_MUST_USE bool emitAwaitInInnermostScope() { ++ return emitAwaitInScope(*innermostEmitterScope); ++ } ++ MOZ_MUST_USE bool emitAwaitInInnermostScope(ParseNode* pn); ++ MOZ_MUST_USE bool emitAwaitInScope(EmitterScope& currentScope); + + MOZ_MUST_USE bool emitPropLHS(ParseNode* pn); + MOZ_MUST_USE bool emitPropOp(ParseNode* pn, JSOp op); +@@ -738,9 +744,16 @@ struct MOZ_STACK_CLASS BytecodeEmitter + // onto the stack. + MOZ_MUST_USE bool emitIteratorNext(ParseNode* pn, IteratorKind kind = IteratorKind::Sync, + bool allowSelfHosted = false); +- MOZ_MUST_USE bool emitIteratorClose(IteratorKind iterKind = IteratorKind::Sync, +- CompletionKind completionKind = CompletionKind::Normal, +- bool allowSelfHosted = false); ++ MOZ_MUST_USE bool emitIteratorCloseInScope(EmitterScope& currentScope, ++ IteratorKind iterKind = IteratorKind::Sync, ++ CompletionKind completionKind = CompletionKind::Normal, ++ bool allowSelfHosted = false); ++ MOZ_MUST_USE bool emitIteratorCloseInInnermostScope(IteratorKind iterKind = IteratorKind::Sync, ++ CompletionKind completionKind = CompletionKind::Normal, ++ bool allowSelfHosted = false) { ++ return emitIteratorCloseInScope(*innermostEmitterScope, iterKind, completionKind, ++ allowSelfHosted); ++ } + + template + MOZ_MUST_USE bool wrapWithDestructuringIteratorCloseTryNote(int32_t iterDepth, + +commit 0cd861187fc0 +Author: Tooru Fujisawa +Date: Tue May 22 18:10:28 2018 +0900 + + Bug 1454285 - Part 2: Disallow using innermostEmitterScope while the value does not match the bytecode environment. r=jwalden, a=RyanVM + + --HG-- + extra : source : 567757b97ff0f511bb142b966f5b5777bad7fdc2 +--- + js/src/frontend/BytecodeEmitter.cpp | 59 ++++++++++++++++++++----------------- + js/src/frontend/BytecodeEmitter.h | 49 ++++++++++++++++++++++++++---- + 2 files changed, 76 insertions(+), 32 deletions(-) + +diff --git js/src/frontend/BytecodeEmitter.cpp js/src/frontend/BytecodeEmitter.cpp +index e8edc66658804..e13f5bfdd243b 100644 +--- js/src/frontend/BytecodeEmitter.cpp ++++ js/src/frontend/BytecodeEmitter.cpp +@@ -102,7 +102,7 @@ class BytecodeEmitter::NestableControl : public Nestable(&bce->innermostNestableControl), + kind_(kind), +- emitterScope_(bce->innermostEmitterScope) ++ emitterScope_(bce->innermostEmitterScopeNoCheck()) + { } + + public: +@@ -436,7 +436,7 @@ class BytecodeEmitter::EmitterScope : public Nestableparent) { + *bce = (*bce)->parent; +- return (*bce)->innermostEmitterScope; ++ return (*bce)->innermostEmitterScopeNoCheck(); + } + + return nullptr; +@@ -470,7 +470,7 @@ class BytecodeEmitter::EmitterScope : public Nestable(&bce->innermostEmitterScope), ++ : Nestable(&bce->innermostEmitterScope_), + nameCache_(bce->cx->frontendCollectionPool()), + hasEnvironment_(false), + environmentChainLength_(0), +@@ -879,7 +879,7 @@ BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind + Handle bindings) + { + MOZ_ASSERT(kind != ScopeKind::NamedLambda && kind != ScopeKind::StrictNamedLambda); +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + if (!ensureCache(bce)) + return false; +@@ -948,7 +948,7 @@ BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind + bool + BytecodeEmitter::EmitterScope::enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + MOZ_ASSERT(funbox->namedLambdaBindings()); + + if (!ensureCache(bce)) +@@ -1015,7 +1015,7 @@ BytecodeEmitter::EmitterScope::enterComprehensionFor(BytecodeEmitter* bce, + bool + BytecodeEmitter::EmitterScope::enterParameterExpressionVar(BytecodeEmitter* bce) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + if (!ensureCache(bce)) + return false; +@@ -1048,7 +1048,7 @@ BytecodeEmitter::EmitterScope::enterParameterExpressionVar(BytecodeEmitter* bce) + bool + BytecodeEmitter::EmitterScope::enterFunction(BytecodeEmitter* bce, FunctionBox* funbox) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + // If there are parameter expressions, there is an extra var scope. + if (!funbox->hasExtraBodyVarScope()) +@@ -1139,7 +1139,7 @@ BytecodeEmitter::EmitterScope::enterFunctionExtraBodyVar(BytecodeEmitter* bce, F + MOZ_ASSERT(funbox->hasParameterExprs); + MOZ_ASSERT(funbox->extraVarScopeBindings() || + funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings()); +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + // The extra var scope is never popped once it's entered. It replaces the + // function scope as the var emitter scope. +@@ -1225,7 +1225,7 @@ class DynamicBindingIter : public BindingIter + bool + BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedContext* globalsc) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + bce->setVarEmitterScope(this); + +@@ -1285,7 +1285,7 @@ BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedCon + bool + BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + bce->setVarEmitterScope(this); + +@@ -1340,7 +1340,7 @@ BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext + bool + BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedContext* modulesc) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + bce->setVarEmitterScope(this); + +@@ -1397,7 +1397,7 @@ BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedCon + bool + BytecodeEmitter::EmitterScope::enterWith(BytecodeEmitter* bce) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + if (!ensureCache(bce)) + return false; +@@ -1425,7 +1425,7 @@ BytecodeEmitter::EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal) + { + // If we aren't leaving the scope due to a non-local jump (e.g., break), + // we must be the innermost scope. +- MOZ_ASSERT_IF(!nonLocal, this == bce->innermostEmitterScope); ++ MOZ_ASSERT_IF(!nonLocal, this == bce->innermostEmitterScopeNoCheck()); + + ScopeKind kind = scope(bce)->kind(); + switch (kind) { +@@ -2139,7 +2139,7 @@ class ForOfLoopControl : public LoopControl + + bool emitIteratorCloseInInnermostScope(BytecodeEmitter* bce, + CompletionKind completionKind = CompletionKind::Normal) { +- return emitIteratorCloseInScope(bce, *bce->innermostEmitterScope, completionKind); ++ return emitIteratorCloseInScope(bce, *bce->innermostEmitterScope(), completionKind); + } + + bool emitIteratorCloseInScope(BytecodeEmitter* bce, +@@ -2213,8 +2213,11 @@ BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, + bodyScopeIndex(UINT32_MAX), + varEmitterScope(nullptr), + innermostNestableControl(nullptr), +- innermostEmitterScope(nullptr), ++ innermostEmitterScope_(nullptr), + innermostTDZCheckCache(nullptr), ++#ifdef DEBUG ++ unstableEmitterScope(false), ++#endif + constList(cx), + scopeList(cx), + tryNoteList(cx), +@@ -2271,13 +2274,13 @@ BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const + NameLocation + BytecodeEmitter::lookupName(JSAtom* name) + { +- return innermostEmitterScope->lookup(this, name); ++ return innermostEmitterScope()->lookup(this, name); + } + + Maybe + BytecodeEmitter::locationOfNameBoundInScope(JSAtom* name, EmitterScope* target) + { +- return innermostEmitterScope->locationBoundInScope(this, name, target); ++ return innermostEmitterScope()->locationBoundInScope(this, name, target); + } + + Maybe +@@ -2757,7 +2760,7 @@ class NonLocalExitControl + : bce_(bce), + savedScopeNoteIndex_(bce->scopeNoteList.length()), + savedDepth_(bce->stackDepth), +- openScopeNoteIndex_(bce->innermostEmitterScope->noteIndex()), ++ openScopeNoteIndex_(bce->innermostEmitterScope()->noteIndex()), + kind_(kind) + { } + +@@ -2803,9 +2806,11 @@ NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* ta + using NestableControl = BytecodeEmitter::NestableControl; + using EmitterScope = BytecodeEmitter::EmitterScope; + +- EmitterScope* es = bce_->innermostEmitterScope; ++ EmitterScope* es = bce_->innermostEmitterScope(); + int npops = 0; + ++ AutoCheckUnstableEmitterScope cues(bce_); ++ + // For 'continue', 'break', and 'return' statements, emit IteratorClose + // bytecode inline. 'continue' statements do not call IteratorClose for + // the loop they are continuing. +@@ -2924,7 +2929,7 @@ BytecodeEmitter::emitGoto(NestableControl* target, JumpList* jumplist, SrcNoteTy + Scope* + BytecodeEmitter::innermostScope() const + { +- return innermostEmitterScope->scope(this); ++ return innermostEmitterScope()->scope(this); + } + + bool +@@ -3585,7 +3590,7 @@ BytecodeEmitter::needsImplicitThis() + return true; + + // Otherwise see if the current point is under a 'with'. +- for (EmitterScope* es = innermostEmitterScope; es; es = es->enclosingInFrame()) { ++ for (EmitterScope* es = innermostEmitterScope(); es; es = es->enclosingInFrame()) { + if (es->scope(this)->kind() == ScopeKind::With) + return true; + } +@@ -5262,7 +5267,7 @@ BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, Destructuri + // destructuring declaration needs to initialize the name in + // the function scope. The innermost scope is the var scope, + // and its enclosing scope is the function scope. +- EmitterScope* funScope = innermostEmitterScope->enclosingInFrame(); ++ EmitterScope* funScope = innermostEmitterScope()->enclosingInFrame(); + NameLocation paramLoc = *locationOfNameBoundInScope(name, funScope); + if (!emitSetOrInitializeNameAtLocation(name, paramLoc, emitSwapScopeAndRhs, true)) + return false; +@@ -7304,7 +7309,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte + // bindings inducing an environment, recreate the current environment. + DebugOnly forOfTarget = forOfHead->pn_kid1; + MOZ_ASSERT(forOfTarget->isKind(PNK_LET) || forOfTarget->isKind(PNK_CONST)); +- MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope); ++ MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope()); + MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical); + + if (headLexicalEmitterScope->hasEnvironment()) { +@@ -7502,7 +7507,7 @@ BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitte + // it must be the innermost one. If that scope has closed-over + // bindings inducing an environment, recreate the current environment. + MOZ_ASSERT(forInTarget->isKind(PNK_LET) || forInTarget->isKind(PNK_CONST)); +- MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope); ++ MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope()); + MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical); + + if (headLexicalEmitterScope->hasEnvironment()) { +@@ -7635,7 +7640,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc + // exists for the head, it must be the innermost one. If that scope + // has closed-over bindings inducing an environment, recreate the + // current environment. +- MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope); ++ MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope()); + MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical); + + if (headLexicalEmitterScope->hasEnvironment()) { +@@ -7683,7 +7688,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc + + // ES 13.7.4.8 step 3.e. The per-iteration freshening. + if (forLoopRequiresFreshening) { +- MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope); ++ MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope()); + MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical); + + if (headLexicalEmitterScope->hasEnvironment()) { +@@ -10410,7 +10415,7 @@ BytecodeEmitter::emitFunctionFormalParameters(ParseNode* pn) + { + ParseNode* funBody = pn->last(); + FunctionBox* funbox = sc->asFunctionBox(); +- EmitterScope* funScope = innermostEmitterScope; ++ EmitterScope* funScope = innermostEmitterScope(); + + bool hasParameterExprs = funbox->hasParameterExprs; + bool hasRest = funbox->hasRest(); +diff --git js/src/frontend/BytecodeEmitter.h js/src/frontend/BytecodeEmitter.h +index 039d271e4d965..91826f27bf9fd 100644 +--- js/src/frontend/BytecodeEmitter.h ++++ js/src/frontend/BytecodeEmitter.h +@@ -232,9 +232,23 @@ struct MOZ_STACK_CLASS BytecodeEmitter + + EmitterScope* varEmitterScope; + NestableControl* innermostNestableControl; +- EmitterScope* innermostEmitterScope; ++ EmitterScope* innermostEmitterScope_; + TDZCheckCache* innermostTDZCheckCache; + ++#ifdef DEBUG ++ bool unstableEmitterScope; ++ ++ friend class AutoCheckUnstableEmitterScope; ++#endif ++ ++ EmitterScope* innermostEmitterScope() const { ++ MOZ_ASSERT(!unstableEmitterScope); ++ return innermostEmitterScopeNoCheck(); ++ } ++ EmitterScope* innermostEmitterScopeNoCheck() const { ++ return innermostEmitterScope_; ++ } ++ + CGConstList constList; /* constants to be included with the script */ + CGObjectList objectList; /* list of emitted objects */ + CGScopeList scopeList; /* list of emitted scopes */ +@@ -339,7 +353,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter + EmitterScope* source); + + mozilla::Maybe locationOfNameBoundInFunctionScope(JSAtom* name) { +- return locationOfNameBoundInFunctionScope(name, innermostEmitterScope); ++ return locationOfNameBoundInFunctionScope(name, innermostEmitterScope()); + } + + void setVarEmitterScope(EmitterScope* emitterScope) { +@@ -635,7 +649,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter + MOZ_MUST_USE bool emitToIteratorResult(bool done); + + MOZ_MUST_USE bool emitGetDotGeneratorInInnermostScope() { +- return emitGetDotGeneratorInScope(*innermostEmitterScope); ++ return emitGetDotGeneratorInScope(*innermostEmitterScope()); + } + MOZ_MUST_USE bool emitGetDotGeneratorInScope(EmitterScope& currentScope); + +@@ -644,7 +658,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter + MOZ_MUST_USE bool emitYieldOp(JSOp op); + MOZ_MUST_USE bool emitYieldStar(ParseNode* iter); + MOZ_MUST_USE bool emitAwaitInInnermostScope() { +- return emitAwaitInScope(*innermostEmitterScope); ++ return emitAwaitInScope(*innermostEmitterScope()); + } + MOZ_MUST_USE bool emitAwaitInInnermostScope(ParseNode* pn); + MOZ_MUST_USE bool emitAwaitInScope(EmitterScope& currentScope); +@@ -751,7 +765,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter + MOZ_MUST_USE bool emitIteratorCloseInInnermostScope(IteratorKind iterKind = IteratorKind::Sync, + CompletionKind completionKind = CompletionKind::Normal, + bool allowSelfHosted = false) { +- return emitIteratorCloseInScope(*innermostEmitterScope, iterKind, completionKind, ++ return emitIteratorCloseInScope(*innermostEmitterScope(), iterKind, completionKind, + allowSelfHosted); + } + +@@ -852,6 +866,31 @@ struct MOZ_STACK_CLASS BytecodeEmitter + MOZ_MUST_USE bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false); + }; + ++class MOZ_RAII AutoCheckUnstableEmitterScope { ++#ifdef DEBUG ++ bool prev_; ++ BytecodeEmitter* bce_; ++#endif ++ ++ public: ++ AutoCheckUnstableEmitterScope() = delete; ++ explicit AutoCheckUnstableEmitterScope(BytecodeEmitter* bce) ++#ifdef DEBUG ++ : bce_(bce) ++#endif ++ { ++#ifdef DEBUG ++ prev_ = bce_->unstableEmitterScope; ++ bce_->unstableEmitterScope = true; ++#endif ++ } ++ ~AutoCheckUnstableEmitterScope() { ++#ifdef DEBUG ++ bce_->unstableEmitterScope = prev_; ++#endif ++ } ++}; ++ + } /* namespace frontend */ + } /* namespace js */ + Added: head/www/waterfox/files/patch-bug1456189 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/waterfox/files/patch-bug1456189 Thu May 24 00:53:46 2018 (r470749) @@ -0,0 +1,218 @@ +commit e5c1015f6968 +Author: Alex Gaynor +Date: Fri May 18 18:59:00 2018 -0400 + + Bug 1456189 - Simplify BufferList::Extract to make the lifetimes clearer. r=froydnj, a=RyanVM + + --HG-- + extra : source : 9d8c922db947eadeca8278bb33d4f5fe271cef05 +--- + mfbt/BufferList.h | 129 ++++++++++++++++++++++++++++-------------- + mfbt/tests/TestBufferList.cpp | 33 ++++++++++- + 2 files changed, 115 insertions(+), 47 deletions(-) + +diff --git mfbt/BufferList.h mfbt/BufferList.h +index 62ab540df0fbb..a2e7aac32a9f3 100644 +--- mfbt/BufferList.h ++++ mfbt/BufferList.h +@@ -9,6 +9,7 @@ + + #include + #include "mozilla/AllocPolicy.h" ++#include "mozilla/Maybe.h" + #include "mozilla/MemoryReporting.h" + #include "mozilla/Move.h" + #include "mozilla/ScopeExit.h" +@@ -538,61 +539,101 @@ BufferList::Extract(IterImpl& aIter, size_t aSize, bool* aSuccess) + MOZ_ASSERT(aSize % kSegmentAlignment == 0); + MOZ_ASSERT(intptr_t(aIter.mData) % kSegmentAlignment == 0); + +- IterImpl iter = aIter; +- size_t size = aSize; +- size_t toCopy = std::min(size, aIter.RemainingInSegment()); +- MOZ_ASSERT(toCopy % kSegmentAlignment == 0); ++ auto failure = [this, aSuccess]() { ++ *aSuccess = false; ++ return BufferList(0, 0, mStandardCapacity); ++ }; + +- BufferList result(0, toCopy, mStandardCapacity); +- BufferList error(0, 0, mStandardCapacity); ++ // Number of segments we'll need to copy data from to satisfy the request. ++ size_t segmentsNeeded = 0; ++ // If this is None then the last segment is a full segment, otherwise we need ++ // to copy this many bytes. ++ Maybe lastSegmentSize; ++ { ++ // Copy of the iterator to walk the BufferList and see how many segments we ++ // need to copy. ++ IterImpl iter = aIter; ++ size_t remaining = aSize; ++ while (!iter.Done() && remaining && ++ remaining >= iter.RemainingInSegment()) { ++ remaining -= iter.RemainingInSegment(); ++ iter.Advance(*this, iter.RemainingInSegment()); ++ segmentsNeeded++; ++ } + +- // Copy the head +- if (!result.WriteBytes(aIter.mData, toCopy)) { +- *aSuccess = false; +- return error; ++ if (remaining) { ++ if (iter.Done()) { ++ // We reached the end of the BufferList and there wasn't enough data to ++ // satisfy the request. ++ return failure(); ++ } ++ lastSegmentSize.emplace(remaining); ++ // The last block also counts as a segment. This makes the conditionals ++ // on segmentsNeeded work in the rest of the function. ++ segmentsNeeded++; ++ } + } +- iter.Advance(*this, toCopy); +- size -= toCopy; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***