'use strict';
							 | 
						|
								
							 | 
						|
								const XHTMLEntities = require('./xhtml');
							 | 
						|
								
							 | 
						|
								const hexNumber = /^[\da-fA-F]+$/;
							 | 
						|
								const decimalNumber = /^\d+$/;
							 | 
						|
								
							 | 
						|
								// The map to `acorn-jsx` tokens from `acorn` namespace objects.
							 | 
						|
								const acornJsxMap = new WeakMap();
							 | 
						|
								
							 | 
						|
								// Get the original tokens for the given `acorn` namespace object.
							 | 
						|
								function getJsxTokens(acorn) {
							 | 
						|
								  acorn = acorn.Parser.acorn || acorn;
							 | 
						|
								  let acornJsx = acornJsxMap.get(acorn);
							 | 
						|
								  if (!acornJsx) {
							 | 
						|
								    const tt = acorn.tokTypes;
							 | 
						|
								    const TokContext = acorn.TokContext;
							 | 
						|
								    const TokenType = acorn.TokenType;
							 | 
						|
								    const tc_oTag = new TokContext('<tag', false);
							 | 
						|
								    const tc_cTag = new TokContext('</tag', false);
							 | 
						|
								    const tc_expr = new TokContext('<tag>...</tag>', true, true);
							 | 
						|
								    const tokContexts = {
							 | 
						|
								      tc_oTag: tc_oTag,
							 | 
						|
								      tc_cTag: tc_cTag,
							 | 
						|
								      tc_expr: tc_expr
							 | 
						|
								    };
							 | 
						|
								    const tokTypes = {
							 | 
						|
								      jsxName: new TokenType('jsxName'),
							 | 
						|
								      jsxText: new TokenType('jsxText', {beforeExpr: true}),
							 | 
						|
								      jsxTagStart: new TokenType('jsxTagStart', {startsExpr: true}),
							 | 
						|
								      jsxTagEnd: new TokenType('jsxTagEnd')
							 | 
						|
								    };
							 | 
						|
								
							 | 
						|
								    tokTypes.jsxTagStart.updateContext = function() {
							 | 
						|
								      this.context.push(tc_expr); // treat as beginning of JSX expression
							 | 
						|
								      this.context.push(tc_oTag); // start opening tag context
							 | 
						|
								      this.exprAllowed = false;
							 | 
						|
								    };
							 | 
						|
								    tokTypes.jsxTagEnd.updateContext = function(prevType) {
							 | 
						|
								      let out = this.context.pop();
							 | 
						|
								      if (out === tc_oTag && prevType === tt.slash || out === tc_cTag) {
							 | 
						|
								        this.context.pop();
							 | 
						|
								        this.exprAllowed = this.curContext() === tc_expr;
							 | 
						|
								      } else {
							 | 
						|
								        this.exprAllowed = true;
							 | 
						|
								      }
							 | 
						|
								    };
							 | 
						|
								
							 | 
						|
								    acornJsx = { tokContexts: tokContexts, tokTypes: tokTypes };
							 | 
						|
								    acornJsxMap.set(acorn, acornJsx);
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  return acornJsx;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Transforms JSX element name to string.
							 | 
						|
								
							 | 
						|
								function getQualifiedJSXName(object) {
							 | 
						|
								  if (!object)
							 | 
						|
								    return object;
							 | 
						|
								
							 | 
						|
								  if (object.type === 'JSXIdentifier')
							 | 
						|
								    return object.name;
							 | 
						|
								
							 | 
						|
								  if (object.type === 'JSXNamespacedName')
							 | 
						|
								    return object.namespace.name + ':' + object.name.name;
							 | 
						|
								
							 | 
						|
								  if (object.type === 'JSXMemberExpression')
							 | 
						|
								    return getQualifiedJSXName(object.object) + '.' +
							 | 
						|
								    getQualifiedJSXName(object.property);
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								module.exports = function(options) {
							 | 
						|
								  options = options || {};
							 | 
						|
								  return function(Parser) {
							 | 
						|
								    return plugin({
							 | 
						|
								      allowNamespaces: options.allowNamespaces !== false,
							 | 
						|
								      allowNamespacedObjects: !!options.allowNamespacedObjects
							 | 
						|
								    }, Parser);
							 | 
						|
								  };
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								// This is `tokTypes` of the peer dep.
							 | 
						|
								// This can be different instances from the actual `tokTypes` this plugin uses.
							 | 
						|
								Object.defineProperty(module.exports, "tokTypes", {
							 | 
						|
								  get: function get_tokTypes() {
							 | 
						|
								    return getJsxTokens(require("acorn")).tokTypes;
							 | 
						|
								  },
							 | 
						|
								  configurable: true,
							 | 
						|
								  enumerable: true
							 | 
						|
								});
							 | 
						|
								
							 | 
						|
								function plugin(options, Parser) {
							 | 
						|
								  const acorn = Parser.acorn || require("acorn");
							 | 
						|
								  const acornJsx = getJsxTokens(acorn);
							 | 
						|
								  const tt = acorn.tokTypes;
							 | 
						|
								  const tok = acornJsx.tokTypes;
							 | 
						|
								  const tokContexts = acorn.tokContexts;
							 | 
						|
								  const tc_oTag = acornJsx.tokContexts.tc_oTag;
							 | 
						|
								  const tc_cTag = acornJsx.tokContexts.tc_cTag;
							 | 
						|
								  const tc_expr = acornJsx.tokContexts.tc_expr;
							 | 
						|
								  const isNewLine = acorn.isNewLine;
							 | 
						|
								  const isIdentifierStart = acorn.isIdentifierStart;
							 | 
						|
								  const isIdentifierChar = acorn.isIdentifierChar;
							 | 
						|
								
							 | 
						|
								  return class extends Parser {
							 | 
						|
								    // Expose actual `tokTypes` and `tokContexts` to other plugins.
							 | 
						|
								    static get acornJsx() {
							 | 
						|
								      return acornJsx;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Reads inline JSX contents token.
							 | 
						|
								    jsx_readToken() {
							 | 
						|
								      let out = '', chunkStart = this.pos;
							 | 
						|
								      for (;;) {
							 | 
						|
								        if (this.pos >= this.input.length)
							 | 
						|
								          this.raise(this.start, 'Unterminated JSX contents');
							 | 
						|
								        let ch = this.input.charCodeAt(this.pos);
							 | 
						|
								
							 | 
						|
								        switch (ch) {
							 | 
						|
								        case 60: // '<'
							 | 
						|
								        case 123: // '{'
							 | 
						|
								          if (this.pos === this.start) {
							 | 
						|
								            if (ch === 60 && this.exprAllowed) {
							 | 
						|
								              ++this.pos;
							 | 
						|
								              return this.finishToken(tok.jsxTagStart);
							 | 
						|
								            }
							 | 
						|
								            return this.getTokenFromCode(ch);
							 | 
						|
								          }
							 | 
						|
								          out += this.input.slice(chunkStart, this.pos);
							 | 
						|
								          return this.finishToken(tok.jsxText, out);
							 | 
						|
								
							 | 
						|
								        case 38: // '&'
							 | 
						|
								          out += this.input.slice(chunkStart, this.pos);
							 | 
						|
								          out += this.jsx_readEntity();
							 | 
						|
								          chunkStart = this.pos;
							 | 
						|
								          break;
							 | 
						|
								
							 | 
						|
								        case 62: // '>'
							 | 
						|
								        case 125: // '}'
							 | 
						|
								          this.raise(
							 | 
						|
								            this.pos,
							 | 
						|
								            "Unexpected token `" + this.input[this.pos] + "`. Did you mean `" +
							 | 
						|
								              (ch === 62 ? ">" : "}") + "` or " + "`{\"" + this.input[this.pos] + "\"}" + "`?"
							 | 
						|
								          );
							 | 
						|
								
							 | 
						|
								        default:
							 | 
						|
								          if (isNewLine(ch)) {
							 | 
						|
								            out += this.input.slice(chunkStart, this.pos);
							 | 
						|
								            out += this.jsx_readNewLine(true);
							 | 
						|
								            chunkStart = this.pos;
							 | 
						|
								          } else {
							 | 
						|
								            ++this.pos;
							 | 
						|
								          }
							 | 
						|
								        }
							 | 
						|
								      }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    jsx_readNewLine(normalizeCRLF) {
							 | 
						|
								      let ch = this.input.charCodeAt(this.pos);
							 | 
						|
								      let out;
							 | 
						|
								      ++this.pos;
							 | 
						|
								      if (ch === 13 && this.input.charCodeAt(this.pos) === 10) {
							 | 
						|
								        ++this.pos;
							 | 
						|
								        out = normalizeCRLF ? '\n' : '\r\n';
							 | 
						|
								      } else {
							 | 
						|
								        out = String.fromCharCode(ch);
							 | 
						|
								      }
							 | 
						|
								      if (this.options.locations) {
							 | 
						|
								        ++this.curLine;
							 | 
						|
								        this.lineStart = this.pos;
							 | 
						|
								      }
							 | 
						|
								
							 | 
						|
								      return out;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    jsx_readString(quote) {
							 | 
						|
								      let out = '', chunkStart = ++this.pos;
							 | 
						|
								      for (;;) {
							 | 
						|
								        if (this.pos >= this.input.length)
							 | 
						|
								          this.raise(this.start, 'Unterminated string constant');
							 | 
						|
								        let ch = this.input.charCodeAt(this.pos);
							 | 
						|
								        if (ch === quote) break;
							 | 
						|
								        if (ch === 38) { // '&'
							 | 
						|
								          out += this.input.slice(chunkStart, this.pos);
							 | 
						|
								          out += this.jsx_readEntity();
							 | 
						|
								          chunkStart = this.pos;
							 | 
						|
								        } else if (isNewLine(ch)) {
							 | 
						|
								          out += this.input.slice(chunkStart, this.pos);
							 | 
						|
								          out += this.jsx_readNewLine(false);
							 | 
						|
								          chunkStart = this.pos;
							 | 
						|
								        } else {
							 | 
						|
								          ++this.pos;
							 | 
						|
								        }
							 | 
						|
								      }
							 | 
						|
								      out += this.input.slice(chunkStart, this.pos++);
							 | 
						|
								      return this.finishToken(tt.string, out);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    jsx_readEntity() {
							 | 
						|
								      let str = '', count = 0, entity;
							 | 
						|
								      let ch = this.input[this.pos];
							 | 
						|
								      if (ch !== '&')
							 | 
						|
								        this.raise(this.pos, 'Entity must start with an ampersand');
							 | 
						|
								      let startPos = ++this.pos;
							 | 
						|
								      while (this.pos < this.input.length && count++ < 10) {
							 | 
						|
								        ch = this.input[this.pos++];
							 | 
						|
								        if (ch === ';') {
							 | 
						|
								          if (str[0] === '#') {
							 | 
						|
								            if (str[1] === 'x') {
							 | 
						|
								              str = str.substr(2);
							 | 
						|
								              if (hexNumber.test(str))
							 | 
						|
								                entity = String.fromCharCode(parseInt(str, 16));
							 | 
						|
								            } else {
							 | 
						|
								              str = str.substr(1);
							 | 
						|
								              if (decimalNumber.test(str))
							 | 
						|
								                entity = String.fromCharCode(parseInt(str, 10));
							 | 
						|
								            }
							 | 
						|
								          } else {
							 | 
						|
								            entity = XHTMLEntities[str];
							 | 
						|
								          }
							 | 
						|
								          break;
							 | 
						|
								        }
							 | 
						|
								        str += ch;
							 | 
						|
								      }
							 | 
						|
								      if (!entity) {
							 | 
						|
								        this.pos = startPos;
							 | 
						|
								        return '&';
							 | 
						|
								      }
							 | 
						|
								      return entity;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Read a JSX identifier (valid tag or attribute name).
							 | 
						|
								    //
							 | 
						|
								    // Optimized version since JSX identifiers can't contain
							 | 
						|
								    // escape characters and so can be read as single slice.
							 | 
						|
								    // Also assumes that first character was already checked
							 | 
						|
								    // by isIdentifierStart in readToken.
							 | 
						|
								
							 | 
						|
								    jsx_readWord() {
							 | 
						|
								      let ch, start = this.pos;
							 | 
						|
								      do {
							 | 
						|
								        ch = this.input.charCodeAt(++this.pos);
							 | 
						|
								      } while (isIdentifierChar(ch) || ch === 45); // '-'
							 | 
						|
								      return this.finishToken(tok.jsxName, this.input.slice(start, this.pos));
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Parse next token as JSX identifier
							 | 
						|
								
							 | 
						|
								    jsx_parseIdentifier() {
							 | 
						|
								      let node = this.startNode();
							 | 
						|
								      if (this.type === tok.jsxName)
							 | 
						|
								        node.name = this.value;
							 | 
						|
								      else if (this.type.keyword)
							 | 
						|
								        node.name = this.type.keyword;
							 | 
						|
								      else
							 | 
						|
								        this.unexpected();
							 | 
						|
								      this.next();
							 | 
						|
								      return this.finishNode(node, 'JSXIdentifier');
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Parse namespaced identifier.
							 | 
						|
								
							 | 
						|
								    jsx_parseNamespacedName() {
							 | 
						|
								      let startPos = this.start, startLoc = this.startLoc;
							 | 
						|
								      let name = this.jsx_parseIdentifier();
							 | 
						|
								      if (!options.allowNamespaces || !this.eat(tt.colon)) return name;
							 | 
						|
								      var node = this.startNodeAt(startPos, startLoc);
							 | 
						|
								      node.namespace = name;
							 | 
						|
								      node.name = this.jsx_parseIdentifier();
							 | 
						|
								      return this.finishNode(node, 'JSXNamespacedName');
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Parses element name in any form - namespaced, member
							 | 
						|
								    // or single identifier.
							 | 
						|
								
							 | 
						|
								    jsx_parseElementName() {
							 | 
						|
								      if (this.type === tok.jsxTagEnd) return '';
							 | 
						|
								      let startPos = this.start, startLoc = this.startLoc;
							 | 
						|
								      let node = this.jsx_parseNamespacedName();
							 | 
						|
								      if (this.type === tt.dot && node.type === 'JSXNamespacedName' && !options.allowNamespacedObjects) {
							 | 
						|
								        this.unexpected();
							 | 
						|
								      }
							 | 
						|
								      while (this.eat(tt.dot)) {
							 | 
						|
								        let newNode = this.startNodeAt(startPos, startLoc);
							 | 
						|
								        newNode.object = node;
							 | 
						|
								        newNode.property = this.jsx_parseIdentifier();
							 | 
						|
								        node = this.finishNode(newNode, 'JSXMemberExpression');
							 | 
						|
								      }
							 | 
						|
								      return node;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Parses any type of JSX attribute value.
							 | 
						|
								
							 | 
						|
								    jsx_parseAttributeValue() {
							 | 
						|
								      switch (this.type) {
							 | 
						|
								      case tt.braceL:
							 | 
						|
								        let node = this.jsx_parseExpressionContainer();
							 | 
						|
								        if (node.expression.type === 'JSXEmptyExpression')
							 | 
						|
								          this.raise(node.start, 'JSX attributes must only be assigned a non-empty expression');
							 | 
						|
								        return node;
							 | 
						|
								
							 | 
						|
								      case tok.jsxTagStart:
							 | 
						|
								      case tt.string:
							 | 
						|
								        return this.parseExprAtom();
							 | 
						|
								
							 | 
						|
								      default:
							 | 
						|
								        this.raise(this.start, 'JSX value should be either an expression or a quoted JSX text');
							 | 
						|
								      }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // JSXEmptyExpression is unique type since it doesn't actually parse anything,
							 | 
						|
								    // and so it should start at the end of last read token (left brace) and finish
							 | 
						|
								    // at the beginning of the next one (right brace).
							 | 
						|
								
							 | 
						|
								    jsx_parseEmptyExpression() {
							 | 
						|
								      let node = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc);
							 | 
						|
								      return this.finishNodeAt(node, 'JSXEmptyExpression', this.start, this.startLoc);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Parses JSX expression enclosed into curly brackets.
							 | 
						|
								
							 | 
						|
								    jsx_parseExpressionContainer() {
							 | 
						|
								      let node = this.startNode();
							 | 
						|
								      this.next();
							 | 
						|
								      node.expression = this.type === tt.braceR
							 | 
						|
								        ? this.jsx_parseEmptyExpression()
							 | 
						|
								        : this.parseExpression();
							 | 
						|
								      this.expect(tt.braceR);
							 | 
						|
								      return this.finishNode(node, 'JSXExpressionContainer');
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Parses following JSX attribute name-value pair.
							 | 
						|
								
							 | 
						|
								    jsx_parseAttribute() {
							 | 
						|
								      let node = this.startNode();
							 | 
						|
								      if (this.eat(tt.braceL)) {
							 | 
						|
								        this.expect(tt.ellipsis);
							 | 
						|
								        node.argument = this.parseMaybeAssign();
							 | 
						|
								        this.expect(tt.braceR);
							 | 
						|
								        return this.finishNode(node, 'JSXSpreadAttribute');
							 | 
						|
								      }
							 | 
						|
								      node.name = this.jsx_parseNamespacedName();
							 | 
						|
								      node.value = this.eat(tt.eq) ? this.jsx_parseAttributeValue() : null;
							 | 
						|
								      return this.finishNode(node, 'JSXAttribute');
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Parses JSX opening tag starting after '<'.
							 | 
						|
								
							 | 
						|
								    jsx_parseOpeningElementAt(startPos, startLoc) {
							 | 
						|
								      let node = this.startNodeAt(startPos, startLoc);
							 | 
						|
								      node.attributes = [];
							 | 
						|
								      let nodeName = this.jsx_parseElementName();
							 | 
						|
								      if (nodeName) node.name = nodeName;
							 | 
						|
								      while (this.type !== tt.slash && this.type !== tok.jsxTagEnd)
							 | 
						|
								        node.attributes.push(this.jsx_parseAttribute());
							 | 
						|
								      node.selfClosing = this.eat(tt.slash);
							 | 
						|
								      this.expect(tok.jsxTagEnd);
							 | 
						|
								      return this.finishNode(node, nodeName ? 'JSXOpeningElement' : 'JSXOpeningFragment');
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Parses JSX closing tag starting after '</'.
							 | 
						|
								
							 | 
						|
								    jsx_parseClosingElementAt(startPos, startLoc) {
							 | 
						|
								      let node = this.startNodeAt(startPos, startLoc);
							 | 
						|
								      let nodeName = this.jsx_parseElementName();
							 | 
						|
								      if (nodeName) node.name = nodeName;
							 | 
						|
								      this.expect(tok.jsxTagEnd);
							 | 
						|
								      return this.finishNode(node, nodeName ? 'JSXClosingElement' : 'JSXClosingFragment');
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Parses entire JSX element, including it's opening tag
							 | 
						|
								    // (starting after '<'), attributes, contents and closing tag.
							 | 
						|
								
							 | 
						|
								    jsx_parseElementAt(startPos, startLoc) {
							 | 
						|
								      let node = this.startNodeAt(startPos, startLoc);
							 | 
						|
								      let children = [];
							 | 
						|
								      let openingElement = this.jsx_parseOpeningElementAt(startPos, startLoc);
							 | 
						|
								      let closingElement = null;
							 | 
						|
								
							 | 
						|
								      if (!openingElement.selfClosing) {
							 | 
						|
								        contents: for (;;) {
							 | 
						|
								          switch (this.type) {
							 | 
						|
								          case tok.jsxTagStart:
							 | 
						|
								            startPos = this.start; startLoc = this.startLoc;
							 | 
						|
								            this.next();
							 | 
						|
								            if (this.eat(tt.slash)) {
							 | 
						|
								              closingElement = this.jsx_parseClosingElementAt(startPos, startLoc);
							 | 
						|
								              break contents;
							 | 
						|
								            }
							 | 
						|
								            children.push(this.jsx_parseElementAt(startPos, startLoc));
							 | 
						|
								            break;
							 | 
						|
								
							 | 
						|
								          case tok.jsxText:
							 | 
						|
								            children.push(this.parseExprAtom());
							 | 
						|
								            break;
							 | 
						|
								
							 | 
						|
								          case tt.braceL:
							 | 
						|
								            children.push(this.jsx_parseExpressionContainer());
							 | 
						|
								            break;
							 | 
						|
								
							 | 
						|
								          default:
							 | 
						|
								            this.unexpected();
							 | 
						|
								          }
							 | 
						|
								        }
							 | 
						|
								        if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) {
							 | 
						|
								          this.raise(
							 | 
						|
								            closingElement.start,
							 | 
						|
								            'Expected corresponding JSX closing tag for <' + getQualifiedJSXName(openingElement.name) + '>');
							 | 
						|
								        }
							 | 
						|
								      }
							 | 
						|
								      let fragmentOrElement = openingElement.name ? 'Element' : 'Fragment';
							 | 
						|
								
							 | 
						|
								      node['opening' + fragmentOrElement] = openingElement;
							 | 
						|
								      node['closing' + fragmentOrElement] = closingElement;
							 | 
						|
								      node.children = children;
							 | 
						|
								      if (this.type === tt.relational && this.value === "<") {
							 | 
						|
								        this.raise(this.start, "Adjacent JSX elements must be wrapped in an enclosing tag");
							 | 
						|
								      }
							 | 
						|
								      return this.finishNode(node, 'JSX' + fragmentOrElement);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Parse JSX text
							 | 
						|
								
							 | 
						|
								    jsx_parseText() {
							 | 
						|
								      let node = this.parseLiteral(this.value);
							 | 
						|
								      node.type = "JSXText";
							 | 
						|
								      return node;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Parses entire JSX element from current position.
							 | 
						|
								
							 | 
						|
								    jsx_parseElement() {
							 | 
						|
								      let startPos = this.start, startLoc = this.startLoc;
							 | 
						|
								      this.next();
							 | 
						|
								      return this.jsx_parseElementAt(startPos, startLoc);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    parseExprAtom(refShortHandDefaultPos) {
							 | 
						|
								      if (this.type === tok.jsxText)
							 | 
						|
								        return this.jsx_parseText();
							 | 
						|
								      else if (this.type === tok.jsxTagStart)
							 | 
						|
								        return this.jsx_parseElement();
							 | 
						|
								      else
							 | 
						|
								        return super.parseExprAtom(refShortHandDefaultPos);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    readToken(code) {
							 | 
						|
								      let context = this.curContext();
							 | 
						|
								
							 | 
						|
								      if (context === tc_expr) return this.jsx_readToken();
							 | 
						|
								
							 | 
						|
								      if (context === tc_oTag || context === tc_cTag) {
							 | 
						|
								        if (isIdentifierStart(code)) return this.jsx_readWord();
							 | 
						|
								
							 | 
						|
								        if (code == 62) {
							 | 
						|
								          ++this.pos;
							 | 
						|
								          return this.finishToken(tok.jsxTagEnd);
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        if ((code === 34 || code === 39) && context == tc_oTag)
							 | 
						|
								          return this.jsx_readString(code);
							 | 
						|
								      }
							 | 
						|
								
							 | 
						|
								      if (code === 60 && this.exprAllowed && this.input.charCodeAt(this.pos + 1) !== 33) {
							 | 
						|
								        ++this.pos;
							 | 
						|
								        return this.finishToken(tok.jsxTagStart);
							 | 
						|
								      }
							 | 
						|
								      return super.readToken(code);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    updateContext(prevType) {
							 | 
						|
								      if (this.type == tt.braceL) {
							 | 
						|
								        var curContext = this.curContext();
							 | 
						|
								        if (curContext == tc_oTag) this.context.push(tokContexts.b_expr);
							 | 
						|
								        else if (curContext == tc_expr) this.context.push(tokContexts.b_tmpl);
							 | 
						|
								        else super.updateContext(prevType);
							 | 
						|
								        this.exprAllowed = true;
							 | 
						|
								      } else if (this.type === tt.slash && prevType === tok.jsxTagStart) {
							 | 
						|
								        this.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore
							 | 
						|
								        this.context.push(tc_cTag); // reconsider as closing tag context
							 | 
						|
								        this.exprAllowed = false;
							 | 
						|
								      } else {
							 | 
						|
								        return super.updateContext(prevType);
							 | 
						|
								      }
							 | 
						|
								    }
							 | 
						|
								  };
							 | 
						|
								}
							 |