Attachment #702262: Parser support for bug #568953

View | Details | Raw Unified | Return to bug 568953
Collapse All | Expand All

(-)a/js/src/frontend/BytecodeEmitter.cpp (+1 lines)
Line     Link Here 
 Lines 325-340   EmitJump(JSContext *cx, BytecodeEmitter Link Here 
325
}
325
}
326
326
327
/* XXX too many "... statement" L10N gaffes below -- fix via js.msg! */
327
/* XXX too many "... statement" L10N gaffes below -- fix via js.msg! */
328
const char js_with_statement_str[] = "with statement";
328
const char js_with_statement_str[] = "with statement";
329
const char js_finally_block_str[]  = "finally block";
329
const char js_finally_block_str[]  = "finally block";
330
const char js_script_str[]         = "script";
330
const char js_script_str[]         = "script";
331
331
332
static const char *statementName[] = {
332
static const char *statementName[] = {
333
    "export statement",      /* EXPORT */
333
    "label statement",       /* LABEL */
334
    "label statement",       /* LABEL */
334
    "if statement",          /* IF */
335
    "if statement",          /* IF */
335
    "else statement",        /* ELSE */
336
    "else statement",        /* ELSE */
336
    "destructuring body",    /* BODY */
337
    "destructuring body",    /* BODY */
337
    "switch statement",      /* SWITCH */
338
    "switch statement",      /* SWITCH */
338
    "block",                 /* BLOCK */
339
    "block",                 /* BLOCK */
339
    js_with_statement_str,   /* WITH */
340
    js_with_statement_str,   /* WITH */
340
    "catch block",           /* CATCH */
341
    "catch block",           /* CATCH */
(-)a/js/src/frontend/ParseNode-inl.h (-2 / +5 lines)
Line     Link Here 
 Lines 2-17    Link Here 
2
 * vim: set ts=8 sw=4 et tw=99:
2
 * vim: set ts=8 sw=4 et tw=99:
3
 * This Source Code Form is subject to the terms of the Mozilla Public
3
 * This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
6
7
#ifndef ParseNode_inl_h__
7
#ifndef ParseNode_inl_h__
8
#define ParseNode_inl_h__
8
#define ParseNode_inl_h__
9
9
10
#include "builtin/Module.h"
10
#include "frontend/ParseNode.h"
11
#include "frontend/ParseNode.h"
11
12
12
namespace js {
13
namespace js {
13
namespace frontend {
14
namespace frontend {
14
15
15
inline bool
16
inline bool
16
UpvarCookie::set(JSContext *cx, unsigned newLevel, uint16_t newSlot)
17
UpvarCookie::set(JSContext *cx, unsigned newLevel, uint16_t newSlot)
17
{
18
{
 Lines 26-43   UpvarCookie::set(JSContext *cx, unsigned Link Here 
26
    level_ = newLevel;
27
    level_ = newLevel;
27
    slot_ = newSlot;
28
    slot_ = newSlot;
28
    return true;
29
    return true;
29
}
30
}
30
31
31
inline PropertyName *
32
inline PropertyName *
32
ParseNode::name() const
33
ParseNode::name() const
33
{
34
{
34
    JS_ASSERT(isKind(PNK_FUNCTION) || isKind(PNK_NAME));
35
    JS_ASSERT(isKind(PNK_MODULE) || isKind(PNK_FUNCTION) || isKind(PNK_NAME));
35
    JSAtom *atom = isKind(PNK_FUNCTION) ? pn_funbox->function()->atom() : pn_atom;
36
    JSAtom *atom = isKind(PNK_MODULE) ? pn_modulebox->module()->atom() 
37
                                      : isKind(PNK_FUNCTION) ? pn_funbox->function()->atom()
38
                                                             : pn_atom;
36
    return atom->asPropertyName();
39
    return atom->asPropertyName();
37
}
40
}
38
41
39
inline bool
42
inline bool
40
ParseNode::isConstant()
43
ParseNode::isConstant()
41
{
44
{
42
    switch (pn_type) {
45
    switch (pn_type) {
43
      case PNK_NUMBER:
46
      case PNK_NUMBER:
(-)a/js/src/frontend/ParseNode.h (-21 / +27 lines)
Line     Link Here 
 Lines 142-162   class UpvarCookie Link Here 
142
    F(FILTER) \
142
    F(FILTER) \
143
    F(XMLELEM) \
143
    F(XMLELEM) \
144
    F(XMLLIST) \
144
    F(XMLLIST) \
145
    F(YIELD) \
145
    F(YIELD) \
146
    F(ARRAYCOMP) \
146
    F(ARRAYCOMP) \
147
    F(ARRAYPUSH) \
147
    F(ARRAYPUSH) \
148
    F(LEXICALSCOPE) \
148
    F(LEXICALSCOPE) \
149
    F(LET) \
149
    F(LET) \
150
    F(EXPORT) \
150
    F(SEQ) \
151
    F(SEQ) \
151
    F(FORIN) \
152
    F(FORIN) \
152
    F(FORHEAD) \
153
    F(FORHEAD) \
153
    F(ARGSBODY) \
154
    F(ARGSBODY) \
154
    F(SPREAD) \
155
    F(SPREAD) \
156
    F(MODULE) \
155
    \
157
    \
156
    /* Equality operators. */ \
158
    /* Equality operators. */ \
157
    F(STRICTEQ) \
159
    F(STRICTEQ) \
158
    F(EQ) \
160
    F(EQ) \
159
    F(STRICTNE) \
161
    F(STRICTNE) \
160
    F(NE) \
162
    F(NE) \
161
    \
163
    \
162
    /* Unary operators. */ \
164
    /* Unary operators. */ \
 Lines 487-502   enum ParseNodeArity { Link Here 
487
struct Definition;
489
struct Definition;
488
490
489
class LoopControlStatement;
491
class LoopControlStatement;
490
class BreakStatement;
492
class BreakStatement;
491
class ContinueStatement;
493
class ContinueStatement;
492
class XMLProcessingInstruction;
494
class XMLProcessingInstruction;
493
class ConditionalExpression;
495
class ConditionalExpression;
494
class PropertyAccess;
496
class PropertyAccess;
497
class ModuleBox;
495
498
496
struct ParseNode {
499
struct ParseNode {
497
  private:
500
  private:
498
    uint32_t            pn_type   : 16, /* PNK_* type */
501
    uint32_t            pn_type   : 16, /* PNK_* type */
499
                        pn_op     : 8,  /* see JSOp enum and jsopcode.tbl */
502
                        pn_op     : 8,  /* see JSOp enum and jsopcode.tbl */
500
                        pn_arity  : 5,  /* see ParseNodeArity enum */
503
                        pn_arity  : 5,  /* see ParseNodeArity enum */
501
                        pn_parens : 1,  /* this expr was enclosed in parens */
504
                        pn_parens : 1,  /* this expr was enclosed in parens */
502
                        pn_used   : 1,  /* name node is on a use-chain */
505
                        pn_used   : 1,  /* name node is on a use-chain */
 Lines 598-621   struct ParseNode { Link Here 
598
        struct {                        /* one kid if unary */
601
        struct {                        /* one kid if unary */
599
            ParseNode   *kid;
602
            ParseNode   *kid;
600
            bool        hidden;         /* hidden genexp-induced JSOP_YIELD
603
            bool        hidden;         /* hidden genexp-induced JSOP_YIELD
601
                                           or directive prologue member (as
604
                                           or directive prologue member (as
602
                                           pn_prologue) */
605
                                           pn_prologue) */
603
        } unary;
606
        } unary;
604
        struct {                        /* name, labeled statement, etc. */
607
        struct {                        /* name, labeled statement, etc. */
605
            union {
608
            union {
606
                JSAtom        *atom;    /* lexical name or label atom */
609
                JSAtom      *atom;      /* lexical name or label atom */
607
                ObjectBox     *objbox;  /* block or regexp object */
610
                ObjectBox   *objbox;    /* block or regexp object */
608
                FunctionBox   *funbox;  /* function object */
611
                ModuleBox   *modulebox; /* modulebox */
612
                FunctionBox *funbox;    /* functionbox */
609
            };
613
            };
610
            union {
614
            union {
611
                ParseNode    *expr;     /* function body, var initializer, argument default,
615
                ParseNode  *expr;       /* function body, var initializer, argument default,
612
                                           or base object of PNK_DOT */
616
                                           or base object of PNK_DOT */
613
                Definition   *lexdef;   /* lexical definition for this use */
617
                Definition *lexdef;     /* lexical definition for this use */
614
            };
618
            };
615
            UpvarCookie cookie;         /* upvar cookie with absolute frame
619
            UpvarCookie cookie;         /* upvar cookie with absolute frame
616
                                           level (not relative skip), possibly
620
                                           level (not relative skip), possibly
617
                                           in current frame */
621
                                           in current frame */
618
            uint32_t    dflags:12,      /* definition/use flags, see below */
622
            uint32_t    dflags:12,      /* definition/use flags, see below */
619
                        blockid:20;     /* block number, for subset dominance
623
                        blockid:20;     /* block number, for subset dominance
620
                                           computation */
624
                                           computation */
621
        } name;
625
        } name;
 Lines 626-641   struct ParseNode { Link Here 
626
        } loopControl;
630
        } loopControl;
627
        class {                         /* E4X <?target data?> XML PI */
631
        class {                         /* E4X <?target data?> XML PI */
628
            friend class XMLProcessingInstruction;
632
            friend class XMLProcessingInstruction;
629
            PropertyName     *target;   /* non-empty */
633
            PropertyName     *target;   /* non-empty */
630
            JSAtom           *data;     /* may be empty, never null */
634
            JSAtom           *data;     /* may be empty, never null */
631
        } xmlpi;
635
        } xmlpi;
632
    } pn_u;
636
    } pn_u;
633
637
638
#define pn_modulebox    pn_u.name.modulebox
634
#define pn_funbox       pn_u.name.funbox
639
#define pn_funbox       pn_u.name.funbox
635
#define pn_body         pn_u.name.expr
640
#define pn_body         pn_u.name.expr
636
#define pn_cookie       pn_u.name.cookie
641
#define pn_cookie       pn_u.name.cookie
637
#define pn_dflags       pn_u.name.dflags
642
#define pn_dflags       pn_u.name.dflags
638
#define pn_blockid      pn_u.name.blockid
643
#define pn_blockid      pn_u.name.blockid
639
#define pn_index        pn_u.name.blockid /* reuse as object table index */
644
#define pn_index        pn_u.name.blockid /* reuse as object table index */
640
#define pn_head         pn_u.list.head
645
#define pn_head         pn_u.list.head
641
#define pn_tail         pn_u.list.tail
646
#define pn_tail         pn_u.list.tail
 Lines 728-763   struct ParseNode { Link Here 
728
                                           'arguments' that has been converted
733
                                           'arguments' that has been converted
729
                                           into a definition after the function
734
                                           into a definition after the function
730
                                           body has been parsed. */
735
                                           body has been parsed. */
731
736
732
/* Flags to propagate from uses to definition. */
737
/* Flags to propagate from uses to definition. */
733
#define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_CLOSED)
738
#define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_CLOSED)
734
739
735
/* PN_LIST pn_xflags bits. */
740
/* PN_LIST pn_xflags bits. */
736
#define PNX_STRCAT      0x01            /* PNK_ADD list has string term */
741
#define PNX_STRCAT       0x01           /* PNK_ADD list has string term */
737
#define PNX_CANTFOLD    0x02            /* PNK_ADD list has unfoldable term */
742
#define PNX_CANTFOLD     0x02           /* PNK_ADD list has unfoldable term */
738
#define PNX_POPVAR      0x04            /* PNK_VAR or PNK_CONST last result
743
#define PNX_POPVAR       0x04           /* PNK_VAR or PNK_CONST last result
739
                                           needs popping */
744
                                           needs popping */
740
#define PNX_FORINVAR    0x08            /* PNK_VAR is left kid of PNK_FORIN node
745
#define PNX_FORINVAR     0x08           /* PNK_VAR is left kid of PNK_FORIN node
741
                                           which is left kid of PNK_FOR */
746
                                           which is left kid of PNK_FOR */
742
#define PNX_ENDCOMMA    0x10            /* array literal has comma at end */
747
#define PNX_ENDCOMMA     0x10           /* array literal has comma at end */
743
#define PNX_XMLROOT     0x20            /* top-most node in XML literal tree */
748
#define PNX_XMLROOT      0x20           /* top-most node in XML literal tree */
744
#define PNX_GROUPINIT   0x40            /* var [a, b] = [c, d]; unit list */
749
#define PNX_GROUPINIT    0x40           /* var [a, b] = [c, d]; unit list */
745
#define PNX_NEEDBRACES  0x80            /* braces necessary due to closure */
750
#define PNX_NEEDBRACES   0x80           /* braces necessary due to closure */
746
#define PNX_FUNCDEFS   0x100            /* contains top-level function statements */
751
#define PNX_FUNCDEFS    0x100           /* contains top-level function statements */
747
#define PNX_SETCALL    0x100            /* call expression in lvalue context */
752
#define PNX_MODULEDEFS  0x100           /* contains module statements */
748
#define PNX_DESTRUCT   0x200            /* destructuring special cases:
753
#define PNX_SETCALL     0x100           /* call expression in lvalue context */
754
#define PNX_DESTRUCT    0x200           /* destructuring special cases:
749
                                           1. shorthand syntax used, at present
755
                                           1. shorthand syntax used, at present
750
                                              object destructuring ({x,y}) only;
756
                                              object destructuring ({x,y}) only;
751
                                           2. code evaluating destructuring
757
                                           2. code evaluating destructuring
752
                                              arguments occurs before function
758
                                              arguments occurs before function
753
                                              body */
759
                                              body */
754
#define PNX_HOLEY      0x400            /* array initialiser has holes */
760
#define PNX_HOLEY       0x400           /* array initialiser has holes */
755
#define PNX_NONCONST   0x800            /* initialiser has non-constants */
761
#define PNX_NONCONST    0x800           /* initialiser has non-constants */
756
762
757
    unsigned frameLevel() const {
763
    unsigned frameLevel() const {
758
        JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME);
764
        JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME);
759
        return pn_cookie.level();
765
        return pn_cookie.level();
760
    }
766
    }
761
767
762
    unsigned frameSlot() const {
768
    unsigned frameSlot() const {
763
        JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME);
769
        JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME);
 Lines 1421-1437   struct Definition : public ParseNode Link Here 
1421
1427
1422
    enum Kind { VAR, CONST, LET, ARG, NAMED_LAMBDA, PLACEHOLDER };
1428
    enum Kind { VAR, CONST, LET, ARG, NAMED_LAMBDA, PLACEHOLDER };
1423
1429
1424
    bool canHaveInitializer() { return int(kind()) <= int(ARG); }
1430
    bool canHaveInitializer() { return int(kind()) <= int(ARG); }
1425
1431
1426
    static const char *kindString(Kind kind);
1432
    static const char *kindString(Kind kind);
1427
1433
1428
    Kind kind() {
1434
    Kind kind() {
1429
        if (getKind() == PNK_FUNCTION) {
1435
        if (getKind() == PNK_MODULE) {
1436
            return VAR;
1437
        } else if (getKind() == PNK_FUNCTION) {
1430
            if (isOp(JSOP_GETARG))
1438
            if (isOp(JSOP_GETARG))
1431
                return ARG;
1439
                return ARG;
1432
            return VAR;
1440
            return VAR;
1433
        }
1441
        }
1434
        JS_ASSERT(getKind() == PNK_NAME);
1442
        JS_ASSERT(getKind() == PNK_NAME);
1435
        if (isOp(JSOP_CALLEE))
1443
        if (isOp(JSOP_CALLEE))
1436
            return NAMED_LAMBDA;
1444
            return NAMED_LAMBDA;
1437
        if (isPlaceholder())
1445
        if (isPlaceholder())
 Lines 1492-1509   LinkUseToDef(ParseNode *pn, Definition * Link Here 
1492
    JS_ASSERT(pn != dn->dn_uses);
1500
    JS_ASSERT(pn != dn->dn_uses);
1493
    pn->pn_link = dn->dn_uses;
1501
    pn->pn_link = dn->dn_uses;
1494
    dn->dn_uses = pn;
1502
    dn->dn_uses = pn;
1495
    dn->pn_dflags |= pn->pn_dflags & PND_USE2DEF_FLAGS;
1503
    dn->pn_dflags |= pn->pn_dflags & PND_USE2DEF_FLAGS;
1496
    pn->setUsed(true);
1504
    pn->setUsed(true);
1497
    pn->pn_lexdef = dn;
1505
    pn->pn_lexdef = dn;
1498
}
1506
}
1499
1507
1500
class ModuleBox;
1501
1502
class ObjectBox {
1508
class ObjectBox {
1503
  public:
1509
  public:
1504
    JSObject *object;
1510
    JSObject *object;
1505
1511
1506
    ObjectBox(JSObject *object, ObjectBox *traceLink);
1512
    ObjectBox(JSObject *object, ObjectBox *traceLink);
1507
    bool isModuleBox() { return object->isModule(); }
1513
    bool isModuleBox() { return object->isModule(); }
1508
    bool isFunctionBox() { return object->isFunction(); }
1514
    bool isFunctionBox() { return object->isFunction(); }
1509
    ModuleBox *asModuleBox();
1515
    ModuleBox *asModuleBox();
(-)a/js/src/frontend/Parser.cpp (-68 / +166 lines)
Line     Link Here 
 Lines 36-51    Link Here 
36
#include "jslock.h"
36
#include "jslock.h"
37
#include "jsnum.h"
37
#include "jsnum.h"
38
#include "jsobj.h"
38
#include "jsobj.h"
39
#include "jsopcode.h"
39
#include "jsopcode.h"
40
#include "jsscope.h"
40
#include "jsscope.h"
41
#include "jsscript.h"
41
#include "jsscript.h"
42
#include "jsstr.h"
42
#include "jsstr.h"
43
43
44
#include "builtin/Module.h"
44
#include "frontend/FoldConstants.h"
45
#include "frontend/FoldConstants.h"
45
#include "frontend/ParseMaps.h"
46
#include "frontend/ParseMaps.h"
46
#include "frontend/Parser.h"
47
#include "frontend/Parser.h"
47
#include "frontend/TokenStream.h"
48
#include "frontend/TokenStream.h"
48
#include "gc/Marking.h"
49
#include "gc/Marking.h"
49
50
50
#if JS_HAS_XML_SUPPORT
51
#if JS_HAS_XML_SUPPORT
51
#include "jsxml.h"
52
#include "jsxml.h"
 Lines 164-181   ParseContext::define(JSContext *cx, Prop Link Here 
164
        if (name == cx->names().empty)
165
        if (name == cx->names().empty)
165
            break;
166
            break;
166
        if (!decls_.addUnique(name, dn))
167
        if (!decls_.addUnique(name, dn))
167
            return false;
168
            return false;
168
        break;
169
        break;
169
170
170
      case Definition::CONST:
171
      case Definition::CONST:
171
      case Definition::VAR:
172
      case Definition::VAR:
172
        if (sc->isFunctionBox()) {
173
        if (sc->isModuleBox() || sc->isFunctionBox()) {
173
            dn->setOp(JSOP_GETLOCAL);
174
            dn->setOp(JSOP_GETLOCAL);
175
            /* Modules don't have local variables */
176
            if (sc->isModuleBox())
177
                dn->pn_dflags |= PND_CLOSED;
174
            dn->pn_dflags |= PND_BOUND;
178
            dn->pn_dflags |= PND_BOUND;
175
            if (!dn->pn_cookie.set(cx, staticLevel, vars_.length()))
179
            if (!dn->pn_cookie.set(cx, staticLevel, vars_.length()))
176
                return false;
180
                return false;
177
            if (!vars_.append(dn))
181
            if (!vars_.append(dn))
178
                return false;
182
                return false;
179
        }
183
        }
180
        if (!decls_.addUnique(name, dn))
184
        if (!decls_.addUnique(name, dn))
181
            return false;
185
            return false;
 Lines 278-296   AppendPackedBindings(const ParseContext Link Here 
278
                       (pc->sc->bindingsAccessedDynamically() &&
282
                       (pc->sc->bindingsAccessedDynamically() &&
279
                        pc->decls().lookupFirst(name) == dn);
283
                        pc->decls().lookupFirst(name) == dn);
280
284
281
        *dst = Binding(name, kind, aliased);
285
        *dst = Binding(name, kind, aliased);
282
    }
286
    }
283
}
287
}
284
288
285
bool
289
bool
286
ParseContext::generateFunctionBindings(JSContext *cx, InternalHandle<Bindings*> bindings) const
290
ParseContext::generateBindings(JSContext *cx, InternalHandle<Bindings*> bindings) const
287
{
291
{
288
    JS_ASSERT(sc->isFunctionBox());
292
    JS_ASSERT(sc->isModuleBox() || sc->isFunctionBox());
293
    JS_ASSERT_IF(sc->isModuleBox(), args_.length() == 0);
289
294
290
    unsigned count = args_.length() + vars_.length();
295
    unsigned count = args_.length() + vars_.length();
291
    Binding *packedBindings = cx->tempLifoAlloc().newArrayUninitialized<Binding>(count);
296
    Binding *packedBindings = cx->tempLifoAlloc().newArrayUninitialized<Binding>(count);
292
    if (!packedBindings) {
297
    if (!packedBindings) {
293
        js_ReportOutOfMemory(cx);
298
        js_ReportOutOfMemory(cx);
294
        return false;
299
        return false;
295
    }
300
    }
296
301
 Lines 298-316   ParseContext::generateFunctionBindings(J Link Here 
298
    AppendPackedBindings(this, vars_, packedBindings + args_.length());
303
    AppendPackedBindings(this, vars_, packedBindings + args_.length());
299
304
300
    if (!Bindings::initWithTemporaryStorage(cx, bindings, args_.length(), vars_.length(),
305
    if (!Bindings::initWithTemporaryStorage(cx, bindings, args_.length(), vars_.length(),
301
                                            packedBindings))
306
                                            packedBindings))
302
    {
307
    {
303
        return false;
308
        return false;
304
    }
309
    }
305
310
306
    FunctionBox *funbox = sc->asFunctionBox();
311
    if (sc->isFunctionBox()) {
307
    if (bindings->hasAnyAliasedBindings() || funbox->hasExtensibleScope())
312
        FunctionBox *funbox = sc->asFunctionBox();
308
        funbox->function()->setIsHeavyweight();
313
        if (bindings->hasAnyAliasedBindings() || funbox->hasExtensibleScope())
314
            funbox->function()->setIsHeavyweight();
315
    }
309
316
310
    return true;
317
    return true;
311
}
318
}
312
319
313
Parser::Parser(JSContext *cx, const CompileOptions &options,
320
Parser::Parser(JSContext *cx, const CompileOptions &options,
314
               StableCharPtr chars, size_t length, bool foldConstants)
321
               StableCharPtr chars, size_t length, bool foldConstants)
315
  : AutoGCRooter(cx, PARSER),
322
  : AutoGCRooter(cx, PARSER),
316
    context(cx),
323
    context(cx),
 Lines 758-774   Parser::standaloneFunctionBody(HandleFun Link Here 
758
        reportError(NULL, JSMSG_SYNTAX_ERROR);
765
        reportError(NULL, JSMSG_SYNTAX_ERROR);
759
        return NULL;
766
        return NULL;
760
    }
767
    }
761
768
762
    if (!FoldConstants(context, pn, this))
769
    if (!FoldConstants(context, pn, this))
763
        return NULL;
770
        return NULL;
764
771
765
    InternalHandle<Bindings*> bindings(script, &script->bindings);
772
    InternalHandle<Bindings*> bindings(script, &script->bindings);
766
    if (!funpc.generateFunctionBindings(context, bindings))
773
    if (!funpc.generateBindings(context, bindings))
767
        return NULL;
774
        return NULL;
768
775
769
    return pn;
776
    return pn;
770
}
777
}
771
778
772
ParseNode *
779
ParseNode *
773
Parser::functionBody(FunctionBodyType type)
780
Parser::functionBody(FunctionBodyType type)
774
{
781
{
 Lines 1162-1236   DeoptimizeUsesWithin(Definition *dn, con Link Here 
1162
1169
1163
/*
1170
/*
1164
 * Beware: this function is called for functions nested in other functions or
1171
 * Beware: this function is called for functions nested in other functions or
1165
 * global scripts but not for functions compiled through the Function
1172
 * global scripts but not for functions compiled through the Function
1166
 * constructor or JSAPI. To always execute code when a function has finished
1173
 * constructor or JSAPI. To always execute code when a function has finished
1167
 * parsing, use Parser::functionBody.
1174
 * parsing, use Parser::functionBody.
1168
 */
1175
 */
1169
static bool
1176
static bool
1170
LeaveFunction(ParseNode *fn, Parser *parser, PropertyName *funName = NULL,
1177
LeaveContext(ParseNode *pn, Parser *parser, PropertyName *funName = NULL,
1171
              FunctionSyntaxKind kind = Expression)
1178
             FunctionSyntaxKind kind = Expression)
1172
{
1179
{
1173
    JSContext *cx = parser->context;
1180
    JSContext *cx = parser->context;
1174
    ParseContext *funpc = parser->pc;
1181
    ParseContext *pc = parser->pc;
1175
    ParseContext *pc = funpc->parent;
1182
    ParseContext *outerpc = pc->parent;
1176
    pc->blockidGen = funpc->blockidGen;
1183
    outerpc->blockidGen = pc->blockidGen;
1177
1184
1178
    FunctionBox *funbox = fn->pn_funbox;
1185
    if (!outerpc->topStmt || outerpc->topStmt->type == STMT_BLOCK)
1179
    JS_ASSERT(funbox == funpc->sc->asFunctionBox());
1186
        pn->pn_dflags |= PND_BLOCKCHILD;
1180
1181
    if (!pc->topStmt || pc->topStmt->type == STMT_BLOCK)
1182
        fn->pn_dflags |= PND_BLOCKCHILD;
1183
1187
1184
    /* Propagate unresolved lexical names up to pc->lexdeps. */
1188
    /* Propagate unresolved lexical names up to pc->lexdeps. */
1185
    if (funpc->lexdeps->count()) {
1189
    if (pc->lexdeps->count()) {
1186
        for (AtomDefnRange r = funpc->lexdeps->all(); !r.empty(); r.popFront()) {
1190
        for (AtomDefnRange r = pc->lexdeps->all(); !r.empty(); r.popFront()) {
1187
            JSAtom *atom = r.front().key();
1191
            JSAtom *atom = r.front().key();
1188
            Definition *dn = r.front().value();
1192
            Definition *dn = r.front().value();
1189
            JS_ASSERT(dn->isPlaceholder());
1193
            JS_ASSERT(dn->isPlaceholder());
1190
1194
1191
            if (atom == funName && kind == Expression) {
1195
            if (pc->sc->isFunctionBox()) {
1192
                dn->setOp(JSOP_CALLEE);
1196
                if (atom == funName && kind == Expression) {
1193
                if (!dn->pn_cookie.set(cx, funpc->staticLevel,
1197
                    dn->setOp(JSOP_CALLEE);
1194
                                       UpvarCookie::CALLEE_SLOT))
1198
                    if (!dn->pn_cookie.set(cx, pc->staticLevel,
1195
                    return false;
1199
                                           UpvarCookie::CALLEE_SLOT))
1196
                dn->pn_dflags |= PND_BOUND;
1200
                        return false;
1197
                JS_ASSERT(dn->kind() == Definition::NAMED_LAMBDA);
1201
                    dn->pn_dflags |= PND_BOUND;
1198
1202
                    JS_ASSERT(dn->kind() == Definition::NAMED_LAMBDA);
1199
                /*
1203
1200
                 * Since 'dn' is a placeholder, it has not been defined in the
1204
                    /*
1201
                 * ParseContext and hence we must manually flag a closed-over
1205
                     * Since 'dn' is a placeholder, it has not been defined in the
1202
                 * callee name as needing a dynamic scope (this is done for all
1206
                     * ParseContext and hence we must manually flag a closed-over
1203
                 * definitions in the ParseContext by generateFunctionBindings).
1207
                     * callee name as needing a dynamic scope (this is done for all
1204
                 *
1208
                     * definitions in the ParseContext by generateBindings).
1205
                 * If 'dn' has been assigned to, then we also flag the function
1209
                     *
1206
                 * scope has needing a dynamic scope so that dynamic scope
1210
                     * If 'dn' has been assigned to, then we also flag the function
1207
                 * setter can either ignore the set (in non-strict mode) or
1211
                     * scope has needing a dynamic scope so that dynamic scope
1208
                 * produce an error (in strict mode).
1212
                     * setter can either ignore the set (in non-strict mode) or
1209
                 */
1213
                     * produce an error (in strict mode).
1210
                if (dn->isClosed() || dn->isAssigned())
1214
                     */
1211
                    funbox->function()->setIsHeavyweight();
1215
                    if (dn->isClosed() || dn->isAssigned())
1212
                continue;
1216
                        pc->sc->asFunctionBox()->function()->setIsHeavyweight();
1217
                    continue;
1218
                }
1213
            }
1219
            }
1214
1220
1215
            Definition *outer_dn = pc->decls().lookupFirst(atom);
1221
            Definition *outerdn = outerpc->decls().lookupFirst(atom);
1216
1222
1217
            /*
1223
            /*
1218
             * Make sure to deoptimize lexical dependencies that are polluted
1224
             * Make sure to deoptimize lexical dependencies that are polluted
1219
             * by eval and function statements (which both flag the function as
1225
             * by eval and function statements (which both flag the function as
1220
             * having an extensible scope) or any enclosing 'with'.
1226
             * having an extensible scope) or any enclosing 'with'.
1221
             */
1227
             */
1222
            if (funbox->hasExtensibleScope() || pc->parsingWith)
1228
            if ((pc->sc->isFunctionBox() && pc->sc->asFunctionBox()->hasExtensibleScope()) ||
1223
                DeoptimizeUsesWithin(dn, fn->pn_pos);
1229
                outerpc->parsingWith)
1224
1230
                DeoptimizeUsesWithin(dn, pn->pn_pos);
1225
            if (!outer_dn) {
1231
1226
                AtomDefnAddPtr p = pc->lexdeps->lookupForAdd(atom);
1232
            if (!outerdn) {
1233
                AtomDefnAddPtr p = outerpc->lexdeps->lookupForAdd(atom);
1227
                if (p) {
1234
                if (p) {
1228
                    outer_dn = p.value();
1235
                    outerdn = p.value();
1229
                } else {
1236
                } else {
1230
                    /*
1237
                    /*
1231
                     * Create a new placeholder for our outer lexdep. We could
1238
                     * Create a new placeholder for our outer lexdep. We could
1232
                     * simply re-use the inner placeholder, but that introduces
1239
                     * simply re-use the inner placeholder, but that introduces
1233
                     * subtleties in the case where we find a later definition
1240
                     * subtleties in the case where we find a later definition
1234
                     * that captures an existing lexdep. For example:
1241
                     * that captures an existing lexdep. For example:
1235
                     *
1242
                     *
1236
                     *   function f() { function g() { x; } let x; }
1243
                     *   function f() { function g() { x; } let x; }
 Lines 1243-1304   LeaveFunction(ParseNode *fn, Parser *par Link Here 
1243
                     *   function f() { x; { function g() { x; } let x; } }
1250
                     *   function f() { x; { function g() { x; } let x; } }
1244
                     *
1251
                     *
1245
                     * Here, the 'let' must not capture all the uses of f's
1252
                     * Here, the 'let' must not capture all the uses of f's
1246
                     * lexdep entry for x, but it must capture the x node
1253
                     * lexdep entry for x, but it must capture the x node
1247
                     * referred to from g's TOK_UPVARS node.  Always turning
1254
                     * referred to from g's TOK_UPVARS node.  Always turning
1248
                     * inherited lexdeps into uses of a new outer definition
1255
                     * inherited lexdeps into uses of a new outer definition
1249
                     * allows us to handle both these cases in a natural way.
1256
                     * allows us to handle both these cases in a natural way.
1250
                     */
1257
                     */
1251
                    outer_dn = MakePlaceholder(dn, parser, pc);
1258
                    outerdn = MakePlaceholder(dn, parser, outerpc);
1252
                    if (!outer_dn || !pc->lexdeps->add(p, atom, outer_dn))
1259
                    if (!outerdn || !outerpc->lexdeps->add(p, atom, outerdn))
1253
                        return false;
1260
                        return false;
1254
                }
1261
                }
1255
            }
1262
            }
1256
1263
1257
            /*
1264
            /*
1258
             * Insert dn's uses list at the front of outer_dn's list.
1265
             * Insert dn's uses list at the front of outerdn's list.
1259
             *
1266
             *
1260
             * Without loss of generality or correctness, we allow a dn to
1267
             * Without loss of generality or correctness, we allow a dn to
1261
             * be in inner and outer lexdeps, since the purpose of lexdeps
1268
             * be in inner and outer lexdeps, since the purpose of lexdeps
1262
             * is one-pass coordination of name use and definition across
1269
             * is one-pass coordination of name use and definition across
1263
             * functions, and if different dn's are used we'll merge lists
1270
             * functions, and if different dn's are used we'll merge lists
1264
             * when leaving the inner function.
1271
             * when leaving the inner function.
1265
             *
1272
             *
1266
             * The dn == outer_dn case arises with generator expressions
1273
             * The dn == outerdn case arises with generator expressions
1267
             * (see CompExprTransplanter::transplant, the PN_FUNC/PN_NAME
1274
             * (see CompExprTransplanter::transplant, the PN_FUNC/PN_NAME
1268
             * case), and nowhere else, currently.
1275
             * case), and nowhere else, currently.
1269
             */
1276
             */
1270
            if (dn != outer_dn) {
1277
            if (dn != outerdn) {
1271
                if (ParseNode *pnu = dn->dn_uses) {
1278
                if (ParseNode *pnu = dn->dn_uses) {
1272
                    while (true) {
1279
                    while (true) {
1273
                        pnu->pn_lexdef = outer_dn;
1280
                        pnu->pn_lexdef = outerdn;
1274
                        if (!pnu->pn_link)
1281
                        if (!pnu->pn_link)
1275
                            break;
1282
                            break;
1276
                        pnu = pnu->pn_link;
1283
                        pnu = pnu->pn_link;
1277
                    }
1284
                    }
1278
                    pnu->pn_link = outer_dn->dn_uses;
1285
                    pnu->pn_link = outerdn->dn_uses;
1279
                    outer_dn->dn_uses = dn->dn_uses;
1286
                    outerdn->dn_uses = dn->dn_uses;
1280
                    dn->dn_uses = NULL;
1287
                    dn->dn_uses = NULL;
1281
                }
1288
                }
1282
1289
1283
                outer_dn->pn_dflags |= dn->pn_dflags & ~PND_PLACEHOLDER;
1290
                outerdn->pn_dflags |= dn->pn_dflags & ~PND_PLACEHOLDER;
1284
            }
1291
            }
1285
1292
1286
            /* Mark the outer dn as escaping. */
1293
            /* Mark the outer dn as escaping. */
1287
            outer_dn->pn_dflags |= PND_CLOSED;
1294
            outerdn->pn_dflags |= PND_CLOSED;
1288
        }
1295
        }
1289
    }
1296
    }
1290
1297
1291
    InternalHandle<Bindings*> bindings =
1298
    InternalHandle<Bindings*> bindings = pc->sc->isModuleBox()
1292
        InternalHandle<Bindings*>::fromMarkedLocation(&funbox->bindings);
1299
        ? InternalHandle<Bindings*>::fromMarkedLocation(&pc->sc->asModuleBox()->bindings)
1293
    if (!funpc->generateFunctionBindings(cx, bindings))
1300
        : InternalHandle<Bindings*>::fromMarkedLocation(&pc->sc->asFunctionBox()->bindings);
1301
    if (!pc->generateBindings(cx, bindings))
1294
        return false;
1302
        return false;
1295
1303
1296
    funpc->lexdeps.releaseMap(cx);
1304
    pc->lexdeps.releaseMap(cx);
1297
    return true;
1305
    return true;
1298
}
1306
}
1299
1307
1300
/*
1308
/*
1301
 * DefineArg is called for both the arguments of a regular function definition
1309
 * DefineArg is called for both the arguments of a regular function definition
1302
 * and the arguments specified by the Function constructor.
1310
 * and the arguments specified by the Function constructor.
1303
 *
1311
 *
1304
 * The 'disallowDuplicateArgs' bool indicates whether the use of another
1312
 * The 'disallowDuplicateArgs' bool indicates whether the use of another
 Lines 1611-1628   Parser::functionDef(HandlePropertyName f Link Here 
1611
         * As a SpiderMonkey-specific extension, non-body-level function
1619
         * As a SpiderMonkey-specific extension, non-body-level function
1612
         * statements (e.g., functions in an "if" or "while" block) are
1620
         * statements (e.g., functions in an "if" or "while" block) are
1613
         * dynamically bound when control flow reaches the statement. The
1621
         * dynamically bound when control flow reaches the statement. The
1614
         * emitter normally emits functions in two passes (see PNK_ARGSBODY).
1622
         * emitter normally emits functions in two passes (see PNK_ARGSBODY).
1615
         * To distinguish
1623
         * To distinguish
1616
         */
1624
         */
1617
        if (bodyLevel) {
1625
        if (bodyLevel) {
1618
            JS_ASSERT(pn->functionIsHoisted());
1626
            JS_ASSERT(pn->functionIsHoisted());
1619
            JS_ASSERT_IF(pc->sc->isFunctionBox(), !pn->pn_cookie.isFree());
1627
            JS_ASSERT_IF(pc->sc->isGlobalSharedContext(), pn->pn_cookie.isFree());
1620
            JS_ASSERT_IF(!pc->sc->isFunctionBox(), pn->pn_cookie.isFree());
1628
            JS_ASSERT_IF(pc->sc->isModuleBox() || pc->sc->isFunctionBox(), !pn->pn_cookie.isFree());
1621
        } else {
1629
        } else {
1622
            JS_ASSERT(!pc->sc->strict);
1630
            JS_ASSERT(!pc->sc->strict);
1623
            JS_ASSERT(pn->pn_cookie.isFree());
1631
            JS_ASSERT(pn->pn_cookie.isFree());
1624
            if (pc->sc->isFunctionBox()) {
1632
            if (pc->sc->isFunctionBox()) {
1625
                FunctionBox *funbox = pc->sc->asFunctionBox();
1633
                FunctionBox *funbox = pc->sc->asFunctionBox();
1626
                funbox->setMightAliasLocals();
1634
                funbox->setMightAliasLocals();
1627
                funbox->setHasExtensibleScope();
1635
                funbox->setHasExtensibleScope();
1628
            }
1636
            }
 Lines 1814-1836   Parser::functionArgsAndBody(ParseNode *p Link Here 
1814
        outerpc->sc->setBindingsAccessedDynamically();
1822
        outerpc->sc->setBindingsAccessedDynamically();
1815
1823
1816
1824
1817
    pn->pn_funbox = funbox;
1825
    pn->pn_funbox = funbox;
1818
    pn->pn_body->append(body);
1826
    pn->pn_body->append(body);
1819
    pn->pn_body->pn_pos = body->pn_pos;
1827
    pn->pn_body->pn_pos = body->pn_pos;
1820
    pn->pn_blockid = outerpc->blockid();
1828
    pn->pn_blockid = outerpc->blockid();
1821
1829
1822
    if (!LeaveFunction(pn, this, funName, kind))
1830
    if (!LeaveContext(pn, this, funName, kind))
1823
        return false;
1831
        return false;
1824
1832
1825
    return true;
1833
    return true;
1826
}
1834
}
1827
1835
1828
ParseNode *
1836
ParseNode *
1837
Parser::moduleStmt()
1838
{
1839
    JS_ASSERT(versionNumber() == JSVERSION_ECMA_5);
1840
    JS_ASSERT(tokenStream.currentToken().name() == context->names().module);
1841
    JS_ALWAYS_TRUE(tokenStream.matchToken(TOK_NAME));
1842
1843
    if (pc->sc->isFunctionBox() || !pc->atBodyLevel()) {
1844
        reportError(NULL, JSMSG_MODULE_STATEMENT);
1845
        return NULL;
1846
    }
1847
    RootedPropertyName name(context, tokenStream.currentToken().name());
1848
    ParseNode *pn = NameNode::create(PNK_MODULE, name, this, pc);
1849
    if (!pn)
1850
        return NULL;
1851
    if (Definition *dn = pc->lexdeps.lookupDefn(name)) {
1852
        JS_ASSERT(dn->isDefn());
1853
        dn->setKind(PNK_MODULE);
1854
        dn->setArity(PN_NAME);
1855
        dn->pn_pos.begin = pn->pn_pos.begin;
1856
        dn->pn_pos.end = pn->pn_pos.end;
1857
1858
        dn->pn_body = NULL;
1859
        dn->pn_cookie.makeFree();
1860
1861
        pc->lexdeps->remove(name);
1862
        freeTree(pn);
1863
        pn = dn;
1864
    }
1865
    if (!pc->define(context, name, pn, Definition::VAR))
1866
        return NULL;
1867
1868
    Module *module = js_NewModule(context, name);
1869
    if (!module)
1870
        return NULL;
1871
    ModuleBox *modulebox = context->tempLifoAlloc().new_<ModuleBox>(context, pc, module, traceListHead);
1872
    if (!modulebox) {
1873
        js_ReportOutOfMemory(context);
1874
        return NULL;
1875
    }
1876
    pn->pn_modulebox = modulebox;
1877
1878
    ParseContext modulepc(this, modulebox, pc->staticLevel + 1, pc->blockidGen);
1879
    if (!modulepc.init())
1880
        return NULL;
1881
1882
    MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_MODULE);
1883
    modulebox->bufStart = tokenStream.offsetOfToken(tokenStream.currentToken());
1884
    pn->pn_body = statements();
1885
    MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_MODULE);
1886
    pn->pn_modulebox->bufEnd = tokenStream.offsetOfToken(tokenStream.currentToken()) + 1;
1887
1888
    if (!LeaveContext(pn, this))
1889
        return NULL;
1890
    return pn;
1891
}
1892
1893
ParseNode *
1829
Parser::functionStmt()
1894
Parser::functionStmt()
1830
{
1895
{
1831
    JS_ASSERT(tokenStream.currentToken().type == TOK_FUNCTION);
1896
    JS_ASSERT(tokenStream.currentToken().type == TOK_FUNCTION);
1832
    RootedPropertyName name(context);
1897
    RootedPropertyName name(context);
1833
    if (tokenStream.getToken(TSF_KEYWORD_IS_NAME) == TOK_NAME) {
1898
    if (tokenStream.getToken(TSF_KEYWORD_IS_NAME) == TOK_NAME) {
1834
        name = tokenStream.currentToken().name();
1899
        name = tokenStream.currentToken().name();
1835
    } else {
1900
    } else {
1836
        /* Unnamed function expressions are forbidden in statement context. */
1901
        /* Unnamed function expressions are forbidden in statement context. */
 Lines 1967-1983   Parser::statements(bool *hasFunctionStmt Link Here 
1967
            return NULL;
2032
            return NULL;
1968
        }
2033
        }
1969
2034
1970
        if (canHaveDirectives) {
2035
        if (canHaveDirectives) {
1971
            if (!maybeParseDirective(next, &canHaveDirectives))
2036
            if (!maybeParseDirective(next, &canHaveDirectives))
1972
                return NULL;
2037
                return NULL;
1973
        }
2038
        }
1974
2039
1975
        if (next->isKind(PNK_FUNCTION)) {
2040
        if (next->isKind(PNK_MODULE)) {
2041
            JS_ASSERT(pc->atBodyLevel());
2042
            pn->pn_xflags |= PNX_MODULEDEFS;
2043
        } else if (next->isKind(PNK_FUNCTION)) {
1976
            /*
2044
            /*
1977
             * PNX_FUNCDEFS notifies the emitter that the block contains body-
2045
             * PNX_FUNCDEFS notifies the emitter that the block contains body-
1978
             * level function definitions that should be processed before the
2046
             * level function definitions that should be processed before the
1979
             * rest of nodes.
2047
             * rest of nodes.
1980
             *
2048
             *
1981
             * |hasFunctionStmt| is for the TOK_LC case in Statement. It
2049
             * |hasFunctionStmt| is for the TOK_LC case in Statement. It
1982
             * is relevant only for function definitions not at body-level,
2050
             * is relevant only for function definitions not at body-level,
1983
             * which we call function statements.
2051
             * which we call function statements.
 Lines 3690-3705   Parser::letStatement() Link Here 
3690
    } while (0);
3758
    } while (0);
3691
3759
3692
    /* Check termination of this primitive statement. */
3760
    /* Check termination of this primitive statement. */
3693
    return MatchOrInsertSemicolon(context, &tokenStream) ? pn : NULL;
3761
    return MatchOrInsertSemicolon(context, &tokenStream) ? pn : NULL;
3694
}
3762
}
3695
#endif
3763
#endif
3696
3764
3697
ParseNode *
3765
ParseNode *
3766
Parser::exportStatement()
3767
{
3768
    if (!pc->sc->isModuleBox()) {
3769
        reportError(NULL, JSMSG_EXPORT_STATEMENT);
3770
        return NULL;
3771
    }
3772
    ParseNode *pn = UnaryNode::create(PNK_EXPORT, this);
3773
    if (!pn)
3774
        return NULL;
3775
    StmtInfoPC stmtInfo(context);
3776
    PushStatementPC(pc, &stmtInfo, STMT_EXPORT);
3777
    pn->pn_kid = statement();
3778
    PopStatementPC(context, pc);
3779
    if (!pn->pn_kid)
3780
        return NULL;
3781
    return pn;
3782
}
3783
3784
ParseNode *
3698
Parser::expressionStatement()
3785
Parser::expressionStatement()
3699
{
3786
{
3700
    tokenStream.ungetToken();
3787
    tokenStream.ungetToken();
3701
    ParseNode *pn2 = expr();
3788
    ParseNode *pn2 = expr();
3702
    if (!pn2)
3789
    if (!pn2)
3703
        return NULL;
3790
        return NULL;
3704
3791
3705
    if (tokenStream.peekToken() == TOK_COLON) {
3792
    if (tokenStream.peekToken() == TOK_COLON) {
 Lines 4000-4015   Parser::statement() Link Here 
4000
        pn->pn_xflags |= PNX_POPVAR;
4087
        pn->pn_xflags |= PNX_POPVAR;
4001
        break;
4088
        break;
4002
4089
4003
#if JS_HAS_BLOCK_SCOPE
4090
#if JS_HAS_BLOCK_SCOPE
4004
      case TOK_LET:
4091
      case TOK_LET:
4005
        return letStatement();
4092
        return letStatement();
4006
#endif /* JS_HAS_BLOCK_SCOPE */
4093
#endif /* JS_HAS_BLOCK_SCOPE */
4007
4094
4095
      case TOK_EXPORT:
4096
        return exportStatement();
4097
4008
      case TOK_RETURN:
4098
      case TOK_RETURN:
4009
        pn = returnOrYield(false);
4099
        pn = returnOrYield(false);
4010
        if (!pn)
4100
        if (!pn)
4011
            return NULL;
4101
            return NULL;
4012
        break;
4102
        break;
4013
4103
4014
      case TOK_LC:
4104
      case TOK_LC:
4015
      {
4105
      {
 Lines 4078-4093   Parser::statement() Link Here 
4078
        pn->pn_kid = pn2;
4168
        pn->pn_kid = pn2;
4079
        break;
4169
        break;
4080
      }
4170
      }
4081
#endif
4171
#endif
4082
4172
4083
      case TOK_ERROR:
4173
      case TOK_ERROR:
4084
        return NULL;
4174
        return NULL;
4085
4175
4176
      case TOK_NAME:
4177
        if (versionNumber() == JSVERSION_ECMA_5 &&
4178
            tokenStream.currentToken().name() == context->names().module &&
4179
            tokenStream.peekTokenSameLine(TSF_OPERAND) == TOK_NAME)
4180
        {
4181
            return moduleStmt();
4182
        }
4183
4086
      default:
4184
      default:
4087
        return expressionStatement();
4185
        return expressionStatement();
4088
    }
4186
    }
4089
4187
4090
    /* Check termination of this primitive statement. */
4188
    /* Check termination of this primitive statement. */
4091
    return MatchOrInsertSemicolon(context, &tokenStream) ? pn : NULL;
4189
    return MatchOrInsertSemicolon(context, &tokenStream) ? pn : NULL;
4092
}
4190
}
4093
4191
 Lines 5388-5404   Parser::generatorExpr(ParseNode *kid) Link Here 
5388
5486
5389
        if (AtomDefnPtr p = genpc.lexdeps->lookup(context->names().arguments)) {
5487
        if (AtomDefnPtr p = genpc.lexdeps->lookup(context->names().arguments)) {
5390
            Definition *dn = p.value();
5488
            Definition *dn = p.value();
5391
            ParseNode *errorNode = dn->dn_uses ? dn->dn_uses : body;
5489
            ParseNode *errorNode = dn->dn_uses ? dn->dn_uses : body;
5392
            reportError(errorNode, JSMSG_BAD_GENEXP_BODY, js_arguments_str);
5490
            reportError(errorNode, JSMSG_BAD_GENEXP_BODY, js_arguments_str);
5393
            return NULL;
5491
            return NULL;
5394
        }
5492
        }
5395
5493
5396
        if (!LeaveFunction(genfn, this))
5494
        if (!LeaveContext(genfn, this))
5397
            return NULL;
5495
            return NULL;
5398
    }
5496
    }
5399
5497
5400
    /*
5498
    /*
5401
     * Our result is a call expression that invokes the anonymous generator
5499
     * Our result is a call expression that invokes the anonymous generator
5402
     * function object.
5500
     * function object.
5403
     */
5501
     */
5404
    ParseNode *result = ListNode::create(PNK_CALL, this);
5502
    ParseNode *result = ListNode::create(PNK_CALL, this);
(-)a/js/src/frontend/Parser.h (-4 / +6 lines)
Line     Link Here 
 Lines 130-159   struct ParseContext /* t Link Here 
130
130
131
    /* See the sad story in DefineArg. */
131
    /* See the sad story in DefineArg. */
132
    void prepareToAddDuplicateArg(Definition *prevDecl);
132
    void prepareToAddDuplicateArg(Definition *prevDecl);
133
133
134
    /* See the sad story in MakeDefIntoUse. */
134
    /* See the sad story in MakeDefIntoUse. */
135
    void updateDecl(JSAtom *atom, ParseNode *newDecl);
135
    void updateDecl(JSAtom *atom, ParseNode *newDecl);
136
136
137
    /*
137
    /*
138
     * After a function body has been parsed, the parser generates the
138
     * After a module or function body has been parsed, the parser generates
139
     * function's "bindings". Bindings are a data-structure, ultimately stored
139
     * its "bindings". Bindings are a data-structure, ultimately stored in the
140
     * in the compiled JSScript, that serve three purposes:
140
     * compiled JSScript, that serve three purposes:
141
     *  - After parsing, the ParseContext is destroyed and 'decls' along with
141
     *  - After parsing, the ParseContext is destroyed and 'decls' along with
142
     *    it. Mostly, the emitter just uses the binding information stored in
142
     *    it. Mostly, the emitter just uses the binding information stored in
143
     *    the use/def nodes, but the emitter occasionally needs 'bindings' for
143
     *    the use/def nodes, but the emitter occasionally needs 'bindings' for
144
     *    various scope-related queries.
144
     *    various scope-related queries.
145
     *  - Bindings provide the initial js::Shape to use when creating a dynamic
145
     *  - Bindings provide the initial js::Shape to use when creating a dynamic
146
     *    scope object (js::CallObject) for the function. This shape is used
146
     *    scope object (js::CallObject) for the function. This shape is used
147
     *    during dynamic name lookup.
147
     *    during dynamic name lookup.
148
     *  - Sometimes a script's bindings are accessed at runtime to retrieve the
148
     *  - Sometimes a script's bindings are accessed at runtime to retrieve the
149
     *    contents of the lexical scope (e.g., from the debugger).
149
     *    contents of the lexical scope (e.g., from the debugger).
150
     */
150
     */
151
    bool generateFunctionBindings(JSContext *cx, InternalHandle<Bindings*> bindings) const;
151
    bool generateBindings(JSContext *cx, InternalHandle<Bindings*> bindings) const;
152
152
153
  public:
153
  public:
154
    ParseNode       *yieldNode;     /* parse node for a yield expression that might
154
    ParseNode       *yieldNode;     /* parse node for a yield expression that might
155
                                       be an error if we turn out to be inside a
155
                                       be an error if we turn out to be inside a
156
                                       generator expression */
156
                                       generator expression */
157
157
158
  private:
158
  private:
159
    ParseContext    **parserPC;     /* this points to the Parser's active pc
159
    ParseContext    **parserPC;     /* this points to the Parser's active pc
 Lines 373-388   struct Parser : private AutoGCRooter Link Here 
373
     * Parsers whose name has a '1' suffix leave the TokenStream state
373
     * Parsers whose name has a '1' suffix leave the TokenStream state
374
     * pointing to the token one past the end of the parsed fragment.  For a
374
     * pointing to the token one past the end of the parsed fragment.  For a
375
     * number of the parsers this is convenient and avoids a lot of
375
     * number of the parsers this is convenient and avoids a lot of
376
     * unnecessary ungetting and regetting of tokens.
376
     * unnecessary ungetting and regetting of tokens.
377
     *
377
     *
378
     * Some parsers have two versions:  an always-inlined version (with an 'i'
378
     * Some parsers have two versions:  an always-inlined version (with an 'i'
379
     * suffix) and a never-inlined version (with an 'n' suffix).
379
     * suffix) and a never-inlined version (with an 'n' suffix).
380
     */
380
     */
381
    ParseNode *moduleStmt();
381
    ParseNode *functionStmt();
382
    ParseNode *functionStmt();
382
    ParseNode *functionExpr();
383
    ParseNode *functionExpr();
383
    ParseNode *statements(bool *hasFunctionStmt = NULL);
384
    ParseNode *statements(bool *hasFunctionStmt = NULL);
384
385
385
    ParseNode *switchStatement();
386
    ParseNode *switchStatement();
386
    ParseNode *forStatement();
387
    ParseNode *forStatement();
387
    ParseNode *tryStatement();
388
    ParseNode *tryStatement();
388
    ParseNode *withStatement();
389
    ParseNode *withStatement();
 Lines 436-451   struct Parser : private AutoGCRooter Link Here 
436
437
437
    ParseNode *condition();
438
    ParseNode *condition();
438
    ParseNode *comprehensionTail(ParseNode *kid, unsigned blockid, bool isGenexp,
439
    ParseNode *comprehensionTail(ParseNode *kid, unsigned blockid, bool isGenexp,
439
                                 ParseNodeKind kind = PNK_SEMI, JSOp op = JSOP_NOP);
440
                                 ParseNodeKind kind = PNK_SEMI, JSOp op = JSOP_NOP);
440
    ParseNode *generatorExpr(ParseNode *kid);
441
    ParseNode *generatorExpr(ParseNode *kid);
441
    bool argumentList(ParseNode *listNode);
442
    bool argumentList(ParseNode *listNode);
442
    ParseNode *bracketedExpr();
443
    ParseNode *bracketedExpr();
443
    ParseNode *letBlock(LetContext letContext);
444
    ParseNode *letBlock(LetContext letContext);
445
    ParseNode *exportStatement();
444
    ParseNode *returnOrYield(bool useAssignExpr);
446
    ParseNode *returnOrYield(bool useAssignExpr);
445
    ParseNode *destructuringExpr(BindData *data, TokenKind tt);
447
    ParseNode *destructuringExpr(BindData *data, TokenKind tt);
446
448
447
    bool checkForFunctionNode(PropertyName *name, ParseNode *node);
449
    bool checkForFunctionNode(PropertyName *name, ParseNode *node);
448
450
449
    ParseNode *identifierName(bool afterDoubleDot);
451
    ParseNode *identifierName(bool afterDoubleDot);
450
452
451
#if JS_HAS_XML_SUPPORT
453
#if JS_HAS_XML_SUPPORT
(-)a/js/src/frontend/SharedContext.h (+1 lines)
Line     Link Here 
 Lines 227-242   class FunctionBox : public ObjectBox, pu Link Here 
227
 * STMT_WITH and STMT_CATCH, or you will break StmtInfoBase::linksScope. If you
227
 * STMT_WITH and STMT_CATCH, or you will break StmtInfoBase::linksScope. If you
228
 * add a non-looping statement type, add it before STMT_DO_LOOP or you will
228
 * add a non-looping statement type, add it before STMT_DO_LOOP or you will
229
 * break StmtInfoBase::isLoop().
229
 * break StmtInfoBase::isLoop().
230
 *
230
 *
231
 * Also remember to keep the statementName array in BytecodeEmitter.cpp in
231
 * Also remember to keep the statementName array in BytecodeEmitter.cpp in
232
 * sync.
232
 * sync.
233
 */
233
 */
234
enum StmtType {
234
enum StmtType {
235
    STMT_EXPORT,                /* export statement */
235
    STMT_LABEL,                 /* labeled statement:  L: s */
236
    STMT_LABEL,                 /* labeled statement:  L: s */
236
    STMT_IF,                    /* if (then) statement */
237
    STMT_IF,                    /* if (then) statement */
237
    STMT_ELSE,                  /* else clause of if statement */
238
    STMT_ELSE,                  /* else clause of if statement */
238
    STMT_SEQ,                   /* synthetic sequence of statements */
239
    STMT_SEQ,                   /* synthetic sequence of statements */
239
    STMT_BLOCK,                 /* compound statement: { s1[;... sN] } */
240
    STMT_BLOCK,                 /* compound statement: { s1[;... sN] } */
240
    STMT_SWITCH,                /* switch statement */
241
    STMT_SWITCH,                /* switch statement */
241
    STMT_WITH,                  /* with statement */
242
    STMT_WITH,                  /* with statement */
242
    STMT_CATCH,                 /* catch block */
243
    STMT_CATCH,                 /* catch block */
(-)a/js/src/js.msg (+4 lines)
Line     Link Here 
 Lines 383-390   MSG_DEF(JSMSG_INVALID_LANGUAGE_TAG, 32 Link Here 
383
MSG_DEF(JSMSG_INVALID_LOCALE_MATCHER, 330, 1, JSEXN_RANGEERR, "invalid locale matcher in supportedLocalesOf(): {0}")
383
MSG_DEF(JSMSG_INVALID_LOCALE_MATCHER, 330, 1, JSEXN_RANGEERR, "invalid locale matcher in supportedLocalesOf(): {0}")
384
MSG_DEF(JSMSG_INVALID_OPTION_VALUE,   331, 2, JSEXN_RANGEERR, "invalid value {1} for option {0}")
384
MSG_DEF(JSMSG_INVALID_OPTION_VALUE,   331, 2, JSEXN_RANGEERR, "invalid value {1} for option {0}")
385
MSG_DEF(JSMSG_INVALID_DIGITS_VALUE,   332, 1, JSEXN_RANGEERR, "invalid digits value: {0}")
385
MSG_DEF(JSMSG_INVALID_DIGITS_VALUE,   332, 1, JSEXN_RANGEERR, "invalid digits value: {0}")
386
MSG_DEF(JSMSG_INTL_OBJECT_REINITED,   333, 0, JSEXN_TYPEERR, "can't initialize object twice as an object of an Intl constructor")
386
MSG_DEF(JSMSG_INTL_OBJECT_REINITED,   333, 0, JSEXN_TYPEERR, "can't initialize object twice as an object of an Intl constructor")
387
MSG_DEF(JSMSG_INVALID_CURRENCY_CODE,  334, 1, JSEXN_RANGEERR, "invalid currency code in NumberFormat(): {0}")
387
MSG_DEF(JSMSG_INVALID_CURRENCY_CODE,  334, 1, JSEXN_RANGEERR, "invalid currency code in NumberFormat(): {0}")
388
MSG_DEF(JSMSG_UNDEFINED_CURRENCY,     335, 0, JSEXN_TYPEERR, "undefined currency in NumberFormat() with currency style")
388
MSG_DEF(JSMSG_UNDEFINED_CURRENCY,     335, 0, JSEXN_TYPEERR, "undefined currency in NumberFormat() with currency style")
389
MSG_DEF(JSMSG_INVALID_TIME_ZONE,      336, 1, JSEXN_RANGEERR, "invalid time zone in DateTimeFormat(): {0}")
389
MSG_DEF(JSMSG_INVALID_TIME_ZONE,      336, 1, JSEXN_RANGEERR, "invalid time zone in DateTimeFormat(): {0}")
390
MSG_DEF(JSMSG_DATE_NOT_FINITE,        337, 0, JSEXN_RANGEERR, "date value is not finite in DateTimeFormat.format()")
390
MSG_DEF(JSMSG_DATE_NOT_FINITE,        337, 0, JSEXN_RANGEERR, "date value is not finite in DateTimeFormat.format()")
391
MSG_DEF(JSMSG_MODULE_STATEMENT,       338, 0, JSEXN_SYNTAXERR, "modules may be declared only at top level or immediately within another module")
392
MSG_DEF(JSMSG_CURLY_BEFORE_MODULE,    339, 0, JSEXN_SYNTAXERR, "missing { before module body")
393
MSG_DEF(JSMSG_CURLY_AFTER_MODULE,     340, 0, JSEXN_SYNTAXERR, "missing } after module body")
394
MSG_DEF(JSMSG_EXPORT_STATEMENT,       341, 0, JSEXN_SYNTAXERR, "export statements may occur only within a module")
(-)a/js/src/jsatom.cpp (+1 lines)
Line     Link Here 
 Lines 47-62   const char * Link Here 
47
js_AtomToPrintableString(JSContext *cx, JSAtom *atom, JSAutoByteString *bytes)
47
js_AtomToPrintableString(JSContext *cx, JSAtom *atom, JSAutoByteString *bytes)
48
{
48
{
49
    return js_ValueToPrintable(cx, StringValue(atom), bytes);
49
    return js_ValueToPrintable(cx, StringValue(atom), bytes);
50
}
50
}
51
51
52
const char * js::TypeStrings[] = {
52
const char * js::TypeStrings[] = {
53
    js_undefined_str,
53
    js_undefined_str,
54
    js_object_str,
54
    js_object_str,
55
    js_module_str,
55
    js_function_str,
56
    js_function_str,
56
    js_string_str,
57
    js_string_str,
57
    js_number_str,
58
    js_number_str,
58
    js_boolean_str,
59
    js_boolean_str,
59
    js_null_str,
60
    js_null_str,
60
    js_xml_str,
61
    js_xml_str,
61
};
62
};
62
63
(-)a/js/src/jspubtd.h (+1 lines)
Line     Link Here 
 Lines 81-96   typedef enum JSVersion { Link Here 
81
    JSVERSION_UNKNOWN = -1,
81
    JSVERSION_UNKNOWN = -1,
82
    JSVERSION_LATEST  = JSVERSION_ECMA_5
82
    JSVERSION_LATEST  = JSVERSION_ECMA_5
83
} JSVersion;
83
} JSVersion;
84
84
85
/* Result of typeof operator enumeration. */
85
/* Result of typeof operator enumeration. */
86
typedef enum JSType {
86
typedef enum JSType {
87
    JSTYPE_VOID,                /* undefined */
87
    JSTYPE_VOID,                /* undefined */
88
    JSTYPE_OBJECT,              /* object */
88
    JSTYPE_OBJECT,              /* object */
89
    JSTYPE_MODULE,              /* module */
89
    JSTYPE_FUNCTION,            /* function */
90
    JSTYPE_FUNCTION,            /* function */
90
    JSTYPE_STRING,              /* string */
91
    JSTYPE_STRING,              /* string */
91
    JSTYPE_NUMBER,              /* number */
92
    JSTYPE_NUMBER,              /* number */
92
    JSTYPE_BOOLEAN,             /* boolean */
93
    JSTYPE_BOOLEAN,             /* boolean */
93
    JSTYPE_NULL,                /* null */
94
    JSTYPE_NULL,                /* null */
94
    JSTYPE_XML,                 /* xml object */
95
    JSTYPE_XML,                 /* xml object */
95
    JSTYPE_LIMIT
96
    JSTYPE_LIMIT
96
} JSType;
97
} JSType;
(-)a/js/src/vm/CommonPropertyNames.h (+1 lines)
Line     Link Here 
 Lines 144-159    Link Here 
144
    macro(valueOf, valueOf, "valueOf") \
144
    macro(valueOf, valueOf, "valueOf") \
145
    macro(var, var, "var") \
145
    macro(var, var, "var") \
146
    macro(void0, void0, "(void 0)") \
146
    macro(void0, void0, "(void 0)") \
147
    macro(watch, watch, "watch") \
147
    macro(watch, watch, "watch") \
148
    macro(writable, writable, "writable") \
148
    macro(writable, writable, "writable") \
149
    /* Type names must be contiguous and ordered; see js::TypeName. */ \
149
    /* Type names must be contiguous and ordered; see js::TypeName. */ \
150
    macro(undefined, undefined, "undefined") \
150
    macro(undefined, undefined, "undefined") \
151
    macro(object, object, "object") \
151
    macro(object, object, "object") \
152
    macro(module, module, "module") \
152
    macro(function, function, "function") \
153
    macro(function, function, "function") \
153
    macro(string, string, "string") \
154
    macro(string, string, "string") \
154
    macro(number, number, "number") \
155
    macro(number, number, "number") \
155
    macro(boolean, boolean, "boolean") \
156
    macro(boolean, boolean, "boolean") \
156
    macro(null, null, "null") \
157
    macro(null, null, "null") \
157
    macro(xml, xml, "xml") \
158
    macro(xml, xml, "xml") \
158
    FOR_EACH_XML_ONLY_NAME(macro)
159
    FOR_EACH_XML_ONLY_NAME(macro)
159
160
(-)a/js/src/vm/Keywords.h (-1 / +1 lines)
Line     Link Here 
 Lines 63-79    Link Here 
63
    macro(typeof, typeof, TOK_TYPEOF, JSOP_TYPEOF, JSVERSION_DEFAULT) \
63
    macro(typeof, typeof, TOK_TYPEOF, JSOP_TYPEOF, JSVERSION_DEFAULT) \
64
    macro(var, var, TOK_VAR, JSOP_DEFVAR, JSVERSION_DEFAULT) \
64
    macro(var, var, TOK_VAR, JSOP_DEFVAR, JSVERSION_DEFAULT) \
65
    macro(void, void_, TOK_VOID, JSOP_VOID, JSVERSION_DEFAULT) \
65
    macro(void, void_, TOK_VOID, JSOP_VOID, JSVERSION_DEFAULT) \
66
    macro(while, while_, TOK_WHILE, JSOP_NOP, JSVERSION_DEFAULT) \
66
    macro(while, while_, TOK_WHILE, JSOP_NOP, JSVERSION_DEFAULT) \
67
    macro(with, with, TOK_WITH, JSOP_NOP, JSVERSION_DEFAULT) \
67
    macro(with, with, TOK_WITH, JSOP_NOP, JSVERSION_DEFAULT) \
68
    /* ES5 reserved keywords reserved in all code. */ \
68
    /* ES5 reserved keywords reserved in all code. */ \
69
    macro(class, class_, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
69
    macro(class, class_, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
70
    macro(enum, enum_, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
70
    macro(enum, enum_, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
71
    macro(export, export, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
71
    macro(export, export, TOK_EXPORT, JSOP_NOP, JSVERSION_DEFAULT) \
72
    macro(extends, extends, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
72
    macro(extends, extends, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
73
    macro(import, import, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
73
    macro(import, import, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
74
    macro(super, super, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
74
    macro(super, super, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
75
    /* ES5 future reserved keywords in strict mode. */ \
75
    /* ES5 future reserved keywords in strict mode. */ \
76
    macro(implements, implements, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
76
    macro(implements, implements, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
77
    macro(interface, interface, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
77
    macro(interface, interface, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
78
    macro(package, package, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
78
    macro(package, package, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
79
    macro(private, private_, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \
79
    macro(private, private_, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \

Return to bug 568953