Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 May 2018 00:58:45 +0000 (UTC)
From:      Jan Beich <jbeich@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-branches@freebsd.org
Subject:   svn commit: r470751 - in branches/2018Q2/www/waterfox: . files
Message-ID:  <201805240058.w4O0wjpM093842@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jbeich
Date: Thu May 24 00:58:44 2018
New Revision: 470751
URL: https://svnweb.freebsd.org/changeset/ports/470751

Log:
  MFH: r470749
  
  www/waterfox: apply some FF61 fixes
  
  Approved by:	ports-secteam blanket

Added:
  branches/2018Q2/www/waterfox/files/patch-bug1412882
     - copied unchanged from r470749, head/www/waterfox/files/patch-bug1412882
  branches/2018Q2/www/waterfox/files/patch-bug1454285
     - copied unchanged from r470749, head/www/waterfox/files/patch-bug1454285
  branches/2018Q2/www/waterfox/files/patch-bug1456189
     - copied unchanged from r470749, head/www/waterfox/files/patch-bug1456189
  branches/2018Q2/www/waterfox/files/patch-bug1456512
     - copied unchanged from r470749, head/www/waterfox/files/patch-bug1456512
  branches/2018Q2/www/waterfox/files/patch-bug1462912
     - copied unchanged from r470749, head/www/waterfox/files/patch-bug1462912
Modified:
  branches/2018Q2/www/waterfox/Makefile
Directory Properties:
  branches/2018Q2/   (props changed)

Modified: branches/2018Q2/www/waterfox/Makefile
==============================================================================
--- branches/2018Q2/www/waterfox/Makefile	Thu May 24 00:54:27 2018	(r470750)
+++ branches/2018Q2/www/waterfox/Makefile	Thu May 24 00:58:44 2018	(r470751)
@@ -3,7 +3,7 @@
 PORTNAME=	waterfox
 DISTVERSION=	56.2.0-13
 DISTVERSIONSUFFIX=	-gd2cdd42f4115b
-PORTREVISION=	1
+PORTREVISION=	4
 CATEGORIES=	www ipv6
 
 MAINTAINER=	jbeich@FreeBSD.org

Copied: branches/2018Q2/www/waterfox/files/patch-bug1412882 (from r470749, head/www/waterfox/files/patch-bug1412882)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/2018Q2/www/waterfox/files/patch-bug1412882	Thu May 24 00:58:44 2018	(r470751, copy of r470749, head/www/waterfox/files/patch-bug1412882)
@@ -0,0 +1,192 @@
+commit 7513891383a1
+Author: Jonathan Kew <jkew@mozilla.com>
+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<const Format4Cmap*>(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;

Copied: branches/2018Q2/www/waterfox/files/patch-bug1454285 (from r470749, head/www/waterfox/files/patch-bug1454285)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/2018Q2/www/waterfox/files/patch-bug1454285	Thu May 24 00:58:44 2018	(r470751, copy of r470749, head/www/waterfox/files/patch-bug1454285)
@@ -0,0 +1,713 @@
+commit 58db23895d95
+Author: Tooru Fujisawa <arai_a@mac.com>
+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<ForOfLoopControl>();
+-                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>()) {
+         ForOfLoopControl& loopinfo = target->as<ForOfLoopControl>();
+-        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, &currentScope);
+     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 <typename InnerEmitter>
+     MOZ_MUST_USE bool wrapWithDestructuringIteratorCloseTryNote(int32_t iterDepth,
+
+commit 0cd861187fc0
+Author: Tooru Fujisawa <arai_a@mac.com>
+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<BytecodeEmitter::Nestab
+     NestableControl(BytecodeEmitter* bce, StatementKind kind)
+       : Nestable<NestableControl>(&bce->innermostNestableControl),
+         kind_(kind),
+-        emitterScope_(bce->innermostEmitterScope)
++        emitterScope_(bce->innermostEmitterScopeNoCheck())
+     { }
+ 
+   public:
+@@ -436,7 +436,7 @@ class BytecodeEmitter::EmitterScope : public Nestable<BytecodeEmitter::EmitterSc
+         // enclosing BCE.
+         if ((*bce)->parent) {
+             *bce = (*bce)->parent;
+-            return (*bce)->innermostEmitterScope;
++            return (*bce)->innermostEmitterScopeNoCheck();
+         }
+ 
+         return nullptr;
+@@ -470,7 +470,7 @@ class BytecodeEmitter::EmitterScope : public Nestable<BytecodeEmitter::EmitterSc
+ 
+   public:
+     explicit EmitterScope(BytecodeEmitter* bce)
+-      : Nestable<EmitterScope>(&bce->innermostEmitterScope),
++      : Nestable<EmitterScope>(&bce->innermostEmitterScope_),
+         nameCache_(bce->cx->frontendCollectionPool()),
+         hasEnvironment_(false),
+         environmentChainLength_(0),
+@@ -879,7 +879,7 @@ BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind
+                                             Handle<LexicalScope::Data*> 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<NameLocation>
+ BytecodeEmitter::locationOfNameBoundInScope(JSAtom* name, EmitterScope* target)
+ {
+-    return innermostEmitterScope->locationBoundInScope(this, name, target);
++    return innermostEmitterScope()->locationBoundInScope(this, name, target);
+ }
+ 
+ Maybe<NameLocation>
+@@ -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<ParseNode*> 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<NameLocation> 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 */
+ 

Copied: branches/2018Q2/www/waterfox/files/patch-bug1456189 (from r470749, head/www/waterfox/files/patch-bug1456189)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/2018Q2/www/waterfox/files/patch-bug1456189	Thu May 24 00:58:44 2018	(r470751, copy of r470749, head/www/waterfox/files/patch-bug1456189)
@@ -0,0 +1,218 @@
+commit e5c1015f6968
+Author: Alex Gaynor <agaynor@mozilla.com>
+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 <algorithm>
+ #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<AllocPolicy>::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<size_t> 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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805240058.w4O0wjpM093842>