PageRenderTime 79ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/dist/qunit/blanket.js

https://github.com/morkai/blanket
JavaScript | 4300 lines | 3448 code | 671 blank | 181 comment | 631 complexity | 66591ef832801d558c208a22efdd158a MD5 | raw file
Possible License(s): MIT
  1. /*---------------------------------*/
  2. /* */
  3. /*---------------------------------*/
  4. /* Blanket.js */
  5. /* version 0.9.5 alpha */
  6. /* See README.md for revision news */
  7. /*---------------------------------*/
  8. /* */
  9. /*-------------------------------*/
  10. /* Stop autorunning of tests */
  11. if (typeof QUnit !== 'undefined'){ QUnit.config.autostart = false; }
  12. /* Esprima Code */
  13. /*
  14. Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
  15. Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
  16. Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
  17. Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
  18. Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
  19. Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
  20. Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
  21. Redistribution and use in source and binary forms, with or without
  22. modification, are permitted provided that the following conditions are met:
  23. * Redistributions of source code must retain the above copyright
  24. notice, this list of conditions and the following disclaimer.
  25. * Redistributions in binary form must reproduce the above copyright
  26. notice, this list of conditions and the following disclaimer in the
  27. documentation and/or other materials provided with the distribution.
  28. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  29. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31. ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  32. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  33. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  35. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  36. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  37. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. */
  39. /*jslint bitwise:true plusplus:true */
  40. /*global esprima:true, define:true, exports:true, window: true,
  41. throwError: true, generateStatement: true, peek: true,
  42. parseAssignmentExpression: true, parseBlock: true, parseExpression: true,
  43. parseFunctionDeclaration: true, parseFunctionExpression: true,
  44. parseFunctionSourceElements: true, parseVariableIdentifier: true,
  45. parseLeftHandSideExpression: true,
  46. parseStatement: true, parseSourceElement: true */
  47. (function (exports) {
  48. 'use strict';
  49. var Token,
  50. TokenName,
  51. Syntax,
  52. PropertyKind,
  53. Messages,
  54. Regex,
  55. SyntaxTreeDelegate,
  56. source,
  57. strict,
  58. index,
  59. lineNumber,
  60. lineStart,
  61. length,
  62. delegate,
  63. lookahead,
  64. state,
  65. extra;
  66. Token = {
  67. BooleanLiteral: 1,
  68. EOF: 2,
  69. Identifier: 3,
  70. Keyword: 4,
  71. NullLiteral: 5,
  72. NumericLiteral: 6,
  73. Punctuator: 7,
  74. StringLiteral: 8
  75. };
  76. TokenName = {};
  77. TokenName[Token.BooleanLiteral] = 'Boolean';
  78. TokenName[Token.EOF] = '<end>';
  79. TokenName[Token.Identifier] = 'Identifier';
  80. TokenName[Token.Keyword] = 'Keyword';
  81. TokenName[Token.NullLiteral] = 'Null';
  82. TokenName[Token.NumericLiteral] = 'Numeric';
  83. TokenName[Token.Punctuator] = 'Punctuator';
  84. TokenName[Token.StringLiteral] = 'String';
  85. Syntax = {
  86. AssignmentExpression: 'AssignmentExpression',
  87. ArrayExpression: 'ArrayExpression',
  88. BlockStatement: 'BlockStatement',
  89. BinaryExpression: 'BinaryExpression',
  90. BreakStatement: 'BreakStatement',
  91. CallExpression: 'CallExpression',
  92. CatchClause: 'CatchClause',
  93. ConditionalExpression: 'ConditionalExpression',
  94. ContinueStatement: 'ContinueStatement',
  95. DoWhileStatement: 'DoWhileStatement',
  96. DebuggerStatement: 'DebuggerStatement',
  97. EmptyStatement: 'EmptyStatement',
  98. ExpressionStatement: 'ExpressionStatement',
  99. ForStatement: 'ForStatement',
  100. ForInStatement: 'ForInStatement',
  101. FunctionDeclaration: 'FunctionDeclaration',
  102. FunctionExpression: 'FunctionExpression',
  103. Identifier: 'Identifier',
  104. IfStatement: 'IfStatement',
  105. Literal: 'Literal',
  106. LabeledStatement: 'LabeledStatement',
  107. LogicalExpression: 'LogicalExpression',
  108. MemberExpression: 'MemberExpression',
  109. NewExpression: 'NewExpression',
  110. ObjectExpression: 'ObjectExpression',
  111. Program: 'Program',
  112. Property: 'Property',
  113. ReturnStatement: 'ReturnStatement',
  114. SequenceExpression: 'SequenceExpression',
  115. SwitchStatement: 'SwitchStatement',
  116. SwitchCase: 'SwitchCase',
  117. ThisExpression: 'ThisExpression',
  118. ThrowStatement: 'ThrowStatement',
  119. TryStatement: 'TryStatement',
  120. UnaryExpression: 'UnaryExpression',
  121. UpdateExpression: 'UpdateExpression',
  122. VariableDeclaration: 'VariableDeclaration',
  123. VariableDeclarator: 'VariableDeclarator',
  124. WhileStatement: 'WhileStatement',
  125. WithStatement: 'WithStatement'
  126. };
  127. PropertyKind = {
  128. Data: 1,
  129. Get: 2,
  130. Set: 4
  131. };
  132. // Error messages should be identical to V8.
  133. Messages = {
  134. UnexpectedToken: 'Unexpected token %0',
  135. UnexpectedNumber: 'Unexpected number',
  136. UnexpectedString: 'Unexpected string',
  137. UnexpectedIdentifier: 'Unexpected identifier',
  138. UnexpectedReserved: 'Unexpected reserved word',
  139. UnexpectedEOS: 'Unexpected end of input',
  140. NewlineAfterThrow: 'Illegal newline after throw',
  141. InvalidRegExp: 'Invalid regular expression',
  142. UnterminatedRegExp: 'Invalid regular expression: missing /',
  143. InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
  144. InvalidLHSInForIn: 'Invalid left-hand side in for-in',
  145. MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
  146. NoCatchOrFinally: 'Missing catch or finally after try',
  147. UnknownLabel: 'Undefined label \'%0\'',
  148. Redeclaration: '%0 \'%1\' has already been declared',
  149. IllegalContinue: 'Illegal continue statement',
  150. IllegalBreak: 'Illegal break statement',
  151. IllegalReturn: 'Illegal return statement',
  152. StrictModeWith: 'Strict mode code may not include a with statement',
  153. StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
  154. StrictVarName: 'Variable name may not be eval or arguments in strict mode',
  155. StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
  156. StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
  157. StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
  158. StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
  159. StrictDelete: 'Delete of an unqualified identifier in strict mode.',
  160. StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode',
  161. AccessorDataProperty: 'Object literal may not have data and accessor property with the same name',
  162. AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name',
  163. StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
  164. StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
  165. StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
  166. StrictReservedWord: 'Use of future reserved word in strict mode'
  167. };
  168. // See also tools/generate-unicode-regex.py.
  169. Regex = {
  170. NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'),
  171. NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]')
  172. };
  173. // Ensure the condition is true, otherwise throw an error.
  174. // This is only to have a better contract semantic, i.e. another safety net
  175. // to catch a logic error. The condition shall be fulfilled in normal case.
  176. // Do NOT use this to enforce a certain condition on any user input.
  177. function assert(condition, message) {
  178. if (!condition) {
  179. throw new Error('ASSERT: ' + message);
  180. }
  181. }
  182. function sliceSource(from, to) {
  183. return source.slice(from, to);
  184. }
  185. if (typeof 'esprima'[0] === 'undefined') {
  186. sliceSource = function sliceArraySource(from, to) {
  187. return source.slice(from, to).join('');
  188. };
  189. }
  190. function isDecimalDigit(ch) {
  191. return '0123456789'.indexOf(ch) >= 0;
  192. }
  193. function isHexDigit(ch) {
  194. return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
  195. }
  196. function isOctalDigit(ch) {
  197. return '01234567'.indexOf(ch) >= 0;
  198. }
  199. // 7.2 White Space
  200. function isWhiteSpace(ch) {
  201. return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') ||
  202. (ch === '\u000C') || (ch === '\u00A0') ||
  203. (ch.charCodeAt(0) >= 0x1680 &&
  204. '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0);
  205. }
  206. // 7.3 Line Terminators
  207. function isLineTerminator(ch) {
  208. return (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029');
  209. }
  210. // 7.6 Identifier Names and Identifiers
  211. function isIdentifierStart(ch) {
  212. return (ch === '$') || (ch === '_') || (ch === '\\') ||
  213. (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
  214. ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch));
  215. }
  216. function isIdentifierPart(ch) {
  217. return (ch === '$') || (ch === '_') || (ch === '\\') ||
  218. (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
  219. ((ch >= '0') && (ch <= '9')) ||
  220. ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));
  221. }
  222. // 7.6.1.2 Future Reserved Words
  223. function isFutureReservedWord(id) {
  224. return ['class', 'enum', 'export', 'extends', 'import', 'super'].
  225. indexOf(id) >= 0;
  226. }
  227. function isStrictModeReservedWord(id) {
  228. return ['implements', 'interface', 'package', 'private', 'protected',
  229. 'public', 'static', 'yield', 'let'].indexOf(id) >= 0;
  230. }
  231. function isRestrictedWord(id) {
  232. return id === 'eval' || id === 'arguments';
  233. }
  234. // 7.6.1.1 Keywords
  235. function isKeyword(id) {
  236. if (strict && isStrictModeReservedWord(id)) {
  237. return true;
  238. }
  239. // 'const' is specialized as Keyword in V8.
  240. // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next.
  241. // Some others are from future reserved words.
  242. switch (id.length) {
  243. case 2:
  244. return (id === 'if') || (id === 'in') || (id === 'do');
  245. case 3:
  246. return (id === 'var') || (id === 'for') || (id === 'new') ||
  247. (id === 'try') || (id === 'let');
  248. case 4:
  249. return (id === 'this') || (id === 'else') || (id === 'case') ||
  250. (id === 'void') || (id === 'with') || (id === 'enum');
  251. case 5:
  252. return (id === 'while') || (id === 'break') || (id === 'catch') ||
  253. (id === 'throw') || (id === 'const') || (id === 'yield') ||
  254. (id === 'class') || (id === 'super');
  255. case 6:
  256. return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
  257. (id === 'switch') || (id === 'export') || (id === 'import');
  258. case 7:
  259. return (id === 'default') || (id === 'finally') || (id === 'extends');
  260. case 8:
  261. return (id === 'function') || (id === 'continue') || (id === 'debugger');
  262. case 10:
  263. return (id === 'instanceof');
  264. default:
  265. return false;
  266. }
  267. }
  268. // 7.4 Comments
  269. function skipComment() {
  270. var ch, blockComment, lineComment;
  271. blockComment = false;
  272. lineComment = false;
  273. while (index < length) {
  274. ch = source[index];
  275. if (lineComment) {
  276. ch = source[index++];
  277. if (isLineTerminator(ch)) {
  278. lineComment = false;
  279. if (ch === '\r' && source[index] === '\n') {
  280. ++index;
  281. }
  282. ++lineNumber;
  283. lineStart = index;
  284. }
  285. } else if (blockComment) {
  286. if (isLineTerminator(ch)) {
  287. if (ch === '\r' && source[index + 1] === '\n') {
  288. ++index;
  289. }
  290. ++lineNumber;
  291. ++index;
  292. lineStart = index;
  293. if (index >= length) {
  294. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  295. }
  296. } else {
  297. ch = source[index++];
  298. if (index >= length) {
  299. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  300. }
  301. if (ch === '*') {
  302. ch = source[index];
  303. if (ch === '/') {
  304. ++index;
  305. blockComment = false;
  306. }
  307. }
  308. }
  309. } else if (ch === '/') {
  310. ch = source[index + 1];
  311. if (ch === '/') {
  312. index += 2;
  313. lineComment = true;
  314. } else if (ch === '*') {
  315. index += 2;
  316. blockComment = true;
  317. if (index >= length) {
  318. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  319. }
  320. } else {
  321. break;
  322. }
  323. } else if (isWhiteSpace(ch)) {
  324. ++index;
  325. } else if (isLineTerminator(ch)) {
  326. ++index;
  327. if (ch === '\r' && source[index] === '\n') {
  328. ++index;
  329. }
  330. ++lineNumber;
  331. lineStart = index;
  332. } else {
  333. break;
  334. }
  335. }
  336. }
  337. function scanHexEscape(prefix) {
  338. var i, len, ch, code = 0;
  339. len = (prefix === 'u') ? 4 : 2;
  340. for (i = 0; i < len; ++i) {
  341. if (index < length && isHexDigit(source[index])) {
  342. ch = source[index++];
  343. code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
  344. } else {
  345. return '';
  346. }
  347. }
  348. return String.fromCharCode(code);
  349. }
  350. function getEscapedIdentifier() {
  351. var ch, id, restore, type;
  352. ch = id = source[index++];
  353. if (ch === '\\') {
  354. if (source[index] !== 'u') {
  355. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  356. }
  357. ++index;
  358. restore = index;
  359. ch = scanHexEscape('u');
  360. if (ch) {
  361. if (ch === '\\' || !isIdentifierStart(ch)) {
  362. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  363. }
  364. id = ch;
  365. } else {
  366. index = restore;
  367. id = 'u';
  368. }
  369. }
  370. while (index < length) {
  371. ch = source[index];
  372. if (!isIdentifierPart(ch)) {
  373. break;
  374. }
  375. ++index;
  376. id += ch;
  377. if (ch === '\\') {
  378. id = id.substr(0, id.length - 1);
  379. if (source[index] !== 'u') {
  380. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  381. }
  382. ++index;
  383. restore = index;
  384. ch = scanHexEscape('u');
  385. if (ch) {
  386. if (ch === '\\' || !isIdentifierPart(ch)) {
  387. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  388. }
  389. id += ch;
  390. } else {
  391. index = restore;
  392. id += 'u';
  393. }
  394. }
  395. }
  396. return id;
  397. }
  398. function getIdentifier() {
  399. var start, ch;
  400. start = index++;
  401. while (index < length) {
  402. ch = source[index];
  403. if (ch === '\\') {
  404. index = start;
  405. return getEscapedIdentifier();
  406. }
  407. if (isIdentifierPart(ch)) {
  408. ++index;
  409. } else {
  410. break;
  411. }
  412. }
  413. return sliceSource(start, index);
  414. }
  415. function scanIdentifier() {
  416. var start, id, type;
  417. start = index;
  418. if (!isIdentifierStart(source[index])) {
  419. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  420. }
  421. id = (source[index] === '\\') ? getEscapedIdentifier() : getIdentifier();
  422. // There is no keyword or literal with only one character.
  423. // Thus, it must be an identifier.
  424. if (id.length === 1) {
  425. type = Token.Identifier;
  426. } else if (isKeyword(id)) {
  427. type = Token.Keyword;
  428. } else if (id === 'null') {
  429. type = Token.NullLiteral;
  430. } else if (id === 'true' || id === 'false') {
  431. type = Token.BooleanLiteral;
  432. } else {
  433. type = Token.Identifier;
  434. }
  435. return {
  436. type: type,
  437. value: id,
  438. lineNumber: lineNumber,
  439. lineStart: lineStart,
  440. range: [start, index]
  441. };
  442. }
  443. // 7.7 Punctuators
  444. function scanPunctuator() {
  445. var start = index,
  446. ch1 = source[index],
  447. ch2,
  448. ch3,
  449. ch4;
  450. // Check for most common single-character punctuators.
  451. if (ch1 === '.' || ch1 === '(' || ch1 === ')' || ch1 === ';' || ch1 === ',' ||
  452. ch1 === '{' || ch1 === '}' || ch1 === '[' || ch1 === ']' ||
  453. ch1 === ':' || ch1 === '?' || ch1 === '~') {
  454. ++index;
  455. return {
  456. type: Token.Punctuator,
  457. value: ch1,
  458. lineNumber: lineNumber,
  459. lineStart: lineStart,
  460. range: [start, index]
  461. };
  462. }
  463. // Peek more characters.
  464. ch2 = source[index + 1];
  465. ch3 = source[index + 2];
  466. ch4 = source[index + 3];
  467. // 4-character punctuator: >>>=
  468. if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
  469. if (ch4 === '=') {
  470. index += 4;
  471. return {
  472. type: Token.Punctuator,
  473. value: '>>>=',
  474. lineNumber: lineNumber,
  475. lineStart: lineStart,
  476. range: [start, index]
  477. };
  478. }
  479. }
  480. // 3-character punctuators: === !== >>> <<= >>=
  481. if (ch1 === '=' && ch2 === '=' && ch3 === '=') {
  482. index += 3;
  483. return {
  484. type: Token.Punctuator,
  485. value: '===',
  486. lineNumber: lineNumber,
  487. lineStart: lineStart,
  488. range: [start, index]
  489. };
  490. }
  491. if (ch1 === '!' && ch2 === '=' && ch3 === '=') {
  492. index += 3;
  493. return {
  494. type: Token.Punctuator,
  495. value: '!==',
  496. lineNumber: lineNumber,
  497. lineStart: lineStart,
  498. range: [start, index]
  499. };
  500. }
  501. if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
  502. index += 3;
  503. return {
  504. type: Token.Punctuator,
  505. value: '>>>',
  506. lineNumber: lineNumber,
  507. lineStart: lineStart,
  508. range: [start, index]
  509. };
  510. }
  511. if (ch1 === '<' && ch2 === '<' && ch3 === '=') {
  512. index += 3;
  513. return {
  514. type: Token.Punctuator,
  515. value: '<<=',
  516. lineNumber: lineNumber,
  517. lineStart: lineStart,
  518. range: [start, index]
  519. };
  520. }
  521. if (ch1 === '>' && ch2 === '>' && ch3 === '=') {
  522. index += 3;
  523. return {
  524. type: Token.Punctuator,
  525. value: '>>=',
  526. lineNumber: lineNumber,
  527. lineStart: lineStart,
  528. range: [start, index]
  529. };
  530. }
  531. // 2-character punctuators: <= >= == != ++ -- << >> && ||
  532. // += -= *= %= &= |= ^= /=
  533. if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) {
  534. if ('+-<>&|'.indexOf(ch2) >= 0) {
  535. index += 2;
  536. return {
  537. type: Token.Punctuator,
  538. value: ch1 + ch2,
  539. lineNumber: lineNumber,
  540. lineStart: lineStart,
  541. range: [start, index]
  542. };
  543. }
  544. }
  545. if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
  546. ++index;
  547. if (ch2 === '=') {
  548. ++index;
  549. ch1 += ch2;
  550. }
  551. return {
  552. type: Token.Punctuator,
  553. value: ch1,
  554. lineNumber: lineNumber,
  555. lineStart: lineStart,
  556. range: [start, index]
  557. };
  558. }
  559. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  560. }
  561. // 7.8.3 Numeric Literals
  562. function scanNumericLiteral() {
  563. var number, start, ch;
  564. ch = source[index];
  565. assert(isDecimalDigit(ch) || (ch === '.'),
  566. 'Numeric literal must start with a decimal digit or a decimal point');
  567. start = index;
  568. number = '';
  569. if (ch !== '.') {
  570. number = source[index++];
  571. ch = source[index];
  572. // Hex number starts with '0x'.
  573. // Octal number starts with '0'.
  574. if (number === '0') {
  575. if (ch === 'x' || ch === 'X') {
  576. number += source[index++];
  577. while (index < length) {
  578. ch = source[index];
  579. if (!isHexDigit(ch)) {
  580. break;
  581. }
  582. number += source[index++];
  583. }
  584. if (number.length <= 2) {
  585. // only 0x
  586. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  587. }
  588. if (index < length) {
  589. ch = source[index];
  590. if (isIdentifierStart(ch)) {
  591. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  592. }
  593. }
  594. return {
  595. type: Token.NumericLiteral,
  596. value: parseInt(number, 16),
  597. lineNumber: lineNumber,
  598. lineStart: lineStart,
  599. range: [start, index]
  600. };
  601. }
  602. if (isOctalDigit(ch)) {
  603. number += source[index++];
  604. while (index < length) {
  605. ch = source[index];
  606. if (!isOctalDigit(ch)) {
  607. break;
  608. }
  609. number += source[index++];
  610. }
  611. if (index < length) {
  612. ch = source[index];
  613. if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
  614. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  615. }
  616. }
  617. return {
  618. type: Token.NumericLiteral,
  619. value: parseInt(number, 8),
  620. octal: true,
  621. lineNumber: lineNumber,
  622. lineStart: lineStart,
  623. range: [start, index]
  624. };
  625. }
  626. // decimal number starts with '0' such as '09' is illegal.
  627. if (isDecimalDigit(ch)) {
  628. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  629. }
  630. }
  631. while (index < length) {
  632. ch = source[index];
  633. if (!isDecimalDigit(ch)) {
  634. break;
  635. }
  636. number += source[index++];
  637. }
  638. }
  639. if (ch === '.') {
  640. number += source[index++];
  641. while (index < length) {
  642. ch = source[index];
  643. if (!isDecimalDigit(ch)) {
  644. break;
  645. }
  646. number += source[index++];
  647. }
  648. }
  649. if (ch === 'e' || ch === 'E') {
  650. number += source[index++];
  651. ch = source[index];
  652. if (ch === '+' || ch === '-') {
  653. number += source[index++];
  654. }
  655. ch = source[index];
  656. if (isDecimalDigit(ch)) {
  657. number += source[index++];
  658. while (index < length) {
  659. ch = source[index];
  660. if (!isDecimalDigit(ch)) {
  661. break;
  662. }
  663. number += source[index++];
  664. }
  665. } else {
  666. ch = 'character ' + ch;
  667. if (index >= length) {
  668. ch = '<end>';
  669. }
  670. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  671. }
  672. }
  673. if (index < length) {
  674. ch = source[index];
  675. if (isIdentifierStart(ch)) {
  676. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  677. }
  678. }
  679. return {
  680. type: Token.NumericLiteral,
  681. value: parseFloat(number),
  682. lineNumber: lineNumber,
  683. lineStart: lineStart,
  684. range: [start, index]
  685. };
  686. }
  687. // 7.8.4 String Literals
  688. function scanStringLiteral() {
  689. var str = '', quote, start, ch, code, unescaped, restore, octal = false;
  690. quote = source[index];
  691. assert((quote === '\'' || quote === '"'),
  692. 'String literal must starts with a quote');
  693. start = index;
  694. ++index;
  695. while (index < length) {
  696. ch = source[index++];
  697. if (ch === quote) {
  698. quote = '';
  699. break;
  700. } else if (ch === '\\') {
  701. ch = source[index++];
  702. if (!isLineTerminator(ch)) {
  703. switch (ch) {
  704. case 'n':
  705. str += '\n';
  706. break;
  707. case 'r':
  708. str += '\r';
  709. break;
  710. case 't':
  711. str += '\t';
  712. break;
  713. case 'u':
  714. case 'x':
  715. restore = index;
  716. unescaped = scanHexEscape(ch);
  717. if (unescaped) {
  718. str += unescaped;
  719. } else {
  720. index = restore;
  721. str += ch;
  722. }
  723. break;
  724. case 'b':
  725. str += '\b';
  726. break;
  727. case 'f':
  728. str += '\f';
  729. break;
  730. case 'v':
  731. str += '\v';
  732. break;
  733. default:
  734. if (isOctalDigit(ch)) {
  735. code = '01234567'.indexOf(ch);
  736. // \0 is not octal escape sequence
  737. if (code !== 0) {
  738. octal = true;
  739. }
  740. if (index < length && isOctalDigit(source[index])) {
  741. octal = true;
  742. code = code * 8 + '01234567'.indexOf(source[index++]);
  743. // 3 digits are only allowed when string starts
  744. // with 0, 1, 2, 3
  745. if ('0123'.indexOf(ch) >= 0 &&
  746. index < length &&
  747. isOctalDigit(source[index])) {
  748. code = code * 8 + '01234567'.indexOf(source[index++]);
  749. }
  750. }
  751. str += String.fromCharCode(code);
  752. } else {
  753. str += ch;
  754. }
  755. break;
  756. }
  757. } else {
  758. ++lineNumber;
  759. if (ch === '\r' && source[index] === '\n') {
  760. ++index;
  761. }
  762. }
  763. } else if (isLineTerminator(ch)) {
  764. break;
  765. } else {
  766. str += ch;
  767. }
  768. }
  769. if (quote !== '') {
  770. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  771. }
  772. return {
  773. type: Token.StringLiteral,
  774. value: str,
  775. octal: octal,
  776. lineNumber: lineNumber,
  777. lineStart: lineStart,
  778. range: [start, index]
  779. };
  780. }
  781. function scanRegExp() {
  782. var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false;
  783. lookahead = null;
  784. skipComment();
  785. start = index;
  786. ch = source[index];
  787. assert(ch === '/', 'Regular expression literal must start with a slash');
  788. str = source[index++];
  789. while (index < length) {
  790. ch = source[index++];
  791. str += ch;
  792. if (classMarker) {
  793. if (ch === ']') {
  794. classMarker = false;
  795. }
  796. } else {
  797. if (ch === '\\') {
  798. ch = source[index++];
  799. // ECMA-262 7.8.5
  800. if (isLineTerminator(ch)) {
  801. throwError({}, Messages.UnterminatedRegExp);
  802. }
  803. str += ch;
  804. } else if (ch === '/') {
  805. terminated = true;
  806. break;
  807. } else if (ch === '[') {
  808. classMarker = true;
  809. } else if (isLineTerminator(ch)) {
  810. throwError({}, Messages.UnterminatedRegExp);
  811. }
  812. }
  813. }
  814. if (!terminated) {
  815. throwError({}, Messages.UnterminatedRegExp);
  816. }
  817. // Exclude leading and trailing slash.
  818. pattern = str.substr(1, str.length - 2);
  819. flags = '';
  820. while (index < length) {
  821. ch = source[index];
  822. if (!isIdentifierPart(ch)) {
  823. break;
  824. }
  825. ++index;
  826. if (ch === '\\' && index < length) {
  827. ch = source[index];
  828. if (ch === 'u') {
  829. ++index;
  830. restore = index;
  831. ch = scanHexEscape('u');
  832. if (ch) {
  833. flags += ch;
  834. for (str += '\\u'; restore < index; ++restore) {
  835. str += source[restore];
  836. }
  837. } else {
  838. index = restore;
  839. flags += 'u';
  840. str += '\\u';
  841. }
  842. } else {
  843. str += '\\';
  844. }
  845. } else {
  846. flags += ch;
  847. str += ch;
  848. }
  849. }
  850. try {
  851. value = new RegExp(pattern, flags);
  852. } catch (e) {
  853. throwError({}, Messages.InvalidRegExp);
  854. }
  855. peek();
  856. return {
  857. literal: str,
  858. value: value,
  859. range: [start, index]
  860. };
  861. }
  862. function isIdentifierName(token) {
  863. return token.type === Token.Identifier ||
  864. token.type === Token.Keyword ||
  865. token.type === Token.BooleanLiteral ||
  866. token.type === Token.NullLiteral;
  867. }
  868. function advance() {
  869. var ch;
  870. skipComment();
  871. if (index >= length) {
  872. return {
  873. type: Token.EOF,
  874. lineNumber: lineNumber,
  875. lineStart: lineStart,
  876. range: [index, index]
  877. };
  878. }
  879. ch = source[index];
  880. if (isIdentifierStart(ch)) {
  881. return scanIdentifier();
  882. }
  883. if (ch === '.') {
  884. // Dot (.) can also start a floating-point number, hence the need
  885. // to check the next character.
  886. if (isDecimalDigit(source[index + 1])) {
  887. return scanNumericLiteral();
  888. }
  889. return scanPunctuator();
  890. }
  891. if (ch === '\'' || ch === '"') {
  892. return scanStringLiteral();
  893. }
  894. if (isDecimalDigit(ch)) {
  895. return scanNumericLiteral();
  896. }
  897. return scanPunctuator();
  898. }
  899. function lex() {
  900. var token;
  901. token = lookahead;
  902. index = token.range[1];
  903. lineNumber = token.lineNumber;
  904. lineStart = token.lineStart;
  905. lookahead = advance();
  906. index = token.range[1];
  907. lineNumber = token.lineNumber;
  908. lineStart = token.lineStart;
  909. return token;
  910. }
  911. function peek() {
  912. var pos, line, start;
  913. pos = index;
  914. line = lineNumber;
  915. start = lineStart;
  916. lookahead = advance();
  917. index = pos;
  918. lineNumber = line;
  919. lineStart = start;
  920. }
  921. SyntaxTreeDelegate = {
  922. name: 'SyntaxTree',
  923. createArrayExpression: function (elements) {
  924. return {
  925. type: Syntax.ArrayExpression,
  926. elements: elements
  927. };
  928. },
  929. createAssignmentExpression: function (operator, left, right) {
  930. return {
  931. type: Syntax.AssignmentExpression,
  932. operator: operator,
  933. left: left,
  934. right: right
  935. };
  936. },
  937. createBinaryExpression: function (operator, left, right) {
  938. return {
  939. type: Syntax.BinaryExpression,
  940. operator: operator,
  941. left: left,
  942. right: right
  943. };
  944. },
  945. createBlockStatement: function (body) {
  946. return {
  947. type: Syntax.BlockStatement,
  948. body: body
  949. };
  950. },
  951. createBreakStatement: function (label) {
  952. return {
  953. type: Syntax.BreakStatement,
  954. label: label
  955. };
  956. },
  957. createCallExpression: function (callee, args) {
  958. return {
  959. type: Syntax.CallExpression,
  960. callee: callee,
  961. 'arguments': args
  962. };
  963. },
  964. createCatchClause: function (param, body) {
  965. return {
  966. type: Syntax.CatchClause,
  967. param: param,
  968. body: body
  969. };
  970. },
  971. createConditionalExpression: function (test, consequent, alternate) {
  972. return {
  973. type: Syntax.ConditionalExpression,
  974. test: test,
  975. consequent: consequent,
  976. alternate: alternate
  977. };
  978. },
  979. createContinueStatement: function (label) {
  980. return {
  981. type: Syntax.ContinueStatement,
  982. label: label
  983. };
  984. },
  985. createDebuggerStatement: function () {
  986. return {
  987. type: Syntax.DebuggerStatement
  988. };
  989. },
  990. createDoWhileStatement: function (body, test) {
  991. return {
  992. type: Syntax.DoWhileStatement,
  993. body: body,
  994. test: test
  995. };
  996. },
  997. createEmptyStatement: function () {
  998. return {
  999. type: Syntax.EmptyStatement
  1000. };
  1001. },
  1002. createExpressionStatement: function (expression) {
  1003. return {
  1004. type: Syntax.ExpressionStatement,
  1005. expression: expression
  1006. };
  1007. },
  1008. createForStatement: function (init, test, update, body) {
  1009. return {
  1010. type: Syntax.ForStatement,
  1011. init: init,
  1012. test: test,
  1013. update: update,
  1014. body: body
  1015. };
  1016. },
  1017. createForInStatement: function (left, right, body) {
  1018. return {
  1019. type: Syntax.ForInStatement,
  1020. left: left,
  1021. right: right,
  1022. body: body,
  1023. each: false
  1024. };
  1025. },
  1026. createFunctionDeclaration: function (id, params, defaults, body) {
  1027. return {
  1028. type: Syntax.FunctionDeclaration,
  1029. id: id,
  1030. params: params,
  1031. defaults: defaults,
  1032. body: body,
  1033. rest: null,
  1034. generator: false,
  1035. expression: false
  1036. };
  1037. },
  1038. createFunctionExpression: function (id, params, defaults, body) {
  1039. return {
  1040. type: Syntax.FunctionExpression,
  1041. id: id,
  1042. params: params,
  1043. defaults: defaults,
  1044. body: body,
  1045. rest: null,
  1046. generator: false,
  1047. expression: false
  1048. };
  1049. },
  1050. createIdentifier: function (name) {
  1051. return {
  1052. type: Syntax.Identifier,
  1053. name: name
  1054. };
  1055. },
  1056. createIfStatement: function (test, consequent, alternate) {
  1057. return {
  1058. type: Syntax.IfStatement,
  1059. test: test,
  1060. consequent: consequent,
  1061. alternate: alternate
  1062. };
  1063. },
  1064. createLabeledStatement: function (label, body) {
  1065. return {
  1066. type: Syntax.LabeledStatement,
  1067. label: label,
  1068. body: body
  1069. };
  1070. },
  1071. createLiteral: function (token) {
  1072. return {
  1073. type: Syntax.Literal,
  1074. value: token.value,
  1075. raw: sliceSource(token.range[0], token.range[1])
  1076. };
  1077. },
  1078. createLogicalExpression: function (operator, left, right) {
  1079. return {
  1080. type: Syntax.LogicalExpression,
  1081. operator: operator,
  1082. left: left,
  1083. right: right
  1084. };
  1085. },
  1086. createMemberExpression: function (accessor, object, property) {
  1087. return {
  1088. type: Syntax.MemberExpression,
  1089. computed: accessor === '[',
  1090. object: object,
  1091. property: property
  1092. };
  1093. },
  1094. createNewExpression: function (callee, args) {
  1095. return {
  1096. type: Syntax.NewExpression,
  1097. callee: callee,
  1098. 'arguments': args
  1099. };
  1100. },
  1101. createObjectExpression: function (properties) {
  1102. return {
  1103. type: Syntax.ObjectExpression,
  1104. properties: properties
  1105. };
  1106. },
  1107. createPostfixExpression: function (operator, argument) {
  1108. return {
  1109. type: Syntax.UpdateExpression,
  1110. operator: operator,
  1111. argument: argument,
  1112. prefix: false
  1113. };
  1114. },
  1115. createProgram: function (body) {
  1116. return {
  1117. type: Syntax.Program,
  1118. body: body
  1119. };
  1120. },
  1121. createProperty: function (kind, key, value) {
  1122. return {
  1123. type: Syntax.Property,
  1124. key: key,
  1125. value: value,
  1126. kind: kind
  1127. };
  1128. },
  1129. createReturnStatement: function (argument) {
  1130. return {
  1131. type: Syntax.ReturnStatement,
  1132. argument: argument
  1133. };
  1134. },
  1135. createSequenceExpression: function (expressions) {
  1136. return {
  1137. type: Syntax.SequenceExpression,
  1138. expressions: expressions
  1139. };
  1140. },
  1141. createSwitchCase: function (test, consequent) {
  1142. return {
  1143. type: Syntax.SwitchCase,
  1144. test: test,
  1145. consequent: consequent
  1146. };
  1147. },
  1148. createSwitchStatement: function (discriminant, cases) {
  1149. return {
  1150. type: Syntax.SwitchStatement,
  1151. discriminant: discriminant,
  1152. cases: cases
  1153. };
  1154. },
  1155. createThisExpression: function () {
  1156. return {
  1157. type: Syntax.ThisExpression
  1158. };
  1159. },
  1160. createThrowStatement: function (argument) {
  1161. return {
  1162. type: Syntax.ThrowStatement,
  1163. argument: argument
  1164. };
  1165. },
  1166. createTryStatement: function (block, guardedHandlers, handlers, finalizer) {
  1167. return {
  1168. type: Syntax.TryStatement,
  1169. block: block,
  1170. guardedHandlers: guardedHandlers,
  1171. handlers: handlers,
  1172. finalizer: finalizer
  1173. };
  1174. },
  1175. createUnaryExpression: function (operator, argument) {
  1176. if (operator === '++' || operator === '--') {
  1177. return {
  1178. type: Syntax.UpdateExpression,
  1179. operator: operator,
  1180. argument: argument,
  1181. prefix: true
  1182. };
  1183. }
  1184. return {
  1185. type: Syntax.UnaryExpression,
  1186. operator: operator,
  1187. argument: argument
  1188. };
  1189. },
  1190. createVariableDeclaration: function (declarations, kind) {
  1191. return {
  1192. type: Syntax.VariableDeclaration,
  1193. declarations: declarations,
  1194. kind: kind
  1195. };
  1196. },
  1197. createVariableDeclarator: function (id, init) {
  1198. return {
  1199. type: Syntax.VariableDeclarator,
  1200. id: id,
  1201. init: init
  1202. };
  1203. },
  1204. createWhileStatement: function (test, body) {
  1205. return {
  1206. type: Syntax.WhileStatement,
  1207. test: test,
  1208. body: body
  1209. };
  1210. },
  1211. createWithStatement: function (object, body) {
  1212. return {
  1213. type: Syntax.WithStatement,
  1214. object: object,
  1215. body: body
  1216. };
  1217. }
  1218. };
  1219. // Return true if there is a line terminator before the next token.
  1220. function peekLineTerminator() {
  1221. var pos, line, start, found;
  1222. pos = index;
  1223. line = lineNumber;
  1224. start = lineStart;
  1225. skipComment();
  1226. found = lineNumber !== line;
  1227. index = pos;
  1228. lineNumber = line;
  1229. lineStart = start;
  1230. return found;
  1231. }
  1232. // Throw an exception
  1233. function throwError(token, messageFormat) {
  1234. var error,
  1235. args = Array.prototype.slice.call(arguments, 2),
  1236. msg = messageFormat.replace(
  1237. /%(\d)/g,
  1238. function (whole, index) {
  1239. return args[index] || '';
  1240. }
  1241. );
  1242. if (typeof token.lineNumber === 'number') {
  1243. error = new Error('Line ' + token.lineNumber + ': ' + msg);
  1244. error.index = token.range[0];
  1245. error.lineNumber = token.lineNumber;
  1246. error.column = token.range[0] - lineStart + 1;
  1247. } else {
  1248. error = new Error('Line ' + lineNumber + ': ' + msg);
  1249. error.index = index;
  1250. error.lineNumber = lineNumber;
  1251. error.column = index - lineStart + 1;
  1252. }
  1253. throw error;
  1254. }
  1255. function throwErrorTolerant() {
  1256. try {
  1257. throwError.apply(null, arguments);
  1258. } catch (e) {
  1259. if (extra.errors) {
  1260. extra.errors.push(e);
  1261. } else {
  1262. throw e;
  1263. }
  1264. }
  1265. }
  1266. // Throw an exception because of the token.
  1267. function throwUnexpected(token) {
  1268. if (token.type === Token.EOF) {
  1269. throwError(token, Messages.UnexpectedEOS);
  1270. }
  1271. if (token.type === Token.NumericLiteral) {
  1272. throwError(token, Messages.UnexpectedNumber);
  1273. }
  1274. if (token.type === Token.StringLiteral) {
  1275. throwError(token, Messages.UnexpectedString);
  1276. }
  1277. if (token.type === Token.Identifier) {
  1278. throwError(token, Messages.UnexpectedIdentifier);
  1279. }
  1280. if (token.type === Token.Keyword) {
  1281. if (isFutureReservedWord(token.value)) {
  1282. throwError(token, Messages.UnexpectedReserved);
  1283. } else if (strict && isStrictModeReservedWord(token.value)) {
  1284. throwErrorTolerant(token, Messages.StrictReservedWord);
  1285. return;
  1286. }
  1287. throwError(token, Messages.UnexpectedToken, token.value);
  1288. }
  1289. // BooleanLiteral, NullLiteral, or Punctuator.
  1290. throwError(token, Messages.UnexpectedToken, token.value);
  1291. }
  1292. // Expect the next token to match the specified punctuator.
  1293. // If not, an exception will be thrown.
  1294. function expect(value) {
  1295. var token = lex();
  1296. if (token.type !== Token.Punctuator || token.value !== value) {
  1297. throwUnexpected(token);
  1298. }
  1299. }
  1300. // Expect the next token to match the specified keyword.
  1301. // If not, an exception will be thrown.
  1302. function expectKeyword(keyword) {
  1303. var token = lex();
  1304. if (token.type !== Token.Keyword || token.value !== keyword) {
  1305. throwUnexpected(token);
  1306. }
  1307. }
  1308. // Return true if the next token matches the specified punctuator.
  1309. function match(value) {
  1310. return lookahead.type === Token.Punctuator && lookahead.value === value;
  1311. }
  1312. // Return true if the next token matches the specified keyword
  1313. function matchKeyword(keyword) {
  1314. return lookahead.type === Token.Keyword && lookahead.value === keyword;
  1315. }
  1316. // Return true if the next token is an assignment operator
  1317. function matchAssign() {
  1318. var op;
  1319. if (lookahead.type !== Token.Punctuator) {
  1320. return false;
  1321. }
  1322. op = lookahead.value;
  1323. return op === '=' ||
  1324. op === '*=' ||
  1325. op === '/=' ||
  1326. op === '%=' ||
  1327. op === '+=' ||
  1328. op === '-=' ||
  1329. op === '<<=' ||
  1330. op === '>>=' ||
  1331. op === '>>>=' ||
  1332. op === '&=' ||
  1333. op === '^=' ||
  1334. op === '|=';
  1335. }
  1336. function consumeSemicolon() {
  1337. var line;
  1338. // Catch the very common case first.
  1339. if (source[index] === ';') {
  1340. lex();
  1341. return;
  1342. }
  1343. line = lineNumber;
  1344. skipComment();
  1345. if (lineNumber !== line) {
  1346. return;
  1347. }
  1348. if (match(';')) {
  1349. lex();
  1350. return;
  1351. }
  1352. if (lookahead.type !== Token.EOF && !match('}')) {
  1353. throwUnexpected(lookahead);
  1354. }
  1355. }
  1356. // Return true if provided expression is LeftHandSideExpression
  1357. function isLeftHandSide(expr) {
  1358. return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
  1359. }
  1360. // 11.1.4 Array Initialiser
  1361. function parseArrayInitialiser() {
  1362. var elements = [];
  1363. expect('[');
  1364. while (!match(']')) {
  1365. if (match(',')) {
  1366. lex();
  1367. elements.push(null);
  1368. } else {
  1369. elements.push(parseAssignmentExpression());
  1370. if (!match(']')) {
  1371. expect(',');
  1372. }
  1373. }
  1374. }
  1375. expect(']');
  1376. return delegate.createArrayExpression(elements);
  1377. }
  1378. // 11.1.5 Object Initialiser
  1379. function parsePropertyFunction(param, first) {
  1380. var previousStrict, body;
  1381. previousStrict = strict;
  1382. body = parseFunctionSourceElements();
  1383. if (first && strict && isRestrictedWord(param[0].name)) {
  1384. throwErrorTolerant(first, Messages.StrictParamName);
  1385. }
  1386. strict = previousStrict;
  1387. return delegate.createFunctionExpression(null, param, [], body);
  1388. }
  1389. function parseObjectPropertyKey() {
  1390. var token = lex();
  1391. // Note: This function is called only from parseObjectProperty(), where
  1392. // EOF and Punctuator tokens are already filtered out.
  1393. if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
  1394. if (strict && token.octal) {
  1395. throwErrorTolerant(token, Messages.StrictOctalLiteral);
  1396. }
  1397. return delegate.createLiteral(token);
  1398. }
  1399. return delegate.createIdentifier(token.value);
  1400. }
  1401. function parseObjectProperty() {
  1402. var token, key, id, value, param;
  1403. token = lookahead;
  1404. if (token.type === Token.Identifier) {
  1405. id = parseObjectPropertyKey();
  1406. // Property Assignment: Getter and Setter.
  1407. if (token.value === 'get' && !match(':')) {
  1408. key = parseObjectPropertyKey();
  1409. expect('(');
  1410. expect(')');
  1411. value = parsePropertyFunction([]);
  1412. return delegate.createProperty('get', key, value);
  1413. }
  1414. if (token.value === 'set' && !match(':')) {
  1415. key = parseObjectPropertyKey();
  1416. expect('(');
  1417. token = lookahead;
  1418. if (token.type !== Token.Identifier) {
  1419. throwUnexpected(lex());
  1420. }
  1421. param = [ parseVariableIdentifier() ];
  1422. expect(')');
  1423. value = parsePropertyFunction(param, token);
  1424. return delegate.createProperty('set', key, value);
  1425. }
  1426. expect(':');
  1427. value = parseAssignmentExpression();
  1428. return delegate.createProperty('init', id, value);
  1429. }
  1430. if (token.type === Token.EOF || token.type === Token.Punctuator) {
  1431. throwUnexpected(token);
  1432. } else {
  1433. key = parseObjectPropertyKey();
  1434. expect(':');
  1435. value = parseAssignmentExpression();
  1436. return delegate.createProperty('init', key, value);
  1437. }
  1438. }
  1439. function parseObjectInitialiser() {
  1440. var properties = [], property, name, kind, map = {}, toString = String;
  1441. expect('{');
  1442. while (!match('}')) {
  1443. property = parseObjectProperty();
  1444. if (property.key.type === Syntax.Identifier) {
  1445. name = property.key.name;
  1446. } else {
  1447. name = toString(property.key.value);
  1448. }
  1449. kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
  1450. if (Object.prototype.hasOwnProperty.call(map, name)) {
  1451. if (map[name] === PropertyKind.Data) {
  1452. if (strict && kind === PropertyKind.Data) {
  1453. throwErrorTolerant({}, Messages.StrictDuplicateProperty);
  1454. } else if (kind !== PropertyKind.Data) {
  1455. throwErrorTolerant({}, Messages.AccessorDataProperty);
  1456. }
  1457. } else {
  1458. if (kind === PropertyKind.Data) {
  1459. throwErrorTolerant({}, Messages.AccessorDataProperty);
  1460. } else if (map[name] & kind) {
  1461. throwErrorTolerant({}, Messages.AccessorGetSet);
  1462. }
  1463. }
  1464. map[name] |= kind;
  1465. } else {
  1466. map[name] = kind;
  1467. }
  1468. properties.push(property);
  1469. if (!match('}')) {
  1470. expect(',');
  1471. }
  1472. }
  1473. expect('}');
  1474. return delegate.createObjectExpression(properties);
  1475. }
  1476. // 11.1.6 The Grouping Operator
  1477. function parseGroupExpression() {
  1478. var expr;
  1479. expect('(');
  1480. expr = parseExpression();
  1481. expect(')');
  1482. return expr;
  1483. }
  1484. // 11.1 Primary Expressions
  1485. function parsePrimaryExpression() {
  1486. var type, token;
  1487. type = lookahead.type;
  1488. if (type === Token.Identifier) {
  1489. return delegate.createIdentifier(lex().value);
  1490. }
  1491. if (type === Token.StringLiteral || type === Token.NumericLiteral) {
  1492. if (strict && lookahead.octal) {
  1493. throwErrorTolerant(lookahead, Messages.StrictOctalLiteral);
  1494. }
  1495. return delegate.createLiteral(lex());
  1496. }
  1497. if (type === Token.Keyword) {
  1498. if (matchKeyword('this')) {
  1499. lex();
  1500. return delegate.createThisExpression();
  1501. }
  1502. if (matchKeyword('function')) {
  1503. return parseFunctionExpression();
  1504. }
  1505. }
  1506. if (type === Token.BooleanLiteral) {
  1507. token = lex();
  1508. token.value = (token.value === 'true');
  1509. return delegate.createLiteral(token);
  1510. }
  1511. if (type === Token.NullLiteral) {
  1512. token = lex();
  1513. token.value = null;
  1514. return delegate.createLiteral(token);
  1515. }
  1516. if (match('[')) {
  1517. return parseArrayInitialiser();
  1518. }
  1519. if (match('{')) {
  1520. return parseObjectInitialiser();
  1521. }
  1522. if (match('(')) {
  1523. return parseGroupExpression();
  1524. }
  1525. if (match('/') || match('/=')) {
  1526. return delegate.createLiteral(scanRegExp());
  1527. }
  1528. return throwUnexpected(lex());
  1529. }
  1530. // 11.2 Left-Hand-Side Expressions
  1531. function parseArguments() {
  1532. var args = [];
  1533. expect('(');
  1534. if (!match(')')) {
  1535. while (index < length) {
  1536. args.push(parseAssignmentExpression());
  1537. if (match(')')) {
  1538. break;
  1539. }
  1540. expect(',');
  1541. }
  1542. }
  1543. expect(')');
  1544. return args;
  1545. }
  1546. function parseNonComputedProperty() {
  1547. var token = lex();
  1548. if (!isIdentifierName(token)) {
  1549. throwUnexpected(token);
  1550. }
  1551. return delegate.createIdentifier(token.value);
  1552. }
  1553. function parseNonComputedMember() {
  1554. expect('.');
  1555. return parseNonComputedProperty();
  1556. }
  1557. function parseComputedMember() {
  1558. var expr;
  1559. expect('[');
  1560. expr = parseExpression();
  1561. expect(']');
  1562. return expr;
  1563. }
  1564. function parseNewExpression() {
  1565. var callee, args;
  1566. expectKeyword('new');
  1567. callee = parseLeftHandSideExpression();
  1568. args = match('(') ? parseArguments() : [];
  1569. return delegate.createNewExpression(callee, args);
  1570. }
  1571. function parseLeftHandSideExpressionAllowCall() {
  1572. var expr, args, property;
  1573. expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
  1574. while (match('.') || match('[') || match('(')) {
  1575. if (match('(')) {
  1576. args = parseArguments();
  1577. expr = delegate.createCallExpression(expr, args);
  1578. } else if (match('[')) {
  1579. property = parseComputedMember();
  1580. expr = delegate.createMemberExpression('[', expr, property);
  1581. } else {
  1582. property = parseNonComputedMember();
  1583. expr = delegate.createMemberExpression('.', expr, property);
  1584. }
  1585. }
  1586. return expr;
  1587. }
  1588. function parseLeftHandSideExpression() {
  1589. var expr, property;
  1590. expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
  1591. while (match('.') || match('[')) {
  1592. if (match('[')) {
  1593. property = parseComputedMember();
  1594. expr = delegate.createMemberExpression('[', expr, property);
  1595. } else {
  1596. property = parseNonComputedMember();
  1597. expr = delegate.createMemberExpression('.', expr, property);
  1598. }
  1599. }
  1600. return expr;
  1601. }
  1602. // 11.3 Postfix Expressions
  1603. function parsePostfixExpression() {
  1604. var expr = parseLeftHandSideExpressionAllowCall(), token;
  1605. if (lookahead.type !== Token.Punctuator) {
  1606. return expr;
  1607. }
  1608. if ((match('++') || match('--')) && !peekLineTerminator()) {
  1609. // 11.3.1, 11.3.2
  1610. if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
  1611. throwErrorTolerant({}, Messages.StrictLHSPostfix);
  1612. }
  1613. if (!isLeftHandSide(expr)) {
  1614. throwError({}, Messages.InvalidLHSInAssignment);
  1615. }
  1616. token = lex();
  1617. expr = delegate.createPostfixExpression(token.value, expr);
  1618. }
  1619. return expr;
  1620. }
  1621. // 11.4 Unary Operators
  1622. function parseUnaryExpression() {
  1623. var token, expr;
  1624. if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
  1625. return parsePostfixExpression();
  1626. }
  1627. if (match('++') || match('--')) {
  1628. token = lex();
  1629. expr = parseUnaryExpression();
  1630. // 11.4.4, 11.4.5
  1631. if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
  1632. throwErrorTolerant({}, Messages.StrictLHSPrefix);
  1633. }
  1634. if (!isLeftHandSide(expr)) {
  1635. throwError({}, Messages.InvalidLHSInAssignment);
  1636. }
  1637. return delegate.createUnaryExpression(token.value, expr);
  1638. }
  1639. if (match('+') || match('-') || match('~') || match('!')) {
  1640. token = lex();
  1641. expr = parseUnaryExpression();
  1642. return delegate.createUnaryExpression(token.value, expr);
  1643. }
  1644. if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
  1645. token = lex();
  1646. expr = parseUnaryExpression();
  1647. expr = delegate.createUnaryExpression(token.value, expr);
  1648. if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
  1649. throwErrorTolerant({}, Messages.StrictDelete);
  1650. }
  1651. return expr;
  1652. }
  1653. return parsePostfixExpression();
  1654. }
  1655. function binaryPrecedence(token, allowIn) {
  1656. var prec = 0;
  1657. if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
  1658. return 0;
  1659. }
  1660. switch (token.value) {
  1661. case '||':
  1662. prec = 1;
  1663. break;
  1664. case '&&':
  1665. prec = 2;
  1666. break;
  1667. case '|':
  1668. prec = 3;
  1669. break;
  1670. case '^':
  1671. prec = 4;
  1672. break;
  1673. case '&':
  1674. prec = 5;
  1675. break;
  1676. case '==':
  1677. case '!=':
  1678. case '===':
  1679. case '!==':
  1680. prec = 6;
  1681. break;
  1682. case '<':
  1683. case '>':
  1684. case '<=':
  1685. case '>=':
  1686. case 'instanceof':
  1687. prec = 7;
  1688. break;
  1689. case 'in':
  1690. prec = allowIn ? 7 : 0;
  1691. break;
  1692. case '<<':
  1693. case '>>':
  1694. case '>>>':
  1695. prec = 8;
  1696. break;
  1697. case '+':
  1698. case '-':
  1699. prec = 9;
  1700. break;
  1701. case '*':
  1702. case '/':
  1703. case '%':
  1704. prec = 11;
  1705. break;
  1706. default:
  1707. break;
  1708. }
  1709. return prec;
  1710. }
  1711. // 11.5 Multiplicative Operators
  1712. // 11.6 Additive Operators
  1713. // 11.7 Bitwise Shift Operators
  1714. // 11.8 Relational Operators
  1715. // 11.9 Equality Operators
  1716. // 11.10 Binary Bitwise Operators
  1717. // 11.11 Binary Logical Operators
  1718. // Reduce: make a binary expression from the three topmost entries.
  1719. function reduceBinary(stack) {
  1720. var right = stack.pop(),
  1721. operator = stack.pop().value,
  1722. left = stack.pop();
  1723. if (operator === '||' || operator === '&&') {
  1724. stack.push(delegate.createLogicalExpression(operator, left, right));
  1725. } else {
  1726. stack.push(delegate.createBinaryExpression(operator, left, right));
  1727. }
  1728. }
  1729. function parseBinaryExpression() {
  1730. var expr, token, prec, previousAllowIn, stack;
  1731. previousAllowIn = state.allowIn;
  1732. state.allowIn = true;
  1733. expr = parseUnaryExpression();
  1734. token = lookahead;
  1735. prec = binaryPrecedence(token, previousAllowIn);
  1736. if (prec === 0) {
  1737. return expr;
  1738. }
  1739. token.prec = prec;
  1740. lex();
  1741. stack = [expr, token, parseUnaryExpression()];
  1742. while ((prec = binaryPrecedence(lookahead, previousAllowIn)) > 0) {
  1743. // Reduce.
  1744. while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
  1745. reduceBinary(stack);
  1746. }
  1747. // Shift.
  1748. token = lex();
  1749. token.prec = prec;
  1750. stack.push(token);
  1751. stack.push(parseUnaryExpression());
  1752. }
  1753. // Final reduce to clean-up the stack.
  1754. while (stack.length > 1) {
  1755. reduceBinary(stack);
  1756. }
  1757. state.allowIn = previousAllowIn;
  1758. return stack[0];
  1759. }
  1760. // 11.12 Conditional Operator
  1761. function parseConditionalExpression() {
  1762. var expr, previousAllowIn, consequent, alternate;
  1763. expr = parseBinaryExpression();
  1764. if (match('?')) {
  1765. lex();
  1766. previousAllowIn = state.allowIn;
  1767. state.allowIn = true;
  1768. consequent = parseAssignmentExpression();
  1769. state.allowIn = previousAllowIn;
  1770. expect(':');
  1771. alternate = parseAssignmentExpression();
  1772. expr = delegate.createConditionalExpression(expr, consequent, alternate);
  1773. }
  1774. return expr;
  1775. }
  1776. // 11.13 Assignment Operators
  1777. function parseAssignmentExpression() {
  1778. var token, left, right;
  1779. token = lookahead;
  1780. left = parseConditionalExpression();
  1781. if (matchAssign()) {
  1782. // LeftHandSideExpression
  1783. if (!isLeftHandSide(left)) {
  1784. throwError({}, Messages.InvalidLHSInAssignment);
  1785. }
  1786. // 11.13.1
  1787. if (strict && left.type === Syntax.Identifier && isRestrictedWord(left.name)) {
  1788. throwErrorTolerant(token, Messages.StrictLHSAssignment);
  1789. }
  1790. token = lex();
  1791. right = parseAssignmentExpression();
  1792. return delegate.createAssignmentExpression(token.value, left, right);
  1793. }
  1794. return left;
  1795. }
  1796. // 11.14 Comma Operator
  1797. function parseExpression() {
  1798. var expr = parseAssignmentExpression();
  1799. if (match(',')) {
  1800. expr = delegate.createSequenceExpression([ expr ]);
  1801. while (index < length) {
  1802. if (!match(',')) {
  1803. break;
  1804. }
  1805. lex();
  1806. expr.expressions.push(parseAssignmentExpression());
  1807. }
  1808. }
  1809. return expr;
  1810. }
  1811. // 12.1 Block
  1812. function parseStatementList() {
  1813. var list = [],
  1814. statement;
  1815. while (index < length) {
  1816. if (match('}')) {
  1817. break;
  1818. }
  1819. statement = parseSourceElement();
  1820. if (typeof statement === 'undefined') {
  1821. break;
  1822. }
  1823. list.push(statement);
  1824. }
  1825. return list;
  1826. }
  1827. function parseBlock() {
  1828. var block;
  1829. expect('{');
  1830. block = parseStatementList();
  1831. expect('}');
  1832. return delegate.createBlockStatement(block);
  1833. }
  1834. // 12.2 Variable Statement
  1835. function parseVariableIdentifier() {
  1836. var token = lex();
  1837. if (token.type !== Token.Identifier) {
  1838. throwUnexpected(token);
  1839. }
  1840. return delegate.createIdentifier(token.value);
  1841. }
  1842. function parseVariableDeclaration(kind) {
  1843. var id = parseVariableIdentifier(),
  1844. init = null;
  1845. // 12.2.1
  1846. if (strict && isRestrictedWord(id.name)) {
  1847. throwErrorTolerant({}, Messages.StrictVarName);
  1848. }
  1849. if (kind === 'const') {
  1850. expect('=');
  1851. init = parseAssignmentExpression();
  1852. } else if (match('=')) {
  1853. lex();
  1854. init = parseAssignmentExpression();
  1855. }
  1856. return delegate.createVariableDeclarator(id, init);
  1857. }
  1858. function parseVariableDeclarationList(kind) {
  1859. var list = [];
  1860. while (index < length) {
  1861. list.push(parseVariableDeclaration(kind));
  1862. if (!match(',')) {
  1863. break;
  1864. }
  1865. lex();
  1866. }
  1867. return list;
  1868. }
  1869. function parseVariableStatement() {
  1870. var declarations;
  1871. expectKeyword('var');
  1872. declarations = parseVariableDeclarationList();
  1873. consumeSemicolon();
  1874. return delegate.createVariableDeclaration(declarations, 'var');
  1875. }
  1876. // kind may be `const` or `let`
  1877. // Both are experimental and not in the specification yet.
  1878. // see http://wiki.ecmascript.org/doku.php?id=harmony:const
  1879. // and http://wiki.ecmascript.org/doku.php?id=harmony:let
  1880. function parseConstLetDeclaration(kind) {
  1881. var declarations;
  1882. expectKeyword(kind);
  1883. declarations = parseVariableDeclarationList(kind);
  1884. consumeSemicolon();
  1885. return delegate.createVariableDeclaration(declarations, kind);
  1886. }
  1887. // 12.3 Empty Statement
  1888. function parseEmptyStatement() {
  1889. expect(';');
  1890. return delegate.createEmptyStatement();
  1891. }
  1892. // 12.4 Expression Statement
  1893. function parseExpressionStatement() {
  1894. var expr = parseExpression();
  1895. consumeSemicolon();
  1896. return delegate.createExpressionStatement(expr);
  1897. }
  1898. // 12.5 If statement
  1899. function parseIfStatement() {
  1900. var test, consequent, alternate;
  1901. expectKeyword('if');
  1902. expect('(');
  1903. test = parseExpression();
  1904. expect(')');
  1905. consequent = parseStatement();
  1906. if (matchKeyword('else')) {
  1907. lex();
  1908. alternate = parseStatement();
  1909. } else {
  1910. alternate = null;
  1911. }
  1912. return delegate.createIfStatement(test, consequent, alternate);
  1913. }
  1914. // 12.6 Iteration Statements
  1915. function parseDoWhileStatement() {
  1916. var body, test, oldInIteration;
  1917. expectKeyword('do');
  1918. oldInIteration = state.inIteration;
  1919. state.inIteration = true;
  1920. body = parseStatement();
  1921. state.inIteration = oldInIteration;
  1922. expectKeyword('while');
  1923. expect('(');
  1924. test = parseExpression();
  1925. expect(')');
  1926. if (match(';')) {
  1927. lex();
  1928. }
  1929. return delegate.createDoWhileStatement(body, test);
  1930. }
  1931. function parseWhileStatement() {
  1932. var test, body, oldInIteration;
  1933. expectKeyword('while');
  1934. expect('(');
  1935. test = parseExpression();
  1936. expect(')');
  1937. oldInIteration = state.inIteration;
  1938. state.inIteration = true;
  1939. body = parseStatement();
  1940. state.inIteration = oldInIteration;
  1941. return delegate.createWhileStatement(test, body);
  1942. }
  1943. function parseForVariableDeclaration() {
  1944. var token = lex(),
  1945. declarations = parseVariableDeclarationList();
  1946. return delegate.createVariableDeclaration(declarations, token.value);
  1947. }
  1948. function parseForStatement() {
  1949. var init, test, update, left, right, body, oldInIteration;
  1950. init = test = update = null;
  1951. expectKeyword('for');
  1952. expect('(');
  1953. if (match(';')) {
  1954. lex();
  1955. } else {
  1956. if (matchKeyword('var') || matchKeyword('let')) {
  1957. state.allowIn = false;
  1958. init = parseForVariableDeclaration();
  1959. state.allowIn = true;
  1960. if (init.declarations.length === 1 && matchKeyword('in')) {
  1961. lex();
  1962. left = init;
  1963. right = parseExpression();
  1964. init = null;
  1965. }
  1966. } else {
  1967. state.allowIn = false;
  1968. init = parseExpression();
  1969. state.allowIn = true;
  1970. if (matchKeyword('in')) {
  1971. // LeftHandSideExpression
  1972. if (!isLeftHandSide(init)) {
  1973. throwError({}, Messages.InvalidLHSInForIn);
  1974. }
  1975. lex();
  1976. left = init;
  1977. right = parseExpression();
  1978. init = null;
  1979. }
  1980. }
  1981. if (typeof left === 'undefined') {
  1982. expect(';');
  1983. }
  1984. }
  1985. if (typeof left === 'undefined') {
  1986. if (!match(';')) {
  1987. test = parseExpression();
  1988. }
  1989. expect(';');
  1990. if (!match(')')) {
  1991. update = parseExpression();
  1992. }
  1993. }
  1994. expect(')');
  1995. oldInIteration = state.inIteration;
  1996. state.inIteration = true;
  1997. body = parseStatement();
  1998. state.inIteration = oldInIteration;
  1999. return (typeof left === 'undefined') ?
  2000. delegate.createForStatement(init, test, update, body) :
  2001. delegate.createForInStatement(left, right, body);
  2002. }
  2003. // 12.7 The continue statement
  2004. function parseContinueStatement() {
  2005. var label = null;
  2006. expectKeyword('continue');
  2007. // Optimize the most common form: 'continue;'.
  2008. if (source[index] === ';') {
  2009. lex();
  2010. if (!state.inIteration) {
  2011. throwError({}, Messages.IllegalContinue);
  2012. }
  2013. return delegate.createContinueStatement(null);
  2014. }
  2015. if (peekLineTerminator()) {
  2016. if (!state.inIteration) {
  2017. throwError({}, Messages.IllegalContinue);
  2018. }
  2019. return delegate.createContinueStatement(null);
  2020. }
  2021. if (lookahead.type === Token.Identifier) {
  2022. label = parseVariableIdentifier();
  2023. if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
  2024. throwError({}, Messages.UnknownLabel, label.name);
  2025. }
  2026. }
  2027. consumeSemicolon();
  2028. if (label === null && !state.inIteration) {
  2029. throwError({}, Messages.IllegalContinue);
  2030. }
  2031. return delegate.createContinueStatement(label);
  2032. }
  2033. // 12.8 The break statement
  2034. function parseBreakStatement() {
  2035. var label = null;
  2036. expectKeyword('break');
  2037. // Optimize the most common form: 'break;'.
  2038. if (source[index] === ';') {
  2039. lex();
  2040. if (!(state.inIteration || state.inSwitch)) {
  2041. throwError({}, Messages.IllegalBreak);
  2042. }
  2043. return delegate.createBreakStatement(null);
  2044. }
  2045. if (peekLineTerminator()) {
  2046. if (!(state.inIteration || state.inSwitch)) {
  2047. throwError({}, Messages.IllegalBreak);
  2048. }
  2049. return delegate.createBreakStatement(null);
  2050. }
  2051. if (lookahead.type === Token.Identifier) {
  2052. label = parseVariableIdentifier();
  2053. if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
  2054. throwError({}, Messages.UnknownLabel, label.name);
  2055. }
  2056. }
  2057. consumeSemicolon();
  2058. if (label === null && !(state.inIteration || state.inSwitch)) {
  2059. throwError({}, Messages.IllegalBreak);
  2060. }
  2061. return delegate.createBreakStatement(label);
  2062. }
  2063. // 12.9 The return statement
  2064. function parseReturnStatement() {
  2065. var argument = null;
  2066. expectKeyword('return');
  2067. if (!state.inFunctionBody) {
  2068. throwErrorTolerant({}, Messages.IllegalReturn);
  2069. }
  2070. // 'return' followed by a space and an identifier is very common.
  2071. if (source[index] === ' ') {
  2072. if (isIdentifierStart(source[index + 1])) {
  2073. argument = parseExpression();
  2074. consumeSemicolon();
  2075. return delegate.createReturnStatement(argument);
  2076. }
  2077. }
  2078. if (peekLineTerminator()) {
  2079. return delegate.createReturnStatement(null);
  2080. }
  2081. if (!match(';')) {
  2082. if (!match('}') && lookahead.type !== Token.EOF) {
  2083. argument = parseExpression();
  2084. }
  2085. }
  2086. consumeSemicolon();
  2087. return delegate.createReturnStatement(argument);
  2088. }
  2089. // 12.10 The with statement
  2090. function parseWithStatement() {
  2091. var object, body;
  2092. if (strict) {
  2093. throwErrorTolerant({}, Messages.StrictModeWith);
  2094. }
  2095. expectKeyword('with');
  2096. expect('(');
  2097. object = parseExpression();
  2098. expect(')');
  2099. body = parseStatement();
  2100. return delegate.createWithStatement(object, body);
  2101. }
  2102. // 12.10 The swith statement
  2103. function parseSwitchCase() {
  2104. var test,
  2105. consequent = [],
  2106. statement;
  2107. if (matchKeyword('default')) {
  2108. lex();
  2109. test = null;
  2110. } else {
  2111. expectKeyword('case');
  2112. test = parseExpression();
  2113. }
  2114. expect(':');
  2115. while (index < length) {
  2116. if (match('}') || matchKeyword('default') || matchKeyword('case')) {
  2117. break;
  2118. }
  2119. statement = parseStatement();
  2120. if (typeof statement === 'undefined') {
  2121. break;
  2122. }
  2123. consequent.push(statement);
  2124. }
  2125. return delegate.createSwitchCase(test, consequent);
  2126. }
  2127. function parseSwitchStatement() {
  2128. var discriminant, cases, clause, oldInSwitch, defaultFound;
  2129. expectKeyword('switch');
  2130. expect('(');
  2131. discriminant = parseExpression();
  2132. expect(')');
  2133. expect('{');
  2134. if (match('}')) {
  2135. lex();
  2136. return delegate.createSwitchStatement(discriminant);
  2137. }
  2138. cases = [];
  2139. oldInSwitch = state.inSwitch;
  2140. state.inSwitch = true;
  2141. defaultFound = false;
  2142. while (index < length) {
  2143. if (match('}')) {
  2144. break;
  2145. }
  2146. clause = parseSwitchCase();
  2147. if (clause.test === null) {
  2148. if (defaultFound) {
  2149. throwError({}, Messages.MultipleDefaultsInSwitch);
  2150. }
  2151. defaultFound = true;
  2152. }
  2153. cases.push(clause);
  2154. }
  2155. state.inSwitch = oldInSwitch;
  2156. expect('}');
  2157. return delegate.createSwitchStatement(discriminant, cases);
  2158. }
  2159. // 12.13 The throw statement
  2160. function parseThrowStatement() {
  2161. var argument;
  2162. expectKeyword('throw');
  2163. if (peekLineTerminator()) {
  2164. throwError({}, Messages.NewlineAfterThrow);
  2165. }
  2166. argument = parseExpression();
  2167. consumeSemicolon();
  2168. return delegate.createThrowStatement(argument);
  2169. }
  2170. // 12.14 The try statement
  2171. function parseCatchClause() {
  2172. var param, body;
  2173. expectKeyword('catch');
  2174. expect('(');
  2175. if (!match(')')) {
  2176. param = parseExpression();
  2177. // 12.14.1
  2178. if (strict && param.type === Syntax.Identifier && isRestrictedWord(param.name)) {
  2179. throwErrorTolerant({}, Messages.StrictCatchVariable);
  2180. }
  2181. }
  2182. expect(')');
  2183. body = parseBlock();
  2184. return delegate.createCatchClause(param, body);
  2185. }
  2186. function parseTryStatement() {
  2187. var block, handlers = [], finalizer = null;
  2188. expectKeyword('try');
  2189. block = parseBlock();
  2190. if (matchKeyword('catch')) {
  2191. handlers.push(parseCatchClause());
  2192. }
  2193. if (matchKeyword('finally')) {
  2194. lex();
  2195. finalizer = parseBlock();
  2196. }
  2197. if (handlers.length === 0 && !finalizer) {
  2198. throwError({}, Messages.NoCatchOrFinally);
  2199. }
  2200. return delegate.createTryStatement(block, [], handlers, finalizer);
  2201. }
  2202. // 12.15 The debugger statement
  2203. function parseDebuggerStatement() {
  2204. expectKeyword('debugger');
  2205. consumeSemicolon();
  2206. return delegate.createDebuggerStatement();
  2207. }
  2208. // 12 Statements
  2209. function parseStatement() {
  2210. var type = lookahead.type,
  2211. expr,
  2212. labeledBody;
  2213. if (type === Token.EOF) {
  2214. throwUnexpected(lookahead);
  2215. }
  2216. if (type === Token.Punctuator) {
  2217. switch (lookahead.value) {
  2218. case ';':
  2219. return parseEmptyStatement();
  2220. case '{':
  2221. return parseBlock();
  2222. case '(':
  2223. return parseExpressionStatement();
  2224. default:
  2225. break;
  2226. }
  2227. }
  2228. if (type === Token.Keyword) {
  2229. switch (lookahead.value) {
  2230. case 'break':
  2231. return parseBreakStatement();
  2232. case 'continue':
  2233. return parseContinueStatement();
  2234. case 'debugger':
  2235. return parseDebuggerStatement();
  2236. case 'do':
  2237. return parseDoWhileStatement();
  2238. case 'for':
  2239. return parseForStatement();
  2240. case 'function':
  2241. return parseFunctionDeclaration();
  2242. case 'if':
  2243. return parseIfStatement();
  2244. case 'return':
  2245. return parseReturnStatement();
  2246. case 'switch':
  2247. return parseSwitchStatement();
  2248. case 'throw':
  2249. return parseThrowStatement();
  2250. case 'try':
  2251. return parseTryStatement();
  2252. case 'var':
  2253. return parseVariableStatement();
  2254. case 'while':
  2255. return parseWhileStatement();
  2256. case 'with':
  2257. return parseWithStatement();
  2258. default:
  2259. break;
  2260. }
  2261. }
  2262. expr = parseExpression();
  2263. // 12.12 Labelled Statements
  2264. if ((expr.type === Syntax.Identifier) && match(':')) {
  2265. lex();
  2266. if (Object.prototype.hasOwnProperty.call(state.labelSet, expr.name)) {
  2267. throwError({}, Messages.Redeclaration, 'Label', expr.name);
  2268. }
  2269. state.labelSet[expr.name] = true;
  2270. labeledBody = parseStatement();
  2271. delete state.labelSet[expr.name];
  2272. return delegate.createLabeledStatement(expr, labeledBody);
  2273. }
  2274. consumeSemicolon();
  2275. return delegate.createExpressionStatement(expr);
  2276. }
  2277. // 13 Function Definition
  2278. function parseFunctionSourceElements() {
  2279. var sourceElement, sourceElements = [], token, directive, firstRestricted,
  2280. oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody;
  2281. expect('{');
  2282. while (index < length) {
  2283. if (lookahead.type !== Token.StringLiteral) {
  2284. break;
  2285. }
  2286. token = lookahead;
  2287. sourceElement = parseSourceElement();
  2288. sourceElements.push(sourceElement);
  2289. if (sourceElement.expression.type !== Syntax.Literal) {
  2290. // this is not directive
  2291. break;
  2292. }
  2293. directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
  2294. if (directive === 'use strict') {
  2295. strict = true;
  2296. if (firstRestricted) {
  2297. throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
  2298. }
  2299. } else {
  2300. if (!firstRestricted && token.octal) {
  2301. firstRestricted = token;
  2302. }
  2303. }
  2304. }
  2305. oldLabelSet = state.labelSet;
  2306. oldInIteration = state.inIteration;
  2307. oldInSwitch = state.inSwitch;
  2308. oldInFunctionBody = state.inFunctionBody;
  2309. state.labelSet = {};
  2310. state.inIteration = false;
  2311. state.inSwitch = false;
  2312. state.inFunctionBody = true;
  2313. while (index < length) {
  2314. if (match('}')) {
  2315. break;
  2316. }
  2317. sourceElement = parseSourceElement();
  2318. if (typeof sourceElement === 'undefined') {
  2319. break;
  2320. }
  2321. sourceElements.push(sourceElement);
  2322. }
  2323. expect('}');
  2324. state.labelSet = oldLabelSet;
  2325. state.inIteration = oldInIteration;
  2326. state.inSwitch = oldInSwitch;
  2327. state.inFunctionBody = oldInFunctionBody;
  2328. return delegate.createBlockStatement(sourceElements);
  2329. }
  2330. function parseParams(firstRestricted) {
  2331. var param, params = [], token, stricted, paramSet, message;
  2332. expect('(');
  2333. if (!match(')')) {
  2334. paramSet = {};
  2335. while (index < length) {
  2336. token = lookahead;
  2337. param = parseVariableIdentifier();
  2338. if (strict) {
  2339. if (isRestrictedWord(token.value)) {
  2340. stricted = token;
  2341. message = Messages.StrictParamName;
  2342. }
  2343. if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
  2344. stricted = token;
  2345. message = Messages.StrictParamDupe;
  2346. }
  2347. } else if (!firstRestricted) {
  2348. if (isRestrictedWord(token.value)) {
  2349. firstRestricted = token;
  2350. message = Messages.StrictParamName;
  2351. } else if (isStrictModeReservedWord(token.value)) {
  2352. firstRestricted = token;
  2353. message = Messages.StrictReservedWord;
  2354. } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
  2355. firstRestricted = token;
  2356. message = Messages.StrictParamDupe;
  2357. }
  2358. }
  2359. params.push(param);
  2360. paramSet[param.name] = true;
  2361. if (match(')')) {
  2362. break;
  2363. }
  2364. expect(',');
  2365. }
  2366. }
  2367. expect(')');
  2368. return {
  2369. params: params,
  2370. stricted: stricted,
  2371. firstRestricted: firstRestricted,
  2372. message: message
  2373. };
  2374. }
  2375. function parseFunctionDeclaration() {
  2376. var id, params = [], body, token, stricted, tmp, firstRestricted, message, previousStrict;
  2377. expectKeyword('function');
  2378. token = lookahead;
  2379. id = parseVariableIdentifier();
  2380. if (strict) {
  2381. if (isRestrictedWord(token.value)) {
  2382. throwErrorTolerant(token, Messages.StrictFunctionName);
  2383. }
  2384. } else {
  2385. if (isRestrictedWord(token.value)) {
  2386. firstRestricted = token;
  2387. message = Messages.StrictFunctionName;
  2388. } else if (isStrictModeReservedWord(token.value)) {
  2389. firstRestricted = token;
  2390. message = Messages.StrictReservedWord;
  2391. }
  2392. }
  2393. tmp = parseParams(firstRestricted);
  2394. params = tmp.params;
  2395. stricted = tmp.stricted;
  2396. firstRestricted = tmp.firstRestricted;
  2397. if (tmp.message) {
  2398. message = tmp.message;
  2399. }
  2400. previousStrict = strict;
  2401. body = parseFunctionSourceElements();
  2402. if (strict && firstRestricted) {
  2403. throwError(firstRestricted, message);
  2404. }
  2405. if (strict && stricted) {
  2406. throwErrorTolerant(stricted, message);
  2407. }
  2408. strict = previousStrict;
  2409. return delegate.createFunctionDeclaration(id, params, [], body);
  2410. }
  2411. function parseFunctionExpression() {
  2412. var token, id = null, stricted, firstRestricted, message, tmp, params = [], body, previousStrict;
  2413. expectKeyword('function');
  2414. if (!match('(')) {
  2415. token = lookahead;
  2416. id = parseVariableIdentifier();
  2417. if (strict) {
  2418. if (isRestrictedWord(token.value)) {
  2419. throwErrorTolerant(token, Messages.StrictFunctionName);
  2420. }
  2421. } else {
  2422. if (isRestrictedWord(token.value)) {
  2423. firstRestricted = token;
  2424. message = Messages.StrictFunctionName;
  2425. } else if (isStrictModeReservedWord(token.value)) {
  2426. firstRestricted = token;
  2427. message = Messages.StrictReservedWord;
  2428. }
  2429. }
  2430. }
  2431. tmp = parseParams(firstRestricted);
  2432. params = tmp.params;
  2433. stricted = tmp.stricted;
  2434. firstRestricted = tmp.firstRestricted;
  2435. if (tmp.message) {
  2436. message = tmp.message;
  2437. }
  2438. previousStrict = strict;
  2439. body = parseFunctionSourceElements();
  2440. if (strict && firstRestricted) {
  2441. throwError(firstRestricted, message);
  2442. }
  2443. if (strict && stricted) {
  2444. throwErrorTolerant(stricted, message);
  2445. }
  2446. strict = previousStrict;
  2447. return delegate.createFunctionExpression(id, params, [], body);
  2448. }
  2449. // 14 Program
  2450. function parseSourceElement() {
  2451. if (lookahead.type === Token.Keyword) {
  2452. switch (lookahead.value) {
  2453. case 'const':
  2454. case 'let':
  2455. return parseConstLetDeclaration(lookahead.value);
  2456. case 'function':
  2457. return parseFunctionDeclaration();
  2458. default:
  2459. return parseStatement();
  2460. }
  2461. }
  2462. if (lookahead.type !== Token.EOF) {
  2463. return parseStatement();
  2464. }
  2465. }
  2466. function parseSourceElements() {
  2467. var sourceElement, sourceElements = [], token, directive, firstRestricted;
  2468. while (index < length) {
  2469. token = lookahead;
  2470. if (token.type !== Token.StringLiteral) {
  2471. break;
  2472. }
  2473. sourceElement = parseSourceElement();
  2474. sourceElements.push(sourceElement);
  2475. if (sourceElement.expression.type !== Syntax.Literal) {
  2476. // this is not directive
  2477. break;
  2478. }
  2479. directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
  2480. if (directive === 'use strict') {
  2481. strict = true;
  2482. if (firstRestricted) {
  2483. throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
  2484. }
  2485. } else {
  2486. if (!firstRestricted && token.octal) {
  2487. firstRestricted = token;
  2488. }
  2489. }
  2490. }
  2491. while (index < length) {
  2492. sourceElement = parseSourceElement();
  2493. if (typeof sourceElement === 'undefined') {
  2494. break;
  2495. }
  2496. sourceElements.push(sourceElement);
  2497. }
  2498. return sourceElements;
  2499. }
  2500. function parseProgram() {
  2501. var body;
  2502. strict = false;
  2503. peek();
  2504. body = parseSourceElements();
  2505. return delegate.createProgram(body);
  2506. }
  2507. // The following functions are needed only when the option to preserve
  2508. // the comments is active.
  2509. function addComment(type, value, start, end, loc) {
  2510. assert(typeof start === 'number', 'Comment must have valid position');
  2511. // Because the way the actual token is scanned, often the comments
  2512. // (if any) are skipped twice during the lexical analysis.
  2513. // Thus, we need to skip adding a comment if the comment array already
  2514. // handled it.
  2515. if (extra.comments.length > 0) {
  2516. if (extra.comments[extra.comments.length - 1].range[1] > start) {
  2517. return;
  2518. }
  2519. }
  2520. extra.comments.push({
  2521. type: type,
  2522. value: value,
  2523. range: [start, end],
  2524. loc: loc
  2525. });
  2526. }
  2527. function scanComment() {
  2528. var comment, ch, loc, start, blockComment, lineComment;
  2529. comment = '';
  2530. blockComment = false;
  2531. lineComment = false;
  2532. while (index < length) {
  2533. ch = source[index];
  2534. if (lineComment) {
  2535. ch = source[index++];
  2536. if (isLineTerminator(ch)) {
  2537. loc.end = {
  2538. line: lineNumber,
  2539. column: index - lineStart - 1
  2540. };
  2541. lineComment = false;
  2542. addComment('Line', comment, start, index - 1, loc);
  2543. if (ch === '\r' && source[index] === '\n') {
  2544. ++index;
  2545. }
  2546. ++lineNumber;
  2547. lineStart = index;
  2548. comment = '';
  2549. } else if (index >= length) {
  2550. lineComment = false;
  2551. comment += ch;
  2552. loc.end = {
  2553. line: lineNumber,
  2554. column: length - lineStart
  2555. };
  2556. addComment('Line', comment, start, length, loc);
  2557. } else {
  2558. comment += ch;
  2559. }
  2560. } else if (blockComment) {
  2561. if (isLineTerminator(ch)) {
  2562. if (ch === '\r' && source[index + 1] === '\n') {
  2563. ++index;
  2564. comment += '\r\n';
  2565. } else {
  2566. comment += ch;
  2567. }
  2568. ++lineNumber;
  2569. ++index;
  2570. lineStart = index;
  2571. if (index >= length) {
  2572. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  2573. }
  2574. } else {
  2575. ch = source[index++];
  2576. if (index >= length) {
  2577. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  2578. }
  2579. comment += ch;
  2580. if (ch === '*') {
  2581. ch = source[index];
  2582. if (ch === '/') {
  2583. comment = comment.substr(0, comment.length - 1);
  2584. blockComment = false;
  2585. ++index;
  2586. loc.end = {
  2587. line: lineNumber,
  2588. column: index - lineStart
  2589. };
  2590. addComment('Block', comment, start, index, loc);
  2591. comment = '';
  2592. }
  2593. }
  2594. }
  2595. } else if (ch === '/') {
  2596. ch = source[index + 1];
  2597. if (ch === '/') {
  2598. loc = {
  2599. start: {
  2600. line: lineNumber,
  2601. column: index - lineStart
  2602. }
  2603. };
  2604. start = index;
  2605. index += 2;
  2606. lineComment = true;
  2607. if (index >= length) {
  2608. loc.end = {
  2609. line: lineNumber,
  2610. column: index - lineStart
  2611. };
  2612. lineComment = false;
  2613. addComment('Line', comment, start, index, loc);
  2614. }
  2615. } else if (ch === '*') {
  2616. start = index;
  2617. index += 2;
  2618. blockComment = true;
  2619. loc = {
  2620. start: {
  2621. line: lineNumber,
  2622. column: index - lineStart - 2
  2623. }
  2624. };
  2625. if (index >= length) {
  2626. throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
  2627. }
  2628. } else {
  2629. break;
  2630. }
  2631. } else if (isWhiteSpace(ch)) {
  2632. ++index;
  2633. } else if (isLineTerminator(ch)) {
  2634. ++index;
  2635. if (ch === '\r' && source[index] === '\n') {
  2636. ++index;
  2637. }
  2638. ++lineNumber;
  2639. lineStart = index;
  2640. } else {
  2641. break;
  2642. }
  2643. }
  2644. }
  2645. function filterCommentLocation() {
  2646. var i, entry, comment, comments = [];
  2647. for (i = 0; i < extra.comments.length; ++i) {
  2648. entry = extra.comments[i];
  2649. comment = {
  2650. type: entry.type,
  2651. value: entry.value
  2652. };
  2653. if (extra.range) {
  2654. comment.range = entry.range;
  2655. }
  2656. if (extra.loc) {
  2657. comment.loc = entry.loc;
  2658. }
  2659. comments.push(comment);
  2660. }
  2661. extra.comments = comments;
  2662. }
  2663. function collectToken() {
  2664. var start, loc, token, range, value;
  2665. skipComment();
  2666. start = index;
  2667. loc = {
  2668. start: {
  2669. line: lineNumber,
  2670. column: index - lineStart
  2671. }
  2672. };
  2673. token = extra.advance();
  2674. loc.end = {
  2675. line: lineNumber,
  2676. column: index - lineStart
  2677. };
  2678. if (token.type !== Token.EOF) {
  2679. range = [token.range[0], token.range[1]];
  2680. value = sliceSource(token.range[0], token.range[1]);
  2681. extra.tokens.push({
  2682. type: TokenName[token.type],
  2683. value: value,
  2684. range: range,
  2685. loc: loc
  2686. });
  2687. }
  2688. return token;
  2689. }
  2690. function collectRegex() {
  2691. var pos, loc, regex, token;
  2692. skipComment();
  2693. pos = index;
  2694. loc = {
  2695. start: {
  2696. line: lineNumber,
  2697. column: index - lineStart
  2698. }
  2699. };
  2700. regex = extra.scanRegExp();
  2701. loc.end = {
  2702. line: lineNumber,
  2703. column: index - lineStart
  2704. };
  2705. // Pop the previous token, which is likely '/' or '/='
  2706. if (extra.tokens.length > 0) {
  2707. token = extra.tokens[extra.tokens.length - 1];
  2708. if (token.range[0] === pos && token.type === 'Punctuator') {
  2709. if (token.value === '/' || token.value === '/=') {
  2710. extra.tokens.pop();
  2711. }
  2712. }
  2713. }
  2714. extra.tokens.push({
  2715. type: 'RegularExpression',
  2716. value: regex.literal,
  2717. range: [pos, index],
  2718. loc: loc
  2719. });
  2720. return regex;
  2721. }
  2722. function filterTokenLocation() {
  2723. var i, entry, token, tokens = [];
  2724. for (i = 0; i < extra.tokens.length; ++i) {
  2725. entry = extra.tokens[i];
  2726. token = {
  2727. type: entry.type,
  2728. value: entry.value
  2729. };
  2730. if (extra.range) {
  2731. token.range = entry.range;
  2732. }
  2733. if (extra.loc) {
  2734. token.loc = entry.loc;
  2735. }
  2736. tokens.push(token);
  2737. }
  2738. extra.tokens = tokens;
  2739. }
  2740. function createLocationMarker() {
  2741. var marker = {};
  2742. marker.range = [index, index];
  2743. marker.loc = {
  2744. start: {
  2745. line: lineNumber,
  2746. column: index - lineStart
  2747. },
  2748. end: {
  2749. line: lineNumber,
  2750. column: index - lineStart
  2751. }
  2752. };
  2753. marker.end = function () {
  2754. this.range[1] = index;
  2755. this.loc.end.line = lineNumber;
  2756. this.loc.end.column = index - lineStart;
  2757. };
  2758. marker.applyGroup = function (node) {
  2759. if (extra.range) {
  2760. node.groupRange = [this.range[0], this.range[1]];
  2761. }
  2762. if (extra.loc) {
  2763. node.groupLoc = {
  2764. start: {
  2765. line: this.loc.start.line,
  2766. column: this.loc.start.column
  2767. },
  2768. end: {
  2769. line: this.loc.end.line,
  2770. column: this.loc.end.column
  2771. }
  2772. };
  2773. }
  2774. };
  2775. marker.apply = function (node) {
  2776. if (extra.range) {
  2777. node.range = [this.range[0], this.range[1]];
  2778. }
  2779. if (extra.loc) {
  2780. node.loc = {
  2781. start: {
  2782. line: this.loc.start.line,
  2783. column: this.loc.start.column
  2784. },
  2785. end: {
  2786. line: this.loc.end.line,
  2787. column: this.loc.end.column
  2788. }
  2789. };
  2790. }
  2791. };
  2792. return marker;
  2793. }
  2794. function trackGroupExpression() {
  2795. var marker, expr;
  2796. skipComment();
  2797. marker = createLocationMarker();
  2798. expect('(');
  2799. expr = parseExpression();
  2800. expect(')');
  2801. marker.end();
  2802. marker.applyGroup(expr);
  2803. return expr;
  2804. }
  2805. function trackLeftHandSideExpression() {
  2806. var marker, expr, property;
  2807. skipComment();
  2808. marker = createLocationMarker();
  2809. expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
  2810. while (match('.') || match('[')) {
  2811. if (match('[')) {
  2812. property = parseComputedMember();
  2813. expr = delegate.createMemberExpression('[', expr, property);
  2814. marker.end();
  2815. marker.apply(expr);
  2816. } else {
  2817. property = parseNonComputedMember();
  2818. expr = delegate.createMemberExpression('.', expr, property);
  2819. marker.end();
  2820. marker.apply(expr);
  2821. }
  2822. }
  2823. return expr;
  2824. }
  2825. function trackLeftHandSideExpressionAllowCall() {
  2826. var marker, expr, args, property;
  2827. skipComment();
  2828. marker = createLocationMarker();
  2829. expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
  2830. while (match('.') || match('[') || match('(')) {
  2831. if (match('(')) {
  2832. args = parseArguments();
  2833. expr = delegate.createCallExpression(expr, args);
  2834. marker.end();
  2835. marker.apply(expr);
  2836. } else if (match('[')) {
  2837. property = parseComputedMember();
  2838. expr = delegate.createMemberExpression('[', expr, property);
  2839. marker.end();
  2840. marker.apply(expr);
  2841. } else {
  2842. property = parseNonComputedMember();
  2843. expr = delegate.createMemberExpression('.', expr, property);
  2844. marker.end();
  2845. marker.apply(expr);
  2846. }
  2847. }
  2848. return expr;
  2849. }
  2850. function filterGroup(node) {
  2851. var n, i, entry;
  2852. n = (Object.prototype.toString.apply(node) === '[object Array]') ? [] : {};
  2853. for (i in node) {
  2854. if (node.hasOwnProperty(i) && i !== 'groupRange' && i !== 'groupLoc') {
  2855. entry = node[i];
  2856. if (entry === null || typeof entry !== 'object' || entry instanceof RegExp) {
  2857. n[i] = entry;
  2858. } else {
  2859. n[i] = filterGroup(entry);
  2860. }
  2861. }
  2862. }
  2863. return n;
  2864. }
  2865. function wrapTrackingFunction(range, loc) {
  2866. return function (parseFunction) {
  2867. function isBinary(node) {
  2868. return node.type === Syntax.LogicalExpression ||
  2869. node.type === Syntax.BinaryExpression;
  2870. }
  2871. function visit(node) {
  2872. var start, end;
  2873. if (isBinary(node.left)) {
  2874. visit(node.left);
  2875. }
  2876. if (isBinary(node.right)) {
  2877. visit(node.right);
  2878. }
  2879. if (range) {
  2880. if (node.left.groupRange || node.right.groupRange) {
  2881. start = node.left.groupRange ? node.left.groupRange[0] : node.left.range[0];
  2882. end = node.right.groupRange ? node.right.groupRange[1] : node.right.range[1];
  2883. node.range = [start, end];
  2884. } else if (typeof node.range === 'undefined') {
  2885. start = node.left.range[0];
  2886. end = node.right.range[1];
  2887. node.range = [start, end];
  2888. }
  2889. }
  2890. if (loc) {
  2891. if (node.left.groupLoc || node.right.groupLoc) {
  2892. start = node.left.groupLoc ? node.left.groupLoc.start : node.left.loc.start;
  2893. end = node.right.groupLoc ? node.right.groupLoc.end : node.right.loc.end;
  2894. node.loc = {
  2895. start: start,
  2896. end: end
  2897. };
  2898. } else if (typeof node.loc === 'undefined') {
  2899. node.loc = {
  2900. start: node.left.loc.start,
  2901. end: node.right.loc.end
  2902. };
  2903. }
  2904. }
  2905. }
  2906. return function () {
  2907. var marker, node;
  2908. skipComment();
  2909. marker = createLocationMarker();
  2910. node = parseFunction.apply(null, arguments);
  2911. marker.end();
  2912. if (range && typeof node.range === 'undefined') {
  2913. marker.apply(node);
  2914. }
  2915. if (loc && typeof node.loc === 'undefined') {
  2916. marker.apply(node);
  2917. }
  2918. if (isBinary(node)) {
  2919. visit(node);
  2920. }
  2921. return node;
  2922. };
  2923. };
  2924. }
  2925. function patch() {
  2926. var wrapTracking;
  2927. if (extra.comments) {
  2928. extra.skipComment = skipComment;
  2929. skipComment = scanComment;
  2930. }
  2931. if (extra.range || extra.loc) {
  2932. extra.parseGroupExpression = parseGroupExpression;
  2933. extra.parseLeftHandSideExpression = parseLeftHandSideExpression;
  2934. extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall;
  2935. parseGroupExpression = trackGroupExpression;
  2936. parseLeftHandSideExpression = trackLeftHandSideExpression;
  2937. parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall;
  2938. wrapTracking = wrapTrackingFunction(extra.range, extra.loc);
  2939. extra.parseAssignmentExpression = parseAssignmentExpression;
  2940. extra.parseBinaryExpression = parseBinaryExpression;
  2941. extra.parseBlock = parseBlock;
  2942. extra.parseFunctionSourceElements = parseFunctionSourceElements;
  2943. extra.parseCatchClause = parseCatchClause;
  2944. extra.parseComputedMember = parseComputedMember;
  2945. extra.parseConditionalExpression = parseConditionalExpression;
  2946. extra.parseConstLetDeclaration = parseConstLetDeclaration;
  2947. extra.parseExpression = parseExpression;
  2948. extra.parseForVariableDeclaration = parseForVariableDeclaration;
  2949. extra.parseFunctionDeclaration = parseFunctionDeclaration;
  2950. extra.parseFunctionExpression = parseFunctionExpression;
  2951. extra.parseNewExpression = parseNewExpression;
  2952. extra.parseNonComputedProperty = parseNonComputedProperty;
  2953. extra.parseObjectProperty = parseObjectProperty;
  2954. extra.parseObjectPropertyKey = parseObjectPropertyKey;
  2955. extra.parsePostfixExpression = parsePostfixExpression;
  2956. extra.parsePrimaryExpression = parsePrimaryExpression;
  2957. extra.parseProgram = parseProgram;
  2958. extra.parsePropertyFunction = parsePropertyFunction;
  2959. extra.parseStatement = parseStatement;
  2960. extra.parseSwitchCase = parseSwitchCase;
  2961. extra.parseUnaryExpression = parseUnaryExpression;
  2962. extra.parseVariableDeclaration = parseVariableDeclaration;
  2963. extra.parseVariableIdentifier = parseVariableIdentifier;
  2964. parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression);
  2965. parseBinaryExpression = wrapTracking(extra.parseBinaryExpression);
  2966. parseBlock = wrapTracking(extra.parseBlock);
  2967. parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements);
  2968. parseCatchClause = wrapTracking(extra.parseCatchClause);
  2969. parseComputedMember = wrapTracking(extra.parseComputedMember);
  2970. parseConditionalExpression = wrapTracking(extra.parseConditionalExpression);
  2971. parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration);
  2972. parseExpression = wrapTracking(extra.parseExpression);
  2973. parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration);
  2974. parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration);
  2975. parseFunctionExpression = wrapTracking(extra.parseFunctionExpression);
  2976. parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression);
  2977. parseNewExpression = wrapTracking(extra.parseNewExpression);
  2978. parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty);
  2979. parseObjectProperty = wrapTracking(extra.parseObjectProperty);
  2980. parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey);
  2981. parsePostfixExpression = wrapTracking(extra.parsePostfixExpression);
  2982. parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression);
  2983. parseProgram = wrapTracking(extra.parseProgram);
  2984. parsePropertyFunction = wrapTracking(extra.parsePropertyFunction);
  2985. parseStatement = wrapTracking(extra.parseStatement);
  2986. parseSwitchCase = wrapTracking(extra.parseSwitchCase);
  2987. parseUnaryExpression = wrapTracking(extra.parseUnaryExpression);
  2988. parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration);
  2989. parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier);
  2990. }
  2991. if (typeof extra.tokens !== 'undefined') {
  2992. extra.advance = advance;
  2993. extra.scanRegExp = scanRegExp;
  2994. advance = collectToken;
  2995. scanRegExp = collectRegex;
  2996. }
  2997. }
  2998. function unpatch() {
  2999. if (typeof extra.skipComment === 'function') {
  3000. skipComment = extra.skipComment;
  3001. }
  3002. if (extra.range || extra.loc) {
  3003. parseAssignmentExpression = extra.parseAssignmentExpression;
  3004. parseBinaryExpression = extra.parseBinaryExpression;
  3005. parseBlock = extra.parseBlock;
  3006. parseFunctionSourceElements = extra.parseFunctionSourceElements;
  3007. parseCatchClause = extra.parseCatchClause;
  3008. parseComputedMember = extra.parseComputedMember;
  3009. parseConditionalExpression = extra.parseConditionalExpression;
  3010. parseConstLetDeclaration = extra.parseConstLetDeclaration;
  3011. parseExpression = extra.parseExpression;
  3012. parseForVariableDeclaration = extra.parseForVariableDeclaration;
  3013. parseFunctionDeclaration = extra.parseFunctionDeclaration;
  3014. parseFunctionExpression = extra.parseFunctionExpression;
  3015. parseGroupExpression = extra.parseGroupExpression;
  3016. parseLeftHandSideExpression = extra.parseLeftHandSideExpression;
  3017. parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall;
  3018. parseNewExpression = extra.parseNewExpression;
  3019. parseNonComputedProperty = extra.parseNonComputedProperty;
  3020. parseObjectProperty = extra.parseObjectProperty;
  3021. parseObjectPropertyKey = extra.parseObjectPropertyKey;
  3022. parsePrimaryExpression = extra.parsePrimaryExpression;
  3023. parsePostfixExpression = extra.parsePostfixExpression;
  3024. parseProgram = extra.parseProgram;
  3025. parsePropertyFunction = extra.parsePropertyFunction;
  3026. parseStatement = extra.parseStatement;
  3027. parseSwitchCase = extra.parseSwitchCase;
  3028. parseUnaryExpression = extra.parseUnaryExpression;
  3029. parseVariableDeclaration = extra.parseVariableDeclaration;
  3030. parseVariableIdentifier = extra.parseVariableIdentifier;
  3031. }
  3032. if (typeof extra.scanRegExp === 'function') {
  3033. advance = extra.advance;
  3034. scanRegExp = extra.scanRegExp;
  3035. }
  3036. }
  3037. function stringToArray(str) {
  3038. var length = str.length,
  3039. result = [],
  3040. i;
  3041. for (i = 0; i < length; ++i) {
  3042. result[i] = str.charAt(i);
  3043. }
  3044. return result;
  3045. }
  3046. // This is used to modify the delegate.
  3047. function extend(object, properties) {
  3048. var entry, result = {};
  3049. for (entry in object) {
  3050. if (object.hasOwnProperty(entry)) {
  3051. result[entry] = object[entry];
  3052. }
  3053. }
  3054. for (entry in properties) {
  3055. if (properties.hasOwnProperty(entry)) {
  3056. result[entry] = properties[entry];
  3057. }
  3058. }
  3059. return result;
  3060. }
  3061. function parse(code, options) {
  3062. var program, toString;
  3063. toString = String;
  3064. if (typeof code !== 'string' && !(code instanceof String)) {
  3065. code = toString(code);
  3066. }
  3067. delegate = SyntaxTreeDelegate;
  3068. source = code;
  3069. index = 0;
  3070. lineNumber = (source.length > 0) ? 1 : 0;
  3071. lineStart = 0;
  3072. length = source.length;
  3073. lookahead = null;
  3074. state = {
  3075. allowIn: true,
  3076. labelSet: {},
  3077. inFunctionBody: false,
  3078. inIteration: false,
  3079. inSwitch: false
  3080. };
  3081. extra = {};
  3082. if (typeof options !== 'undefined') {
  3083. extra.range = (typeof options.range === 'boolean') && options.range;
  3084. extra.loc = (typeof options.loc === 'boolean') && options.loc;
  3085. if (typeof options.tokens === 'boolean' && options.tokens) {
  3086. extra.tokens = [];
  3087. }
  3088. if (typeof options.comment === 'boolean' && options.comment) {
  3089. extra.comments = [];
  3090. }
  3091. if (typeof options.tolerant === 'boolean' && options.tolerant) {
  3092. extra.errors = [];
  3093. }
  3094. }
  3095. if (length > 0) {
  3096. if (typeof source[0] === 'undefined') {
  3097. // Try first to convert to a string. This is good as fast path
  3098. // for old IE which understands string indexing for string
  3099. // literals only and not for string object.
  3100. if (code instanceof String) {
  3101. source = code.valueOf();
  3102. }
  3103. // Force accessing the characters via an array.
  3104. if (typeof source[0] === 'undefined') {
  3105. source = stringToArray(code);
  3106. }
  3107. }
  3108. }
  3109. patch();
  3110. try {
  3111. program = parseProgram();
  3112. if (typeof extra.comments !== 'undefined') {
  3113. filterCommentLocation();
  3114. program.comments = extra.comments;
  3115. }
  3116. if (typeof extra.tokens !== 'undefined') {
  3117. filterTokenLocation();
  3118. program.tokens = extra.tokens;
  3119. }
  3120. if (typeof extra.errors !== 'undefined') {
  3121. program.errors = extra.errors;
  3122. }
  3123. if (extra.range || extra.loc) {
  3124. program.body = filterGroup(program.body);
  3125. }
  3126. } catch (e) {
  3127. throw e;
  3128. } finally {
  3129. unpatch();
  3130. extra = {};
  3131. }
  3132. return program;
  3133. }
  3134. // Sync with package.json and component.json.
  3135. exports.version = '1.1.0-dev';
  3136. exports.parse = parse;
  3137. // Deep copy.
  3138. exports.Syntax = (function () {
  3139. var name, types = {};
  3140. if (typeof Object.create === 'function') {
  3141. types = Object.create(null);
  3142. }
  3143. for (name in Syntax) {
  3144. if (Syntax.hasOwnProperty(name)) {
  3145. types[name] = Syntax[name];
  3146. }
  3147. }
  3148. if (typeof Object.freeze === 'function') {
  3149. Object.freeze(types);
  3150. }
  3151. return types;
  3152. }());
  3153. }(typeof exports === 'undefined' ? (esprima = {}) : exports));
  3154. /* vim: set sw=4 ts=4 et tw=80 : */
  3155. /* Falafel Code */
  3156. var parse = (typeof exports === 'undefined' ? esprima : require("./esprima")).parse;
  3157. (typeof exports === 'undefined' ? window : exports).falafel = function (src, opts, fn,srcName) {
  3158. if (typeof opts === 'function') {
  3159. fn = opts;
  3160. opts = {};
  3161. }
  3162. if (typeof src === 'object') {
  3163. opts = src;
  3164. src = opts.source;
  3165. delete opts.source;
  3166. }
  3167. src = src || opts.source;
  3168. opts.range = true;
  3169. if (typeof src !== 'string') src = String(src);
  3170. var ast = parse(src, opts);
  3171. var result = {
  3172. chunks : src.split(''),
  3173. toString : function () { return result.chunks.join(''); },
  3174. inspect : function () { return result.toString(); }
  3175. };
  3176. var index = 0;
  3177. (function walk (node, parent) {
  3178. insertHelpers(node, parent, result.chunks);
  3179. Object.keys(node).forEach(function (key) {
  3180. if (key === 'parent') return;
  3181. var child = node[key];
  3182. if (Array.isArray(child)) {
  3183. child.forEach(function (c) {
  3184. if (c && typeof c.type === 'string') {
  3185. walk(c, node);
  3186. }
  3187. });
  3188. }
  3189. else if (child && typeof child.type === 'string') {
  3190. insertHelpers(child, node, result.chunks);
  3191. walk(child, node);
  3192. }
  3193. });
  3194. fn(node,srcName);
  3195. })(ast, undefined);
  3196. return result;
  3197. };
  3198. function insertHelpers (node, parent, chunks) {
  3199. if (!node.range) return;
  3200. node.parent = parent;
  3201. node.source = function () {
  3202. return chunks.slice(
  3203. node.range[0], node.range[1]
  3204. ).join('');
  3205. };
  3206. if (node.update && typeof node.update === 'object') {
  3207. var prev = node.update;
  3208. Object.keys(prev).forEach(function (key) {
  3209. update[key] = prev[key];
  3210. });
  3211. node.update = update;
  3212. }
  3213. else {
  3214. node.update = update;
  3215. }
  3216. function update (s) {
  3217. chunks[node.range[0]] = s;
  3218. for (var i = node.range[0] + 1; i < node.range[1]; i++) {
  3219. chunks[i] = '';
  3220. }
  3221. }
  3222. }
  3223. var startTest=true;
  3224. /* Require JS Code */
  3225. if (typeof requirejs === "undefined" && typeof require === "undefined" && typeof define === "undefined"){
  3226. /*
  3227. RequireJS 2.1.1 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
  3228. Available via the MIT or new BSD license.
  3229. see: http://github.com/jrburke/requirejs for details
  3230. */
  3231. var requirejs,require,define;
  3232. (function(W){function D(b){return M.call(b)==="[object Function]"}function E(b){return M.call(b)==="[object Array]"}function t(b,c){if(b){var d;for(d=0;d<b.length;d+=1)if(b[d]&&c(b[d],d,b))break}}function N(b,c){if(b){var d;for(d=b.length-1;d>-1;d-=1)if(b[d]&&c(b[d],d,b))break}}function A(b,c){for(var d in b)if(b.hasOwnProperty(d)&&c(b[d],d))break}function O(b,c,d,g){c&&A(c,function(c,j){if(d||!F.call(b,j))g&&typeof c!=="string"?(b[j]||(b[j]={}),O(b[j],c,d,g)):b[j]=c});return b}function r(b,c){return function(){return c.apply(b,
  3233. arguments)}}function X(b){if(!b)return b;var c=W;t(b.split("."),function(b){c=c[b]});return c}function G(b,c,d,g){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=g;if(d)c.originalError=d;return c}function ba(){if(H&&H.readyState==="interactive")return H;N(document.getElementsByTagName("script"),function(b){if(b.readyState==="interactive")return H=b});return H}var g,s,u,y,q,B,H,I,Y,Z,ca=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,da=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
  3234. $=/\.js$/,ea=/^\.\//;s=Object.prototype;var M=s.toString,F=s.hasOwnProperty,fa=Array.prototype.splice,v=!!(typeof window!=="undefined"&&navigator&&document),aa=!v&&typeof importScripts!=="undefined",ga=v&&navigator.platform==="PLAYSTATION 3"?/^complete$/:/^(complete|loaded)$/,R=typeof opera!=="undefined"&&opera.toString()==="[object Opera]",w={},n={},P=[],J=!1;if(typeof define==="undefined"){if(typeof requirejs!=="undefined"){if(D(requirejs))return;n=requirejs;requirejs=void 0}typeof require!=="undefined"&&
  3235. !D(require)&&(n=require,require=void 0);g=requirejs=function(b,c,d,p){var i,j="_";!E(b)&&typeof b!=="string"&&(i=b,E(c)?(b=c,c=d,d=p):b=[]);if(i&&i.context)j=i.context;(p=w[j])||(p=w[j]=g.s.newContext(j));i&&p.configure(i);return p.require(b,c,d)};g.config=function(b){return g(b)};g.nextTick=typeof setTimeout!=="undefined"?function(b){setTimeout(b,4)}:function(b){b()};require||(require=g);g.version="2.1.1";g.jsExtRegExp=/^\/|:|\?|\.js$/;g.isBrowser=v;s=g.s={contexts:w,newContext:function(b){function c(a,
  3236. f,x){var e,m,b,c,d,h,i,g=f&&f.split("/");e=g;var j=k.map,l=j&&j["*"];if(a&&a.charAt(0)===".")if(f){e=k.pkgs[f]?g=[f]:g.slice(0,g.length-1);f=a=e.concat(a.split("/"));for(e=0;f[e];e+=1)if(m=f[e],m===".")f.splice(e,1),e-=1;else if(m==="..")if(e===1&&(f[2]===".."||f[0]===".."))break;else e>0&&(f.splice(e-1,2),e-=2);e=k.pkgs[f=a[0]];a=a.join("/");e&&a===f+"/"+e.main&&(a=f)}else a.indexOf("./")===0&&(a=a.substring(2));if(x&&(g||l)&&j){f=a.split("/");for(e=f.length;e>0;e-=1){b=f.slice(0,e).join("/");if(g)for(m=
  3237. g.length;m>0;m-=1)if(x=j[g.slice(0,m).join("/")])if(x=x[b]){c=x;d=e;break}if(c)break;!h&&l&&l[b]&&(h=l[b],i=e)}!c&&h&&(c=h,d=i);c&&(f.splice(0,d,c),a=f.join("/"))}return a}function d(a){v&&t(document.getElementsByTagName("script"),function(f){if(f.getAttribute("data-requiremodule")===a&&f.getAttribute("data-requirecontext")===h.contextName)return f.parentNode.removeChild(f),!0})}function p(a){var f=k.paths[a];if(f&&E(f)&&f.length>1)return d(a),f.shift(),h.require.undef(a),h.require([a]),!0}function i(a){var f,
  3238. b=a?a.indexOf("!"):-1;b>-1&&(f=a.substring(0,b),a=a.substring(b+1,a.length));return[f,a]}function j(a,f,b,e){var m,K,d=null,g=f?f.name:null,j=a,l=!0,k="";a||(l=!1,a="_@r"+(M+=1));a=i(a);d=a[0];a=a[1];d&&(d=c(d,g,e),K=o[d]);a&&(d?k=K&&K.normalize?K.normalize(a,function(a){return c(a,g,e)}):c(a,g,e):(k=c(a,g,e),a=i(k),d=a[0],k=a[1],b=!0,m=h.nameToUrl(k)));b=d&&!K&&!b?"_unnormalized"+(N+=1):"";return{prefix:d,name:k,parentMap:f,unnormalized:!!b,url:m,originalName:j,isDefine:l,id:(d?d+"!"+k:k)+b}}function n(a){var f=
  3239. a.id,b=l[f];b||(b=l[f]=new h.Module(a));return b}function q(a,f,b){var e=a.id,m=l[e];if(F.call(o,e)&&(!m||m.defineEmitComplete))f==="defined"&&b(o[e]);else n(a).on(f,b)}function z(a,f){var b=a.requireModules,e=!1;if(f)f(a);else if(t(b,function(f){if(f=l[f])f.error=a,f.events.error&&(e=!0,f.emit("error",a))}),!e)g.onError(a)}function s(){P.length&&(fa.apply(C,[C.length-1,0].concat(P)),P=[])}function u(a,f,b){var e=a.map.id;a.error?a.emit("error",a.error):(f[e]=!0,t(a.depMaps,function(e,c){var d=e.id,
  3240. g=l[d];g&&!a.depMatched[c]&&!b[d]&&(f[d]?(a.defineDep(c,o[d]),a.check()):u(g,f,b))}),b[e]=!0)}function w(){var a,f,b,e,m=(b=k.waitSeconds*1E3)&&h.startTime+b<(new Date).getTime(),c=[],g=[],i=!1,j=!0;if(!S){S=!0;A(l,function(b){a=b.map;f=a.id;if(b.enabled&&(a.isDefine||g.push(b),!b.error))if(!b.inited&&m)p(f)?i=e=!0:(c.push(f),d(f));else if(!b.inited&&b.fetched&&a.isDefine&&(i=!0,!a.prefix))return j=!1});if(m&&c.length)return b=G("timeout","Load timeout for modules: "+c,null,c),b.contextName=h.contextName,
  3241. z(b);j&&t(g,function(a){u(a,{},{})});if((!m||e)&&i)if((v||aa)&&!T)T=setTimeout(function(){T=0;w()},50);S=!1}}function y(a){n(j(a[0],null,!0)).init(a[1],a[2])}function B(a){var a=a.currentTarget||a.srcElement,b=h.onScriptLoad;a.detachEvent&&!R?a.detachEvent("onreadystatechange",b):a.removeEventListener("load",b,!1);b=h.onScriptError;a.detachEvent&&!R||a.removeEventListener("error",b,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function I(){var a;for(s();C.length;)if(a=C.shift(),a[0]===
  3242. null)return z(G("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));else y(a)}var S,U,h,L,T,k={waitSeconds:7,baseUrl:"./",paths:{},pkgs:{},shim:{},map:{},config:{}},l={},V={},C=[],o={},Q={},M=1,N=1;L={require:function(a){return a.require?a.require:a.require=h.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=o[a.map.id]={}},module:function(a){return a.module?a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return k.config&&
  3243. k.config[a.map.id]||{}},exports:o[a.map.id]}}};U=function(a){this.events=V[a.id]||{};this.map=a;this.shim=k.shim[a.id];this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};U.prototype={init:function(a,b,c,e){e=e||{};if(!this.inited){this.factory=b;if(c)this.on("error",c);else this.events.error&&(c=r(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=!0;this.ignore=e.ignore;e.enabled||this.enabled?this.enable():this.check()}},
  3244. defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=b)},fetch:function(){if(!this.fetched){this.fetched=!0;h.startTime=(new Date).getTime();var a=this.map;if(this.shim)h.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],r(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=this.map.url;Q[a]||(Q[a]=!0,h.load(this.map.id,a))},check:function(){if(this.enabled&&
  3245. !this.enabling){var a,b,c=this.map.id;b=this.depExports;var e=this.exports,m=this.factory;if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(this.depCount<1&&!this.defined){if(D(m)){if(this.events.error)try{e=h.execCb(c,m,b,e)}catch(d){a=d}else e=h.execCb(c,m,b,e);if(this.map.isDefine)if((b=this.module)&&b.exports!==void 0&&b.exports!==this.exports)e=b.exports;else if(e===void 0&&this.usingExports)e=this.exports;if(a)return a.requireMap=this.map,
  3246. a.requireModules=[this.map.id],a.requireType="define",z(this.error=a)}else e=m;this.exports=e;if(this.map.isDefine&&!this.ignore&&(o[c]=e,g.onResourceLoad))g.onResourceLoad(h,this.map,this.depMaps);delete l[c];this.defined=!0}this.defining=!1;if(this.defined&&!this.defineEmitted)this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=j(a.prefix);this.depMaps.push(d);q(d,"defined",r(this,function(e){var m,
  3247. d;d=this.map.name;var x=this.map.parentMap?this.map.parentMap.name:null,i=h.makeRequire(a.parentMap,{enableBuildCallback:!0,skipMap:!0});if(this.map.unnormalized){if(e.normalize&&(d=e.normalize(d,function(a){return c(a,x,!0)})||""),e=j(a.prefix+"!"+d,this.map.parentMap),q(e,"defined",r(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=l[e.id]){this.depMaps.push(e);if(this.events.error)d.on("error",r(this,function(a){this.emit("error",a)}));d.enable()}}else m=r(this,
  3248. function(a){this.init([],function(){return a},null,{enabled:!0})}),m.error=r(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];A(l,function(a){a.map.id.indexOf(b+"_unnormalized")===0&&delete l[a.map.id]});z(a)}),m.fromText=r(this,function(b,e){var f=a.name,c=j(f),d=J;e&&(b=e);d&&(J=!1);n(c);try{g.exec(b)}catch(x){throw Error("fromText eval for "+f+" failed: "+x);}d&&(J=!0);this.depMaps.push(c);h.completeLoad(f);i([f],m)}),e.load(a.name,i,m,k)}));h.enable(d,this);this.pluginMaps[d.id]=
  3249. d},enable:function(){this.enabling=this.enabled=!0;t(this.depMaps,r(this,function(a,b){var c,e;if(typeof a==="string"){a=j(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=L[a.id]){this.depExports[b]=c(this);return}this.depCount+=1;q(a,"defined",r(this,function(a){this.defineDep(b,a);this.check()}));this.errback&&q(a,"error",this.errback)}c=a.id;e=l[c];!L[c]&&e&&!e.enabled&&h.enable(a,this)}));A(this.pluginMaps,r(this,function(a){var b=l[a.id];b&&!b.enabled&&
  3250. h.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){t(this.events[a],function(a){a(b)});a==="error"&&delete this.events[a]}};h={config:k,contextName:b,registry:l,defined:o,urlFetched:Q,defQueue:C,Module:U,makeModuleMap:j,nextTick:g.nextTick,configure:function(a){a.baseUrl&&a.baseUrl.charAt(a.baseUrl.length-1)!=="/"&&(a.baseUrl+="/");var b=k.pkgs,c=k.shim,e={paths:!0,config:!0,map:!0};A(a,function(a,b){e[b]?
  3251. b==="map"?O(k[b],a,!0,!0):O(k[b],a,!0):k[b]=a});if(a.shim)A(a.shim,function(a,b){E(a)&&(a={deps:a});if(a.exports&&!a.exportsFn)a.exportsFn=h.makeShimExports(a);c[b]=a}),k.shim=c;if(a.packages)t(a.packages,function(a){a=typeof a==="string"?{name:a}:a;b[a.name]={name:a.name,location:a.location||a.name,main:(a.main||"main").replace(ea,"").replace($,"")}}),k.pkgs=b;A(l,function(a,b){if(!a.inited&&!a.map.unnormalized)a.map=j(b)});if(a.deps||a.callback)h.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;
  3252. a.init&&(b=a.init.apply(W,arguments));return b||X(a.exports)}},makeRequire:function(a,f){function d(e,c,i){var k,p;if(f.enableBuildCallback&&c&&D(c))c.__requireJsBuild=!0;if(typeof e==="string"){if(D(c))return z(G("requireargs","Invalid require call"),i);if(a&&L[e])return L[e](l[a.id]);if(g.get)return g.get(h,e,a);k=j(e,a,!1,!0);k=k.id;return!F.call(o,k)?z(G("notloaded",'Module name "'+k+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):o[k]}I();h.nextTick(function(){I();p=
  3253. n(j(null,a));p.skipMap=f.skipMap;p.init(e,c,i,{enabled:!0});w()});return d}f=f||{};O(d,{isBrowser:v,toUrl:function(b){var d=b.lastIndexOf("."),f=null;d!==-1&&(f=b.substring(d,b.length),b=b.substring(0,d));return h.nameToUrl(c(b,a&&a.id,!0),f)},defined:function(b){b=j(b,a,!1,!0).id;return F.call(o,b)},specified:function(b){b=j(b,a,!1,!0).id;return F.call(o,b)||F.call(l,b)}});if(!a)d.undef=function(b){s();var c=j(b,a,!0),d=l[b];delete o[b];delete Q[c.url];delete V[b];if(d){if(d.events.defined)V[b]=
  3254. d.events;delete l[b]}};return d},enable:function(a){l[a.id]&&n(a).enable()},completeLoad:function(a){var b,c,d=k.shim[a]||{},g=d.exports;for(s();C.length;){c=C.shift();if(c[0]===null){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);y(c)}c=l[a];if(!b&&!o[a]&&c&&!c.inited)if(k.enforceDefine&&(!g||!X(g)))if(p(a))return;else return z(G("nodefine","No define call for "+a,null,[a]));else y([a,d.deps||[],d.exportsFn]);w()},nameToUrl:function(a,b){var c,d,i,h,j,l;if(g.jsExtRegExp.test(a))h=a+(b||"");else{c=
  3255. k.paths;d=k.pkgs;h=a.split("/");for(j=h.length;j>0;j-=1)if(l=h.slice(0,j).join("/"),i=d[l],l=c[l]){E(l)&&(l=l[0]);h.splice(0,j,l);break}else if(i){c=a===i.name?i.location+"/"+i.main:i.location;h.splice(0,j,c);break}h=h.join("/");h+=b||(/\?/.test(h)?"":".js");h=(h.charAt(0)==="/"||h.match(/^[\w\+\.\-]+:/)?"":k.baseUrl)+h}return k.urlArgs?h+((h.indexOf("?")===-1?"?":"&")+k.urlArgs):h},load:function(a,b){g.load(h,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if(a.type===
  3256. "load"||ga.test((a.currentTarget||a.srcElement).readyState))H=null,a=B(a),h.completeLoad(a.id)},onScriptError:function(a){var b=B(a);if(!p(b.id))return z(G("scripterror","Script error",a,[b.id]))}};h.require=h.makeRequire();return h}};g({});t(["toUrl","undef","defined","specified"],function(b){g[b]=function(){var c=w._;return c.require[b].apply(c,arguments)}});if(v&&(u=s.head=document.getElementsByTagName("head")[0],y=document.getElementsByTagName("base")[0]))u=s.head=y.parentNode;g.onError=function(b){throw b;
  3257. };g.load=function(b,c,d){var g=b&&b.config||{},i;if(v)return i=g.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),i.type=g.scriptType||"text/javascript",i.charset="utf-8",i.async=!0,i.setAttribute("data-requirecontext",b.contextName),i.setAttribute("data-requiremodule",c),i.attachEvent&&!(i.attachEvent.toString&&i.attachEvent.toString().indexOf("[native code")<0)&&!R?(J=!0,i.attachEvent("onreadystatechange",b.onScriptLoad)):(i.addEventListener("load",
  3258. b.onScriptLoad,!1),i.addEventListener("error",b.onScriptError,!1)),i.src=d,I=i,y?u.insertBefore(i,y):u.appendChild(i),I=null,i;else aa&&(importScripts(d),b.completeLoad(c))};v&&N(document.getElementsByTagName("script"),function(b){if(!u)u=b.parentNode;if(q=b.getAttribute("data-main")){if(!n.baseUrl)B=q.split("/"),Y=B.pop(),Z=B.length?B.join("/")+"/":"./",n.baseUrl=Z,q=Y;q=q.replace($,"");n.deps=n.deps?n.deps.concat(q):[q];return!0}});define=function(b,c,d){var g,i;typeof b!=="string"&&(d=c,c=b,b=
  3259. null);E(c)||(d=c,c=[]);!c.length&&D(d)&&d.length&&(d.toString().replace(ca,"").replace(da,function(b,d){c.push(d)}),c=(d.length===1?["require"]:["require","exports","module"]).concat(c));if(J&&(g=I||ba()))b||(b=g.getAttribute("data-requiremodule")),i=w[g.getAttribute("data-requirecontext")];(i?i.defQueue:P).push([b,c,d])};define.amd={jQuery:!0};g.exec=function(b){return eval(b)};g(n)}})(this);
  3260. }else{
  3261. startTest=false;
  3262. }
  3263. /* Reporter Code */
  3264. var Reporter = function(blanket){
  3265. var cssSytle = "#blanket-main {margin:2px;background:#EEE;color:#333;clear:both;font-family:'Helvetica Neue Light', 'HelveticaNeue-Light', 'Helvetica Neue', Calibri, Helvetica, Arial, sans-serif;} #blanket-main a {color:#333;text-decoration:none;} #blanket-main a:hover {text-decoration:underline;} .blanket {margin:0;padding:5px;clear:both;} .bl-error {color:red;}.bl-success {color:#5E7D00;} .bl-file{width:200px;} .bl-cl{float:left;} .blanket div.rs {margin-left:350px; width:150px;} .bl-nb {padding-right:10px;}",
  3266. successRate = 60,
  3267. head = document.head,
  3268. fileNumber = 0,
  3269. body = document.body,
  3270. headerContent,
  3271. bodyContent = "<div id='blanket-main'><div class='blanket bl-title'><div class='bl-cl bl-file'>Blanket.js results</div><div class='bl-cl rs'>Coverage (%)</div><div class='bl-cl rs'>Covered/Total Smts.</div></div>",
  3272. fileTemplate = "<div class='blanket {{statusclass}}'><div class='bl-cl bl-file'><span class='bl-nb'>{{fileNumber}}.</span><a href='#'>{{file}}</a></div><div class='bl-cl rs'>{{percentage}} %</div><div class='bl-cl rs'>{{numberCovered}}/{{totalSmts}}</div><div style='clear:both;'></div></div>";
  3273. var percentage = function(number, total) {
  3274. return (Math.round(((number/total) * 100)*100)/100);
  3275. };
  3276. var appendHtml = function (el, str) {
  3277. var div = document.createElement('div');
  3278. div.innerHTML = str;
  3279. el.appendChild(div);
  3280. };
  3281. var appendStyle = function (el, str) {
  3282. var style = document.createElement('style');
  3283. style.innerHTML = str;
  3284. el.appendChild(style);
  3285. };
  3286. var files = blanket.files;
  3287. for(var file in files)
  3288. {
  3289. fileNumber += 1;
  3290. var statsForFile = files[file],
  3291. totalSmts = statsForFile.length-1,
  3292. numberOfFilesCovered = 0;
  3293. for(var i = 0; i < statsForFile.length; i++)
  3294. {
  3295. if(statsForFile[i]) {
  3296. numberOfFilesCovered += 1;
  3297. }
  3298. }
  3299. var result = percentage(numberOfFilesCovered, totalSmts);
  3300. var output = fileTemplate.replace("{{file}}", file)
  3301. .replace("{{percentage}}",result)
  3302. .replace("{{numberCovered}}", numberOfFilesCovered)
  3303. .replace("{{fileNumber}}", fileNumber)
  3304. .replace("{{totalSmts}}", totalSmts);
  3305. if(result < successRate)
  3306. {
  3307. output = output.replace("{{statusclass}}", "bl-error");
  3308. } else {
  3309. output = output.replace("{{statusclass}}", "bl-success");
  3310. }
  3311. bodyContent += output;
  3312. }
  3313. bodyContent += "</div>"; //closing main
  3314. appendStyle(head, cssSytle);
  3315. //appendStyle(body, headerContent);
  3316. appendHtml(body, bodyContent);
  3317. //appendHtml(body, '</div>');
  3318. };
  3319. /* Blanket Code */
  3320. var parseAndModify = (typeof exports === 'undefined' ? window.falafel : require("./falafel").falafel);
  3321. (typeof exports === 'undefined' ? window : exports).blanket = (function(){
  3322. var linesToAddTracking = [
  3323. "ExpressionStatement",
  3324. "LabeledStatement" ,
  3325. "BreakStatement" ,
  3326. "ContinueStatement" ,
  3327. "VariableDeclaration",
  3328. "ReturnStatement" ,
  3329. "ThrowStatement" ,
  3330. "Line",
  3331. "TryStatement" ,
  3332. "FunctionDeclaration" ,
  3333. "IfStatement" ,
  3334. "WhileStatement" ,
  3335. "DoWhileStatement" ,
  3336. "ForStatement" ,
  3337. "ForInStatement" ,
  3338. "SwitchStatement" ,
  3339. "WithStatement"
  3340. ],
  3341. linesToAddBrackets = [
  3342. "IfStatement" ,
  3343. "WhileStatement" ,
  3344. "DoWhileStatement" ,
  3345. "ForStatement" ,
  3346. "ForInStatement" ,
  3347. "WithStatement"
  3348. ],
  3349. astgen = {
  3350. variable: function (name) { return { type: "Identifier", name: name }; },
  3351. stringLiteral: function (str) { return { type: "Literal", value: String(str) }; },
  3352. numericLiteral: function (num) { return { type: "Literal", value: Number(num) }; },
  3353. statement: function (contents) { return { type: "ExpressionStatement", expression: contents }; },
  3354. dot: function (obj, field) { return { type: "MemberExpression", computed: false, object: obj, property: field }; },
  3355. subscript: function (obj, sub) { return { type: "MemberExpression", computed: true, object: obj, property: sub }; },
  3356. postIncrement: function (obj) { return { type: "UpdateExpression", operator: '++', prefix: false, argument: obj }; },
  3357. sequence: function (one, two) { return { type: "SequenceExpression", expressions: [one, two] }; }
  3358. };
  3359. covVar = (typeof window === 'undefined' ? "_$jscoverage" : "window._$blanket" ),
  3360. blanket = {
  3361. loadOnly: "",
  3362. instrument: function(config, next){
  3363. var inFile = config.inputFile,
  3364. inFileName = config.inputFileName;
  3365. var sourceArray = this._prepareSource(inFile);
  3366. var instrumented = parseAndModify(inFile,{loc:true,comment:true}, this._addTracking,inFileName);
  3367. instrumented = this._trackingSetup(inFileName,sourceArray)+instrumented;
  3368. next(instrumented);
  3369. },
  3370. _prepareSource: function(source){
  3371. return source.replace(/'/g,"\\'").replace(/(\r\n|\n|\r)/gm,"\n").split('\n');
  3372. },
  3373. _trackingSetup: function(filename,sourceArray){
  3374. var sourceString = sourceArray.join("',\n'");
  3375. var intro = "if (typeof "+covVar+" === 'undefined') "+covVar+" = {};\n";
  3376. intro += "if (typeof "+covVar+"['"+filename+"'] === 'undefined'){";
  3377. intro += covVar+"['"+filename+"']=[];\n";
  3378. intro += covVar+"['"+filename+"'].source=['"+sourceString+"'];\n";
  3379. //initialize array values
  3380. for (var j=1;j<sourceArray.length+1;j++){
  3381. intro += covVar+"['"+filename+"']["+j+"]=0;\n";
  3382. }
  3383. intro += "}";
  3384. return intro;
  3385. },
  3386. _blockifyIf: function(node){
  3387. if (linesToAddBrackets.indexOf(node.type) > -1){
  3388. var bracketsExistObject = node.consequent || node.body;
  3389. var bracketsExistAlt = node.alternate;
  3390. if( bracketsExistAlt && bracketsExistAlt.type != "BlockStatement") {
  3391. bracketsExistAlt.update("{\n"+bracketsExistAlt.source()+"}\n");
  3392. }
  3393. //if (bracketsExistAlt){
  3394. // this._blockifyIf(bracketsExistAlt);
  3395. //}
  3396. if( bracketsExistObject && bracketsExistObject.type != "BlockStatement") {
  3397. bracketsExistObject.update("{\n"+bracketsExistObject.source()+"}\n");
  3398. }
  3399. }
  3400. },
  3401. _addTracking: function (node,filename) {
  3402. blanket._blockifyIf(node);
  3403. if (linesToAddTracking.indexOf(node.type) > -1){
  3404. if (node.type == "VariableDeclaration" &&
  3405. (node.parent.type == "ForStatement" || node.parent.type == "ForInStatement")){
  3406. return;
  3407. }
  3408. if (node.loc && node.loc.start){
  3409. node.update(covVar+"['"+filename+"']["+(node.loc.start.line-1)+"]++;\n"+node.source());
  3410. }else{
  3411. //I don't think we can handle a node with no location
  3412. throw new Error("The instrumenter encountered a node with no location: "+Object.keys(node));
  3413. }
  3414. }
  3415. },
  3416. report: function(coverage_data){
  3417. coverage_data.files = (typeof window === 'undefined' ? _$jscoverage : window._$blanket );
  3418. Reporter(coverage_data);
  3419. }
  3420. };
  3421. return blanket;
  3422. })();
  3423. /* Custom Loader Code */
  3424. var commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
  3425. defineRegExp = /(^|[^\.])define\s*\(/,
  3426. requireRegExp = /(^|[^\.])require\s*\(\s*['"][^'"]+['"]\s*\)/,
  3427. exportsRegExp = /exports\s*=\s*/,
  3428. sourceUrlRegExp = /\/\/@\s+sourceURL=/;
  3429. var blanketEval = function(data){
  3430. return ( window.execScript || function( data ) {
  3431. //borrowed from jquery
  3432. window[ "eval" ].call( window, data );
  3433. } )( data );
  3434. };
  3435. //if requirejs is already being used, we need to have a plugin tells us whether or not to overload this
  3436. var oldloader = requirejs.load;
  3437. requirejs.load = function (context, moduleName, url) {
  3438. var hasLocation = typeof location !== 'undefined' && location.href,
  3439. defaultHostName = hasLocation && location.hostname,
  3440. defaultPort = hasLocation && (location.port || undefined),
  3441. defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, '');
  3442. requirejs.cget(url, function (content) {
  3443. var match = blanket.loadOnly;
  3444. if (url.indexOf(match) > -1){
  3445. var temp = content.replace(commentRegExp, '');
  3446. blanket.instrument({
  3447. inputFile: content,
  3448. inputFileName: url
  3449. },function(instrumented){
  3450. //console.log("instrumented:\n"+instrumented);
  3451. try{
  3452. blanketEval(instrumented);
  3453. context.completeLoad(moduleName);
  3454. }
  3455. catch(err){
  3456. console.log("Error parsing instrumented code: "+err);
  3457. }
  3458. });
  3459. }else{
  3460. oldloader(context, moduleName, url);
  3461. }
  3462. }, function (err) {
  3463. throw err;
  3464. });
  3465. };
  3466. requirejs.createXhr = function () {
  3467. //Would love to dump the ActiveX crap in here. Need IE 6 to die first.
  3468. var xhr, i, progId;
  3469. if (typeof XMLHttpRequest !== "undefined") {
  3470. return new XMLHttpRequest();
  3471. } else if (typeof ActiveXObject !== "undefined") {
  3472. for (i = 0; i < 3; i += 1) {
  3473. progId = progIds[i];
  3474. try {
  3475. xhr = new ActiveXObject(progId);
  3476. } catch (e) {}
  3477. if (xhr) {
  3478. progIds = [progId]; // so faster next time
  3479. break;
  3480. }
  3481. }
  3482. }
  3483. return xhr;
  3484. };
  3485. requirejs.cget = function (url, callback, errback, onXhr) {
  3486. var xhr = requirejs.createXhr();
  3487. xhr.open('GET', url, true);
  3488. //Allow overrides specified in config
  3489. if (onXhr) {
  3490. onXhr(xhr, url);
  3491. }
  3492. xhr.onreadystatechange = function (evt) {
  3493. var status, err;
  3494. //Do not explicitly handle errors, those should be
  3495. //visible via console output in the browser.
  3496. if (xhr.readyState === 4) {
  3497. status = xhr.status;
  3498. if (status > 399 && status < 600) {
  3499. //An http 4xx or 5xx error. Signal an error.
  3500. err = new Error(url + ' HTTP status: ' + status);
  3501. err.xhr = xhr;
  3502. errback(err);
  3503. } else {
  3504. callback(xhr.responseText);
  3505. }
  3506. }
  3507. };
  3508. xhr.send(null);
  3509. };
  3510. function collectPageScripts(){
  3511. var toArray = Array.prototype.slice;
  3512. var scripts = toArray.call(document.scripts);
  3513. var scriptNames = scripts.filter(function(elem){
  3514. return toArray.call(elem.attributes).some(function(es){
  3515. return es.nodeName == "data-cover";
  3516. });
  3517. }).map(function(s){
  3518. return toArray.call(s.attributes).filter(function(sn){
  3519. return sn.nodeName == "src";
  3520. })[0].nodeValue.replace(".js","");
  3521. });
  3522. return scriptNames;
  3523. }
  3524. /* Test Specific Code */
  3525. if (typeof QUnit !== 'undefined'){
  3526. QUnit.config.urlConfig.push({
  3527. id: "coverage",
  3528. label: "Enable coverage",
  3529. tooltip: "Enable code coverage."
  3530. });
  3531. if ( QUnit.urlParams.coverage ) {
  3532. var coverageInfo;
  3533. QUnit.done = function(failures, total) {
  3534. coverageInfo.stats.end = new Date();
  3535. blanket.report(coverageInfo);
  3536. };
  3537. QUnit.moduleStart(function( details ) {
  3538. coverageInfo.stats.suites++;
  3539. });
  3540. QUnit.testStart(function( details ) {
  3541. coverageInfo.stats.tests++;
  3542. coverageInfo.stats.pending++;
  3543. });
  3544. QUnit.testDone(function( details ) {
  3545. if(details.passed == details.total){
  3546. coverageInfo.stats.passes++;
  3547. }else{
  3548. coverageInfo.stats.failures++;
  3549. }
  3550. coverageInfo.stats.pending--;
  3551. });
  3552. QUnit.begin(function(){
  3553. coverageInfo = coverageInfo || {};
  3554. //add the basic info, based on jscoverage
  3555. coverageInfo.instrumentation = "blanket";
  3556. coverageInfo.stats = {
  3557. "suites": 0,
  3558. "tests": 0,
  3559. "passes": 0,
  3560. "pending": 0,
  3561. "failures": 0,
  3562. "start": new Date()
  3563. };
  3564. });
  3565. if (startTest){
  3566. require(collectPageScripts(), function() {
  3567. QUnit.start();
  3568. });
  3569. }
  3570. }else{
  3571. QUnit.start();
  3572. }
  3573. }