escodegen.js 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188
  1. /*
  2. Copyright (C) 2012-2013 Yusuke Suzuki <utatane.tea@gmail.com>
  3. Copyright (C) 2012-2013 Michael Ficarra <escodegen.copyright@michael.ficarra.me>
  4. Copyright (C) 2012-2013 Mathias Bynens <mathias@qiwi.be>
  5. Copyright (C) 2013 Irakli Gozalishvili <rfobic@gmail.com>
  6. Copyright (C) 2012 Robert Gust-Bardon <donate@robert.gust-bardon.org>
  7. Copyright (C) 2012 John Freeman <jfreeman08@gmail.com>
  8. Copyright (C) 2011-2012 Ariya Hidayat <ariya.hidayat@gmail.com>
  9. Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
  10. Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
  11. Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
  12. Redistribution and use in source and binary forms, with or without
  13. modification, are permitted provided that the following conditions are met:
  14. * Redistributions of source code must retain the above copyright
  15. notice, this list of conditions and the following disclaimer.
  16. * Redistributions in binary form must reproduce the above copyright
  17. notice, this list of conditions and the following disclaimer in the
  18. documentation and/or other materials provided with the distribution.
  19. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  23. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. /*global exports:true, generateStatement:true, generateExpression:true, require:true, global:true*/
  31. (function () {
  32. 'use strict';
  33. var Syntax,
  34. Precedence,
  35. BinaryPrecedence,
  36. SourceNode,
  37. estraverse,
  38. esutils,
  39. isArray,
  40. base,
  41. indent,
  42. json,
  43. renumber,
  44. hexadecimal,
  45. quotes,
  46. escapeless,
  47. newline,
  48. space,
  49. parentheses,
  50. semicolons,
  51. safeConcatenation,
  52. directive,
  53. extra,
  54. parse,
  55. sourceMap,
  56. FORMAT_MINIFY,
  57. FORMAT_DEFAULTS;
  58. estraverse = require('estraverse');
  59. esutils = require('esutils');
  60. Syntax = {
  61. AssignmentExpression: 'AssignmentExpression',
  62. ArrayExpression: 'ArrayExpression',
  63. ArrayPattern: 'ArrayPattern',
  64. ArrowFunctionExpression: 'ArrowFunctionExpression',
  65. BlockStatement: 'BlockStatement',
  66. BinaryExpression: 'BinaryExpression',
  67. BreakStatement: 'BreakStatement',
  68. CallExpression: 'CallExpression',
  69. CatchClause: 'CatchClause',
  70. ComprehensionBlock: 'ComprehensionBlock',
  71. ComprehensionExpression: 'ComprehensionExpression',
  72. ConditionalExpression: 'ConditionalExpression',
  73. ContinueStatement: 'ContinueStatement',
  74. DirectiveStatement: 'DirectiveStatement',
  75. DoWhileStatement: 'DoWhileStatement',
  76. DebuggerStatement: 'DebuggerStatement',
  77. EmptyStatement: 'EmptyStatement',
  78. ExportDeclaration: 'ExportDeclaration',
  79. ExpressionStatement: 'ExpressionStatement',
  80. ForStatement: 'ForStatement',
  81. ForInStatement: 'ForInStatement',
  82. ForOfStatement: 'ForOfStatement',
  83. FunctionDeclaration: 'FunctionDeclaration',
  84. FunctionExpression: 'FunctionExpression',
  85. GeneratorExpression: 'GeneratorExpression',
  86. Identifier: 'Identifier',
  87. IfStatement: 'IfStatement',
  88. Literal: 'Literal',
  89. LabeledStatement: 'LabeledStatement',
  90. LogicalExpression: 'LogicalExpression',
  91. MemberExpression: 'MemberExpression',
  92. NewExpression: 'NewExpression',
  93. ObjectExpression: 'ObjectExpression',
  94. ObjectPattern: 'ObjectPattern',
  95. Program: 'Program',
  96. Property: 'Property',
  97. ReturnStatement: 'ReturnStatement',
  98. SequenceExpression: 'SequenceExpression',
  99. SwitchStatement: 'SwitchStatement',
  100. SwitchCase: 'SwitchCase',
  101. ThisExpression: 'ThisExpression',
  102. ThrowStatement: 'ThrowStatement',
  103. TryStatement: 'TryStatement',
  104. UnaryExpression: 'UnaryExpression',
  105. UpdateExpression: 'UpdateExpression',
  106. VariableDeclaration: 'VariableDeclaration',
  107. VariableDeclarator: 'VariableDeclarator',
  108. WhileStatement: 'WhileStatement',
  109. WithStatement: 'WithStatement',
  110. YieldExpression: 'YieldExpression'
  111. };
  112. Precedence = {
  113. Sequence: 0,
  114. Yield: 1,
  115. Assignment: 1,
  116. Conditional: 2,
  117. ArrowFunction: 2,
  118. LogicalOR: 3,
  119. LogicalAND: 4,
  120. BitwiseOR: 5,
  121. BitwiseXOR: 6,
  122. BitwiseAND: 7,
  123. Equality: 8,
  124. Relational: 9,
  125. BitwiseSHIFT: 10,
  126. Additive: 11,
  127. Multiplicative: 12,
  128. Unary: 13,
  129. Postfix: 14,
  130. Call: 15,
  131. New: 16,
  132. Member: 17,
  133. Primary: 18
  134. };
  135. BinaryPrecedence = {
  136. '||': Precedence.LogicalOR,
  137. '&&': Precedence.LogicalAND,
  138. '|': Precedence.BitwiseOR,
  139. '^': Precedence.BitwiseXOR,
  140. '&': Precedence.BitwiseAND,
  141. '==': Precedence.Equality,
  142. '!=': Precedence.Equality,
  143. '===': Precedence.Equality,
  144. '!==': Precedence.Equality,
  145. 'is': Precedence.Equality,
  146. 'isnt': Precedence.Equality,
  147. '<': Precedence.Relational,
  148. '>': Precedence.Relational,
  149. '<=': Precedence.Relational,
  150. '>=': Precedence.Relational,
  151. 'in': Precedence.Relational,
  152. 'instanceof': Precedence.Relational,
  153. '<<': Precedence.BitwiseSHIFT,
  154. '>>': Precedence.BitwiseSHIFT,
  155. '>>>': Precedence.BitwiseSHIFT,
  156. '+': Precedence.Additive,
  157. '-': Precedence.Additive,
  158. '*': Precedence.Multiplicative,
  159. '%': Precedence.Multiplicative,
  160. '/': Precedence.Multiplicative
  161. };
  162. function getDefaultOptions() {
  163. // default options
  164. return {
  165. indent: null,
  166. base: null,
  167. parse: null,
  168. comment: false,
  169. format: {
  170. indent: {
  171. style: ' ',
  172. base: 0,
  173. adjustMultilineComment: false
  174. },
  175. newline: '\n',
  176. space: ' ',
  177. json: false,
  178. renumber: false,
  179. hexadecimal: false,
  180. quotes: 'single',
  181. escapeless: false,
  182. compact: false,
  183. parentheses: true,
  184. semicolons: true,
  185. safeConcatenation: false
  186. },
  187. moz: {
  188. comprehensionExpressionStartsWithAssignment: false,
  189. starlessGenerator: false,
  190. parenthesizedComprehensionBlock: false
  191. },
  192. sourceMap: null,
  193. sourceMapRoot: null,
  194. sourceMapWithCode: false,
  195. directive: false,
  196. verbatim: null
  197. };
  198. }
  199. function stringRepeat(str, num) {
  200. var result = '';
  201. for (num |= 0; num > 0; num >>>= 1, str += str) {
  202. if (num & 1) {
  203. result += str;
  204. }
  205. }
  206. return result;
  207. }
  208. isArray = Array.isArray;
  209. if (!isArray) {
  210. isArray = function isArray(array) {
  211. return Object.prototype.toString.call(array) === '[object Array]';
  212. };
  213. }
  214. function hasLineTerminator(str) {
  215. return (/[\r\n]/g).test(str);
  216. }
  217. function endsWithLineTerminator(str) {
  218. var len = str.length;
  219. return len && esutils.code.isLineTerminator(str.charCodeAt(len - 1));
  220. }
  221. function updateDeeply(target, override) {
  222. var key, val;
  223. function isHashObject(target) {
  224. return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp);
  225. }
  226. for (key in override) {
  227. if (override.hasOwnProperty(key)) {
  228. val = override[key];
  229. if (isHashObject(val)) {
  230. if (isHashObject(target[key])) {
  231. updateDeeply(target[key], val);
  232. } else {
  233. target[key] = updateDeeply({}, val);
  234. }
  235. } else {
  236. target[key] = val;
  237. }
  238. }
  239. }
  240. return target;
  241. }
  242. function generateNumber(value) {
  243. var result, point, temp, exponent, pos;
  244. if (value !== value) {
  245. throw new Error('Numeric literal whose value is NaN');
  246. }
  247. if (value < 0 || (value === 0 && 1 / value < 0)) {
  248. throw new Error('Numeric literal whose value is negative');
  249. }
  250. if (value === 1 / 0) {
  251. return json ? 'null' : renumber ? '1e400' : '1e+400';
  252. }
  253. result = '' + value;
  254. if (!renumber || result.length < 3) {
  255. return result;
  256. }
  257. point = result.indexOf('.');
  258. if (!json && result.charCodeAt(0) === 0x30 /* 0 */ && point === 1) {
  259. point = 0;
  260. result = result.slice(1);
  261. }
  262. temp = result;
  263. result = result.replace('e+', 'e');
  264. exponent = 0;
  265. if ((pos = temp.indexOf('e')) > 0) {
  266. exponent = +temp.slice(pos + 1);
  267. temp = temp.slice(0, pos);
  268. }
  269. if (point >= 0) {
  270. exponent -= temp.length - point - 1;
  271. temp = +(temp.slice(0, point) + temp.slice(point + 1)) + '';
  272. }
  273. pos = 0;
  274. while (temp.charCodeAt(temp.length + pos - 1) === 0x30 /* 0 */) {
  275. --pos;
  276. }
  277. if (pos !== 0) {
  278. exponent -= pos;
  279. temp = temp.slice(0, pos);
  280. }
  281. if (exponent !== 0) {
  282. temp += 'e' + exponent;
  283. }
  284. if ((temp.length < result.length ||
  285. (hexadecimal && value > 1e12 && Math.floor(value) === value && (temp = '0x' + value.toString(16)).length < result.length)) &&
  286. +temp === value) {
  287. result = temp;
  288. }
  289. return result;
  290. }
  291. // Generate valid RegExp expression.
  292. // This function is based on https://github.com/Constellation/iv Engine
  293. function escapeRegExpCharacter(ch, previousIsBackslash) {
  294. // not handling '\' and handling \u2028 or \u2029 to unicode escape sequence
  295. if ((ch & ~1) === 0x2028) {
  296. return (previousIsBackslash ? 'u' : '\\u') + ((ch === 0x2028) ? '2028' : '2029');
  297. } else if (ch === 10 || ch === 13) { // \n, \r
  298. return (previousIsBackslash ? '' : '\\') + ((ch === 10) ? 'n' : 'r');
  299. }
  300. return String.fromCharCode(ch);
  301. }
  302. function generateRegExp(reg) {
  303. var match, result, flags, i, iz, ch, characterInBrack, previousIsBackslash;
  304. result = reg.toString();
  305. if (reg.source) {
  306. // extract flag from toString result
  307. match = result.match(/\/([^/]*)$/);
  308. if (!match) {
  309. return result;
  310. }
  311. flags = match[1];
  312. result = '';
  313. characterInBrack = false;
  314. previousIsBackslash = false;
  315. for (i = 0, iz = reg.source.length; i < iz; ++i) {
  316. ch = reg.source.charCodeAt(i);
  317. if (!previousIsBackslash) {
  318. if (characterInBrack) {
  319. if (ch === 93) { // ]
  320. characterInBrack = false;
  321. }
  322. } else {
  323. if (ch === 47) { // /
  324. result += '\\';
  325. } else if (ch === 91) { // [
  326. characterInBrack = true;
  327. }
  328. }
  329. result += escapeRegExpCharacter(ch, previousIsBackslash);
  330. previousIsBackslash = ch === 92; // \
  331. } else {
  332. // if new RegExp("\\\n') is provided, create /\n/
  333. result += escapeRegExpCharacter(ch, previousIsBackslash);
  334. // prevent like /\\[/]/
  335. previousIsBackslash = false;
  336. }
  337. }
  338. return '/' + result + '/' + flags;
  339. }
  340. return result;
  341. }
  342. function escapeAllowedCharacter(code, next) {
  343. var hex, result = '\\';
  344. switch (code) {
  345. case 0x08 /* \b */:
  346. result += 'b';
  347. break;
  348. case 0x0C /* \f */:
  349. result += 'f';
  350. break;
  351. case 0x09 /* \t */:
  352. result += 't';
  353. break;
  354. default:
  355. hex = code.toString(16).toUpperCase();
  356. if (json || code > 0xFF) {
  357. result += 'u' + '0000'.slice(hex.length) + hex;
  358. } else if (code === 0x0000 && !esutils.code.isDecimalDigit(next)) {
  359. result += '0';
  360. } else if (code === 0x000B /* \v */) { // '\v'
  361. result += 'x0B';
  362. } else {
  363. result += 'x' + '00'.slice(hex.length) + hex;
  364. }
  365. break;
  366. }
  367. return result;
  368. }
  369. function escapeDisallowedCharacter(code) {
  370. var result = '\\';
  371. switch (code) {
  372. case 0x5C /* \ */:
  373. result += '\\';
  374. break;
  375. case 0x0A /* \n */:
  376. result += 'n';
  377. break;
  378. case 0x0D /* \r */:
  379. result += 'r';
  380. break;
  381. case 0x2028:
  382. result += 'u2028';
  383. break;
  384. case 0x2029:
  385. result += 'u2029';
  386. break;
  387. default:
  388. throw new Error('Incorrectly classified character');
  389. }
  390. return result;
  391. }
  392. function escapeDirective(str) {
  393. var i, iz, code, quote;
  394. quote = quotes === 'double' ? '"' : '\'';
  395. for (i = 0, iz = str.length; i < iz; ++i) {
  396. code = str.charCodeAt(i);
  397. if (code === 0x27 /* ' */) {
  398. quote = '"';
  399. break;
  400. } else if (code === 0x22 /* " */) {
  401. quote = '\'';
  402. break;
  403. } else if (code === 0x5C /* \ */) {
  404. ++i;
  405. }
  406. }
  407. return quote + str + quote;
  408. }
  409. function escapeString(str) {
  410. var result = '', i, len, code, singleQuotes = 0, doubleQuotes = 0, single, quote;
  411. for (i = 0, len = str.length; i < len; ++i) {
  412. code = str.charCodeAt(i);
  413. if (code === 0x27 /* ' */) {
  414. ++singleQuotes;
  415. } else if (code === 0x22 /* " */) {
  416. ++doubleQuotes;
  417. } else if (code === 0x2F /* / */ && json) {
  418. result += '\\';
  419. } else if (esutils.code.isLineTerminator(code) || code === 0x5C /* \ */) {
  420. result += escapeDisallowedCharacter(code);
  421. continue;
  422. } else if ((json && code < 0x20 /* SP */) || !(json || escapeless || (code >= 0x20 /* SP */ && code <= 0x7E /* ~ */))) {
  423. result += escapeAllowedCharacter(code, str.charCodeAt(i + 1));
  424. continue;
  425. }
  426. result += String.fromCharCode(code);
  427. }
  428. single = !(quotes === 'double' || (quotes === 'auto' && doubleQuotes < singleQuotes));
  429. quote = single ? '\'' : '"';
  430. if (!(single ? singleQuotes : doubleQuotes)) {
  431. return quote + result + quote;
  432. }
  433. str = result;
  434. result = quote;
  435. for (i = 0, len = str.length; i < len; ++i) {
  436. code = str.charCodeAt(i);
  437. if ((code === 0x27 /* ' */ && single) || (code === 0x22 /* " */ && !single)) {
  438. result += '\\';
  439. }
  440. result += String.fromCharCode(code);
  441. }
  442. return result + quote;
  443. }
  444. /**
  445. * flatten an array to a string, where the array can contain
  446. * either strings or nested arrays
  447. */
  448. function flattenToString(arr) {
  449. var i, iz, elem, result = '';
  450. for (i = 0, iz = arr.length; i < iz; ++i) {
  451. elem = arr[i];
  452. result += isArray(elem) ? flattenToString(elem) : elem;
  453. }
  454. return result;
  455. }
  456. /**
  457. * convert generated to a SourceNode when source maps are enabled.
  458. */
  459. function toSourceNodeWhenNeeded(generated, node) {
  460. if (!sourceMap) {
  461. // with no source maps, generated is either an
  462. // array or a string. if an array, flatten it.
  463. // if a string, just return it
  464. if (isArray(generated)) {
  465. return flattenToString(generated);
  466. } else {
  467. return generated;
  468. }
  469. }
  470. if (node == null) {
  471. if (generated instanceof SourceNode) {
  472. return generated;
  473. } else {
  474. node = {};
  475. }
  476. }
  477. if (node.loc == null) {
  478. return new SourceNode(null, null, sourceMap, generated, node.name || null);
  479. }
  480. return new SourceNode(node.loc.start.line, node.loc.start.column, (sourceMap === true ? node.loc.source || null : sourceMap), generated, node.name || null);
  481. }
  482. function noEmptySpace() {
  483. return (space) ? space : ' ';
  484. }
  485. function join(left, right) {
  486. var leftSource = toSourceNodeWhenNeeded(left).toString(),
  487. rightSource = toSourceNodeWhenNeeded(right).toString(),
  488. leftCharCode = leftSource.charCodeAt(leftSource.length - 1),
  489. rightCharCode = rightSource.charCodeAt(0);
  490. if ((leftCharCode === 0x2B /* + */ || leftCharCode === 0x2D /* - */) && leftCharCode === rightCharCode ||
  491. esutils.code.isIdentifierPart(leftCharCode) && esutils.code.isIdentifierPart(rightCharCode) ||
  492. leftCharCode === 0x2F /* / */ && rightCharCode === 0x69 /* i */) { // infix word operators all start with `i`
  493. return [left, noEmptySpace(), right];
  494. } else if (esutils.code.isWhiteSpace(leftCharCode) || esutils.code.isLineTerminator(leftCharCode) ||
  495. esutils.code.isWhiteSpace(rightCharCode) || esutils.code.isLineTerminator(rightCharCode)) {
  496. return [left, right];
  497. }
  498. return [left, space, right];
  499. }
  500. function addIndent(stmt) {
  501. return [base, stmt];
  502. }
  503. function withIndent(fn) {
  504. var previousBase, result;
  505. previousBase = base;
  506. base += indent;
  507. result = fn.call(this, base);
  508. base = previousBase;
  509. return result;
  510. }
  511. function calculateSpaces(str) {
  512. var i;
  513. for (i = str.length - 1; i >= 0; --i) {
  514. if (esutils.code.isLineTerminator(str.charCodeAt(i))) {
  515. break;
  516. }
  517. }
  518. return (str.length - 1) - i;
  519. }
  520. function adjustMultilineComment(value, specialBase) {
  521. var array, i, len, line, j, spaces, previousBase, sn;
  522. array = value.split(/\r\n|[\r\n]/);
  523. spaces = Number.MAX_VALUE;
  524. // first line doesn't have indentation
  525. for (i = 1, len = array.length; i < len; ++i) {
  526. line = array[i];
  527. j = 0;
  528. while (j < line.length && esutils.code.isWhiteSpace(line.charCodeAt(j))) {
  529. ++j;
  530. }
  531. if (spaces > j) {
  532. spaces = j;
  533. }
  534. }
  535. if (typeof specialBase !== 'undefined') {
  536. // pattern like
  537. // {
  538. // var t = 20; /*
  539. // * this is comment
  540. // */
  541. // }
  542. previousBase = base;
  543. if (array[1][spaces] === '*') {
  544. specialBase += ' ';
  545. }
  546. base = specialBase;
  547. } else {
  548. if (spaces & 1) {
  549. // /*
  550. // *
  551. // */
  552. // If spaces are odd number, above pattern is considered.
  553. // We waste 1 space.
  554. --spaces;
  555. }
  556. previousBase = base;
  557. }
  558. for (i = 1, len = array.length; i < len; ++i) {
  559. sn = toSourceNodeWhenNeeded(addIndent(array[i].slice(spaces)));
  560. array[i] = sourceMap ? sn.join('') : sn;
  561. }
  562. base = previousBase;
  563. return array.join('\n');
  564. }
  565. function generateComment(comment, specialBase) {
  566. if (comment.type === 'Line') {
  567. if (endsWithLineTerminator(comment.value)) {
  568. return '//' + comment.value;
  569. } else {
  570. // Always use LineTerminator
  571. return '//' + comment.value + '\n';
  572. }
  573. }
  574. if (extra.format.indent.adjustMultilineComment && /[\n\r]/.test(comment.value)) {
  575. return adjustMultilineComment('/*' + comment.value + '*/', specialBase);
  576. }
  577. return '/*' + comment.value + '*/';
  578. }
  579. function addCommentsToStatement(stmt, result) {
  580. var i, len, comment, save, tailingToStatement, specialBase, fragment;
  581. if (stmt.leadingComments && stmt.leadingComments.length > 0) {
  582. save = result;
  583. comment = stmt.leadingComments[0];
  584. result = [];
  585. if (safeConcatenation && stmt.type === Syntax.Program && stmt.body.length === 0) {
  586. result.push('\n');
  587. }
  588. result.push(generateComment(comment));
  589. if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
  590. result.push('\n');
  591. }
  592. for (i = 1, len = stmt.leadingComments.length; i < len; ++i) {
  593. comment = stmt.leadingComments[i];
  594. fragment = [generateComment(comment)];
  595. if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
  596. fragment.push('\n');
  597. }
  598. result.push(addIndent(fragment));
  599. }
  600. result.push(addIndent(save));
  601. }
  602. if (stmt.trailingComments) {
  603. tailingToStatement = !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString());
  604. specialBase = stringRepeat(' ', calculateSpaces(toSourceNodeWhenNeeded([base, result, indent]).toString()));
  605. for (i = 0, len = stmt.trailingComments.length; i < len; ++i) {
  606. comment = stmt.trailingComments[i];
  607. if (tailingToStatement) {
  608. // We assume target like following script
  609. //
  610. // var t = 20; /**
  611. // * This is comment of t
  612. // */
  613. if (i === 0) {
  614. // first case
  615. result = [result, indent];
  616. } else {
  617. result = [result, specialBase];
  618. }
  619. result.push(generateComment(comment, specialBase));
  620. } else {
  621. result = [result, addIndent(generateComment(comment))];
  622. }
  623. if (i !== len - 1 && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
  624. result = [result, '\n'];
  625. }
  626. }
  627. }
  628. return result;
  629. }
  630. function parenthesize(text, current, should) {
  631. if (current < should) {
  632. return ['(', text, ')'];
  633. }
  634. return text;
  635. }
  636. function maybeBlock(stmt, semicolonOptional, functionBody) {
  637. var result, noLeadingComment;
  638. noLeadingComment = !extra.comment || !stmt.leadingComments;
  639. if (stmt.type === Syntax.BlockStatement && noLeadingComment) {
  640. return [space, generateStatement(stmt, { functionBody: functionBody })];
  641. }
  642. if (stmt.type === Syntax.EmptyStatement && noLeadingComment) {
  643. return ';';
  644. }
  645. withIndent(function () {
  646. result = [newline, addIndent(generateStatement(stmt, { semicolonOptional: semicolonOptional, functionBody: functionBody }))];
  647. });
  648. return result;
  649. }
  650. function maybeBlockSuffix(stmt, result) {
  651. var ends = endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString());
  652. if (stmt.type === Syntax.BlockStatement && (!extra.comment || !stmt.leadingComments) && !ends) {
  653. return [result, space];
  654. }
  655. if (ends) {
  656. return [result, base];
  657. }
  658. return [result, newline, base];
  659. }
  660. function generateVerbatim(expr, option) {
  661. var i, result;
  662. result = expr[extra.verbatim].split(/\r\n|\n/);
  663. for (i = 1; i < result.length; i++) {
  664. result[i] = newline + base + result[i];
  665. }
  666. result = parenthesize(result, Precedence.Sequence, option.precedence);
  667. return toSourceNodeWhenNeeded(result, expr);
  668. }
  669. function generateIdentifier(node) {
  670. return toSourceNodeWhenNeeded(node.name, node);
  671. }
  672. function generatePattern(node, options) {
  673. var result;
  674. if (node.type === Syntax.Identifier) {
  675. result = generateIdentifier(node);
  676. } else {
  677. result = generateExpression(node, {
  678. precedence: options.precedence,
  679. allowIn: options.allowIn,
  680. allowCall: true
  681. });
  682. }
  683. return result;
  684. }
  685. function generateFunctionBody(node) {
  686. var result, i, len, expr, arrow;
  687. arrow = node.type === Syntax.ArrowFunctionExpression;
  688. if (arrow && node.params.length === 1 && node.params[0].type === Syntax.Identifier) {
  689. // arg => { } case
  690. result = [generateIdentifier(node.params[0])];
  691. } else {
  692. result = ['('];
  693. for (i = 0, len = node.params.length; i < len; ++i) {
  694. result.push(generatePattern(node.params[i], {
  695. precedence: Precedence.Assignment,
  696. allowIn: true
  697. }));
  698. if (i + 1 < len) {
  699. result.push(',' + space);
  700. }
  701. }
  702. result.push(')');
  703. }
  704. if (arrow) {
  705. result.push(space);
  706. result.push('=>');
  707. }
  708. if (node.expression) {
  709. result.push(space);
  710. expr = generateExpression(node.body, {
  711. precedence: Precedence.Assignment,
  712. allowIn: true,
  713. allowCall: true
  714. });
  715. if (expr.toString().charAt(0) === '{') {
  716. expr = ['(', expr, ')'];
  717. }
  718. result.push(expr);
  719. } else {
  720. result.push(maybeBlock(node.body, false, true));
  721. }
  722. return result;
  723. }
  724. function generateIterationForStatement(operator, stmt, semicolonIsNotNeeded) {
  725. var result = ['for' + space + '('];
  726. withIndent(function () {
  727. if (stmt.left.type === Syntax.VariableDeclaration) {
  728. withIndent(function () {
  729. result.push(stmt.left.kind + noEmptySpace());
  730. result.push(generateStatement(stmt.left.declarations[0], {
  731. allowIn: false
  732. }));
  733. });
  734. } else {
  735. result.push(generateExpression(stmt.left, {
  736. precedence: Precedence.Call,
  737. allowIn: true,
  738. allowCall: true
  739. }));
  740. }
  741. result = join(result, operator);
  742. result = [join(
  743. result,
  744. generateExpression(stmt.right, {
  745. precedence: Precedence.Sequence,
  746. allowIn: true,
  747. allowCall: true
  748. })
  749. ), ')'];
  750. });
  751. result.push(maybeBlock(stmt.body, semicolonIsNotNeeded));
  752. return result;
  753. }
  754. function generateExpression(expr, option) {
  755. var result,
  756. precedence,
  757. type,
  758. currentPrecedence,
  759. i,
  760. len,
  761. raw,
  762. fragment,
  763. multiline,
  764. leftCharCode,
  765. leftSource,
  766. rightCharCode,
  767. allowIn,
  768. allowCall,
  769. allowUnparenthesizedNew,
  770. property,
  771. isGenerator;
  772. precedence = option.precedence;
  773. allowIn = option.allowIn;
  774. allowCall = option.allowCall;
  775. type = expr.type || option.type;
  776. if (extra.verbatim && expr.hasOwnProperty(extra.verbatim)) {
  777. return generateVerbatim(expr, option);
  778. }
  779. switch (type) {
  780. case Syntax.SequenceExpression:
  781. result = [];
  782. allowIn |= (Precedence.Sequence < precedence);
  783. for (i = 0, len = expr.expressions.length; i < len; ++i) {
  784. result.push(generateExpression(expr.expressions[i], {
  785. precedence: Precedence.Assignment,
  786. allowIn: allowIn,
  787. allowCall: true
  788. }));
  789. if (i + 1 < len) {
  790. result.push(',' + space);
  791. }
  792. }
  793. result = parenthesize(result, Precedence.Sequence, precedence);
  794. break;
  795. case Syntax.AssignmentExpression:
  796. allowIn |= (Precedence.Assignment < precedence);
  797. result = parenthesize(
  798. [
  799. generateExpression(expr.left, {
  800. precedence: Precedence.Call,
  801. allowIn: allowIn,
  802. allowCall: true
  803. }),
  804. space + expr.operator + space,
  805. generateExpression(expr.right, {
  806. precedence: Precedence.Assignment,
  807. allowIn: allowIn,
  808. allowCall: true
  809. })
  810. ],
  811. Precedence.Assignment,
  812. precedence
  813. );
  814. break;
  815. case Syntax.ArrowFunctionExpression:
  816. allowIn |= (Precedence.ArrowFunction < precedence);
  817. result = parenthesize(generateFunctionBody(expr), Precedence.ArrowFunction, precedence);
  818. break;
  819. case Syntax.ConditionalExpression:
  820. allowIn |= (Precedence.Conditional < precedence);
  821. result = parenthesize(
  822. [
  823. generateExpression(expr.test, {
  824. precedence: Precedence.LogicalOR,
  825. allowIn: allowIn,
  826. allowCall: true
  827. }),
  828. space + '?' + space,
  829. generateExpression(expr.consequent, {
  830. precedence: Precedence.Assignment,
  831. allowIn: allowIn,
  832. allowCall: true
  833. }),
  834. space + ':' + space,
  835. generateExpression(expr.alternate, {
  836. precedence: Precedence.Assignment,
  837. allowIn: allowIn,
  838. allowCall: true
  839. })
  840. ],
  841. Precedence.Conditional,
  842. precedence
  843. );
  844. break;
  845. case Syntax.LogicalExpression:
  846. case Syntax.BinaryExpression:
  847. currentPrecedence = BinaryPrecedence[expr.operator];
  848. allowIn |= (currentPrecedence < precedence);
  849. fragment = generateExpression(expr.left, {
  850. precedence: currentPrecedence,
  851. allowIn: allowIn,
  852. allowCall: true
  853. });
  854. leftSource = fragment.toString();
  855. if (leftSource.charCodeAt(leftSource.length - 1) === 0x2F /* / */ && esutils.code.isIdentifierPart(expr.operator.charCodeAt(0))) {
  856. result = [fragment, noEmptySpace(), expr.operator];
  857. } else {
  858. result = join(fragment, expr.operator);
  859. }
  860. fragment = generateExpression(expr.right, {
  861. precedence: currentPrecedence + 1,
  862. allowIn: allowIn,
  863. allowCall: true
  864. });
  865. if (expr.operator === '/' && fragment.toString().charAt(0) === '/' ||
  866. expr.operator.slice(-1) === '<' && fragment.toString().slice(0, 3) === '!--') {
  867. // If '/' concats with '/' or `<` concats with `!--`, it is interpreted as comment start
  868. result.push(noEmptySpace());
  869. result.push(fragment);
  870. } else {
  871. result = join(result, fragment);
  872. }
  873. if (expr.operator === 'in' && !allowIn) {
  874. result = ['(', result, ')'];
  875. } else {
  876. result = parenthesize(result, currentPrecedence, precedence);
  877. }
  878. break;
  879. case Syntax.CallExpression:
  880. result = [generateExpression(expr.callee, {
  881. precedence: Precedence.Call,
  882. allowIn: true,
  883. allowCall: true,
  884. allowUnparenthesizedNew: false
  885. })];
  886. result.push('(');
  887. for (i = 0, len = expr['arguments'].length; i < len; ++i) {
  888. result.push(generateExpression(expr['arguments'][i], {
  889. precedence: Precedence.Assignment,
  890. allowIn: true,
  891. allowCall: true
  892. }));
  893. if (i + 1 < len) {
  894. result.push(',' + space);
  895. }
  896. }
  897. result.push(')');
  898. if (!allowCall) {
  899. result = ['(', result, ')'];
  900. } else {
  901. result = parenthesize(result, Precedence.Call, precedence);
  902. }
  903. break;
  904. case Syntax.NewExpression:
  905. len = expr['arguments'].length;
  906. allowUnparenthesizedNew = option.allowUnparenthesizedNew === undefined || option.allowUnparenthesizedNew;
  907. result = join(
  908. 'new',
  909. generateExpression(expr.callee, {
  910. precedence: Precedence.New,
  911. allowIn: true,
  912. allowCall: false,
  913. allowUnparenthesizedNew: allowUnparenthesizedNew && !parentheses && len === 0
  914. })
  915. );
  916. if (!allowUnparenthesizedNew || parentheses || len > 0) {
  917. result.push('(');
  918. for (i = 0; i < len; ++i) {
  919. result.push(generateExpression(expr['arguments'][i], {
  920. precedence: Precedence.Assignment,
  921. allowIn: true,
  922. allowCall: true
  923. }));
  924. if (i + 1 < len) {
  925. result.push(',' + space);
  926. }
  927. }
  928. result.push(')');
  929. }
  930. result = parenthesize(result, Precedence.New, precedence);
  931. break;
  932. case Syntax.MemberExpression:
  933. result = [generateExpression(expr.object, {
  934. precedence: Precedence.Call,
  935. allowIn: true,
  936. allowCall: allowCall,
  937. allowUnparenthesizedNew: false
  938. })];
  939. if (expr.computed) {
  940. result.push('[');
  941. result.push(generateExpression(expr.property, {
  942. precedence: Precedence.Sequence,
  943. allowIn: true,
  944. allowCall: allowCall
  945. }));
  946. result.push(']');
  947. } else {
  948. if (expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') {
  949. fragment = toSourceNodeWhenNeeded(result).toString();
  950. // When the following conditions are all true,
  951. // 1. No floating point
  952. // 2. Don't have exponents
  953. // 3. The last character is a decimal digit
  954. // 4. Not hexadecimal OR octal number literal
  955. // we should add a floating point.
  956. if (
  957. fragment.indexOf('.') < 0 &&
  958. !/[eExX]/.test(fragment) &&
  959. esutils.code.isDecimalDigit(fragment.charCodeAt(fragment.length - 1)) &&
  960. !(fragment.length >= 2 && fragment.charCodeAt(0) === 48) // '0'
  961. ) {
  962. result.push('.');
  963. }
  964. }
  965. result.push('.');
  966. result.push(generateIdentifier(expr.property));
  967. }
  968. result = parenthesize(result, Precedence.Member, precedence);
  969. break;
  970. case Syntax.UnaryExpression:
  971. fragment = generateExpression(expr.argument, {
  972. precedence: Precedence.Unary,
  973. allowIn: true,
  974. allowCall: true
  975. });
  976. if (space === '') {
  977. result = join(expr.operator, fragment);
  978. } else {
  979. result = [expr.operator];
  980. if (expr.operator.length > 2) {
  981. // delete, void, typeof
  982. // get `typeof []`, not `typeof[]`
  983. result = join(result, fragment);
  984. } else {
  985. // Prevent inserting spaces between operator and argument if it is unnecessary
  986. // like, `!cond`
  987. leftSource = toSourceNodeWhenNeeded(result).toString();
  988. leftCharCode = leftSource.charCodeAt(leftSource.length - 1);
  989. rightCharCode = fragment.toString().charCodeAt(0);
  990. if (((leftCharCode === 0x2B /* + */ || leftCharCode === 0x2D /* - */) && leftCharCode === rightCharCode) ||
  991. (esutils.code.isIdentifierPart(leftCharCode) && esutils.code.isIdentifierPart(rightCharCode))) {
  992. result.push(noEmptySpace());
  993. result.push(fragment);
  994. } else {
  995. result.push(fragment);
  996. }
  997. }
  998. }
  999. result = parenthesize(result, Precedence.Unary, precedence);
  1000. break;
  1001. case Syntax.YieldExpression:
  1002. if (expr.delegate) {
  1003. result = 'yield*';
  1004. } else {
  1005. result = 'yield';
  1006. }
  1007. if (expr.argument) {
  1008. result = join(
  1009. result,
  1010. generateExpression(expr.argument, {
  1011. precedence: Precedence.Yield,
  1012. allowIn: true,
  1013. allowCall: true
  1014. })
  1015. );
  1016. }
  1017. result = parenthesize(result, Precedence.Yield, precedence);
  1018. break;
  1019. case Syntax.UpdateExpression:
  1020. if (expr.prefix) {
  1021. result = parenthesize(
  1022. [
  1023. expr.operator,
  1024. generateExpression(expr.argument, {
  1025. precedence: Precedence.Unary,
  1026. allowIn: true,
  1027. allowCall: true
  1028. })
  1029. ],
  1030. Precedence.Unary,
  1031. precedence
  1032. );
  1033. } else {
  1034. result = parenthesize(
  1035. [
  1036. generateExpression(expr.argument, {
  1037. precedence: Precedence.Postfix,
  1038. allowIn: true,
  1039. allowCall: true
  1040. }),
  1041. expr.operator
  1042. ],
  1043. Precedence.Postfix,
  1044. precedence
  1045. );
  1046. }
  1047. break;
  1048. case Syntax.FunctionExpression:
  1049. isGenerator = expr.generator && !extra.moz.starlessGenerator;
  1050. result = isGenerator ? 'function*' : 'function';
  1051. if (expr.id) {
  1052. result = [result, (isGenerator) ? space : noEmptySpace(),
  1053. generateIdentifier(expr.id),
  1054. generateFunctionBody(expr)];
  1055. } else {
  1056. result = [result + space, generateFunctionBody(expr)];
  1057. }
  1058. break;
  1059. case Syntax.ArrayPattern:
  1060. case Syntax.ArrayExpression:
  1061. if (!expr.elements.length) {
  1062. result = '[]';
  1063. break;
  1064. }
  1065. multiline = expr.elements.length > 1;
  1066. result = ['[', multiline ? newline : ''];
  1067. withIndent(function (indent) {
  1068. for (i = 0, len = expr.elements.length; i < len; ++i) {
  1069. if (!expr.elements[i]) {
  1070. if (multiline) {
  1071. result.push(indent);
  1072. }
  1073. if (i + 1 === len) {
  1074. result.push(',');
  1075. }
  1076. } else {
  1077. result.push(multiline ? indent : '');
  1078. result.push(generateExpression(expr.elements[i], {
  1079. precedence: Precedence.Assignment,
  1080. allowIn: true,
  1081. allowCall: true
  1082. }));
  1083. }
  1084. if (i + 1 < len) {
  1085. result.push(',' + (multiline ? newline : space));
  1086. }
  1087. }
  1088. });
  1089. if (multiline && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
  1090. result.push(newline);
  1091. }
  1092. result.push(multiline ? base : '');
  1093. result.push(']');
  1094. break;
  1095. case Syntax.Property:
  1096. if (expr.kind === 'get' || expr.kind === 'set') {
  1097. result = [
  1098. expr.kind, noEmptySpace(),
  1099. generateExpression(expr.key, {
  1100. precedence: Precedence.Sequence,
  1101. allowIn: true,
  1102. allowCall: true
  1103. }),
  1104. generateFunctionBody(expr.value)
  1105. ];
  1106. } else {
  1107. if (expr.shorthand) {
  1108. result = generateExpression(expr.key, {
  1109. precedence: Precedence.Sequence,
  1110. allowIn: true,
  1111. allowCall: true
  1112. });
  1113. } else if (expr.method) {
  1114. result = [];
  1115. if (expr.value.generator) {
  1116. result.push('*');
  1117. }
  1118. result.push(generateExpression(expr.key, {
  1119. precedence: Precedence.Sequence,
  1120. allowIn: true,
  1121. allowCall: true
  1122. }));
  1123. result.push(generateFunctionBody(expr.value));
  1124. } else {
  1125. result = [
  1126. generateExpression(expr.key, {
  1127. precedence: Precedence.Sequence,
  1128. allowIn: true,
  1129. allowCall: true
  1130. }),
  1131. ':' + space,
  1132. generateExpression(expr.value, {
  1133. precedence: Precedence.Assignment,
  1134. allowIn: true,
  1135. allowCall: true
  1136. })
  1137. ];
  1138. }
  1139. }
  1140. break;
  1141. case Syntax.ObjectExpression:
  1142. if (!expr.properties.length) {
  1143. result = '{}';
  1144. break;
  1145. }
  1146. multiline = expr.properties.length > 1;
  1147. withIndent(function () {
  1148. fragment = generateExpression(expr.properties[0], {
  1149. precedence: Precedence.Sequence,
  1150. allowIn: true,
  1151. allowCall: true,
  1152. type: Syntax.Property
  1153. });
  1154. });
  1155. if (!multiline) {
  1156. // issues 4
  1157. // Do not transform from
  1158. // dejavu.Class.declare({
  1159. // method2: function () {}
  1160. // });
  1161. // to
  1162. // dejavu.Class.declare({method2: function () {
  1163. // }});
  1164. if (!hasLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
  1165. result = [ '{', space, fragment, space, '}' ];
  1166. break;
  1167. }
  1168. }
  1169. withIndent(function (indent) {
  1170. result = [ '{', newline, indent, fragment ];
  1171. if (multiline) {
  1172. result.push(',' + newline);
  1173. for (i = 1, len = expr.properties.length; i < len; ++i) {
  1174. result.push(indent);
  1175. result.push(generateExpression(expr.properties[i], {
  1176. precedence: Precedence.Sequence,
  1177. allowIn: true,
  1178. allowCall: true,
  1179. type: Syntax.Property
  1180. }));
  1181. if (i + 1 < len) {
  1182. result.push(',' + newline);
  1183. }
  1184. }
  1185. }
  1186. });
  1187. if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
  1188. result.push(newline);
  1189. }
  1190. result.push(base);
  1191. result.push('}');
  1192. break;
  1193. case Syntax.ObjectPattern:
  1194. if (!expr.properties.length) {
  1195. result = '{}';
  1196. break;
  1197. }
  1198. multiline = false;
  1199. if (expr.properties.length === 1) {
  1200. property = expr.properties[0];
  1201. if (property.value.type !== Syntax.Identifier) {
  1202. multiline = true;
  1203. }
  1204. } else {
  1205. for (i = 0, len = expr.properties.length; i < len; ++i) {
  1206. property = expr.properties[i];
  1207. if (!property.shorthand) {
  1208. multiline = true;
  1209. break;
  1210. }
  1211. }
  1212. }
  1213. result = ['{', multiline ? newline : '' ];
  1214. withIndent(function (indent) {
  1215. for (i = 0, len = expr.properties.length; i < len; ++i) {
  1216. result.push(multiline ? indent : '');
  1217. result.push(generateExpression(expr.properties[i], {
  1218. precedence: Precedence.Sequence,
  1219. allowIn: true,
  1220. allowCall: true
  1221. }));
  1222. if (i + 1 < len) {
  1223. result.push(',' + (multiline ? newline : space));
  1224. }
  1225. }
  1226. });
  1227. if (multiline && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
  1228. result.push(newline);
  1229. }
  1230. result.push(multiline ? base : '');
  1231. result.push('}');
  1232. break;
  1233. case Syntax.ThisExpression:
  1234. result = 'this';
  1235. break;
  1236. case Syntax.Identifier:
  1237. result = generateIdentifier(expr);
  1238. break;
  1239. case Syntax.Literal:
  1240. if (expr.hasOwnProperty('raw') && parse) {
  1241. try {
  1242. raw = parse(expr.raw).body[0].expression;
  1243. if (raw.type === Syntax.Literal) {
  1244. if (raw.value === expr.value) {
  1245. result = expr.raw;
  1246. break;
  1247. }
  1248. }
  1249. } catch (e) {
  1250. // not use raw property
  1251. }
  1252. }
  1253. if (expr.value === null) {
  1254. result = 'null';
  1255. break;
  1256. }
  1257. if (typeof expr.value === 'string') {
  1258. result = escapeString(expr.value);
  1259. break;
  1260. }
  1261. if (typeof expr.value === 'number') {
  1262. result = generateNumber(expr.value);
  1263. break;
  1264. }
  1265. if (typeof expr.value === 'boolean') {
  1266. result = expr.value ? 'true' : 'false';
  1267. break;
  1268. }
  1269. result = generateRegExp(expr.value);
  1270. break;
  1271. case Syntax.GeneratorExpression:
  1272. case Syntax.ComprehensionExpression:
  1273. // GeneratorExpression should be parenthesized with (...), ComprehensionExpression with [...]
  1274. // Due to https://bugzilla.mozilla.org/show_bug.cgi?id=883468 position of expr.body can differ in Spidermonkey and ES6
  1275. result = (type === Syntax.GeneratorExpression) ? ['('] : ['['];
  1276. if (extra.moz.comprehensionExpressionStartsWithAssignment) {
  1277. fragment = generateExpression(expr.body, {
  1278. precedence: Precedence.Assignment,
  1279. allowIn: true,
  1280. allowCall: true
  1281. });
  1282. result.push(fragment);
  1283. }
  1284. if (expr.blocks) {
  1285. withIndent(function () {
  1286. for (i = 0, len = expr.blocks.length; i < len; ++i) {
  1287. fragment = generateExpression(expr.blocks[i], {
  1288. precedence: Precedence.Sequence,
  1289. allowIn: true,
  1290. allowCall: true
  1291. });
  1292. if (i > 0 || extra.moz.comprehensionExpressionStartsWithAssignment) {
  1293. result = join(result, fragment);
  1294. } else {
  1295. result.push(fragment);
  1296. }
  1297. }
  1298. });
  1299. }
  1300. if (expr.filter) {
  1301. result = join(result, 'if' + space);
  1302. fragment = generateExpression(expr.filter, {
  1303. precedence: Precedence.Sequence,
  1304. allowIn: true,
  1305. allowCall: true
  1306. });
  1307. if (extra.moz.parenthesizedComprehensionBlock) {
  1308. result = join(result, [ '(', fragment, ')' ]);
  1309. } else {
  1310. result = join(result, fragment);
  1311. }
  1312. }
  1313. if (!extra.moz.comprehensionExpressionStartsWithAssignment) {
  1314. fragment = generateExpression(expr.body, {
  1315. precedence: Precedence.Assignment,
  1316. allowIn: true,
  1317. allowCall: true
  1318. });
  1319. result = join(result, fragment);
  1320. }
  1321. result.push((type === Syntax.GeneratorExpression) ? ')' : ']');
  1322. break;
  1323. case Syntax.ComprehensionBlock:
  1324. if (expr.left.type === Syntax.VariableDeclaration) {
  1325. fragment = [
  1326. expr.left.kind, noEmptySpace(),
  1327. generateStatement(expr.left.declarations[0], {
  1328. allowIn: false
  1329. })
  1330. ];
  1331. } else {
  1332. fragment = generateExpression(expr.left, {
  1333. precedence: Precedence.Call,
  1334. allowIn: true,
  1335. allowCall: true
  1336. });
  1337. }
  1338. fragment = join(fragment, expr.of ? 'of' : 'in');
  1339. fragment = join(fragment, generateExpression(expr.right, {
  1340. precedence: Precedence.Sequence,
  1341. allowIn: true,
  1342. allowCall: true
  1343. }));
  1344. if (extra.moz.parenthesizedComprehensionBlock) {
  1345. result = [ 'for' + space + '(', fragment, ')' ];
  1346. } else {
  1347. result = join('for' + space, fragment);
  1348. }
  1349. break;
  1350. default:
  1351. throw new Error('Unknown expression type: ' + expr.type);
  1352. }
  1353. return toSourceNodeWhenNeeded(result, expr);
  1354. }
  1355. function generateStatement(stmt, option) {
  1356. var i,
  1357. len,
  1358. result,
  1359. node,
  1360. allowIn,
  1361. functionBody,
  1362. directiveContext,
  1363. fragment,
  1364. semicolon,
  1365. isGenerator;
  1366. allowIn = true;
  1367. semicolon = ';';
  1368. functionBody = false;
  1369. directiveContext = false;
  1370. if (option) {
  1371. allowIn = option.allowIn === undefined || option.allowIn;
  1372. if (!semicolons && option.semicolonOptional === true) {
  1373. semicolon = '';
  1374. }
  1375. functionBody = option.functionBody;
  1376. directiveContext = option.directiveContext;
  1377. }
  1378. switch (stmt.type) {
  1379. case Syntax.BlockStatement:
  1380. result = ['{', newline];
  1381. withIndent(function () {
  1382. for (i = 0, len = stmt.body.length; i < len; ++i) {
  1383. fragment = addIndent(generateStatement(stmt.body[i], {
  1384. semicolonOptional: i === len - 1,
  1385. directiveContext: functionBody
  1386. }));
  1387. result.push(fragment);
  1388. if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
  1389. result.push(newline);
  1390. }
  1391. }
  1392. });
  1393. result.push(addIndent('}'));
  1394. break;
  1395. case Syntax.BreakStatement:
  1396. if (stmt.label) {
  1397. result = 'break ' + stmt.label.name + semicolon;
  1398. } else {
  1399. result = 'break' + semicolon;
  1400. }
  1401. break;
  1402. case Syntax.ContinueStatement:
  1403. if (stmt.label) {
  1404. result = 'continue ' + stmt.label.name + semicolon;
  1405. } else {
  1406. result = 'continue' + semicolon;
  1407. }
  1408. break;
  1409. case Syntax.DirectiveStatement:
  1410. if (stmt.raw) {
  1411. result = stmt.raw + semicolon;
  1412. } else {
  1413. result = escapeDirective(stmt.directive) + semicolon;
  1414. }
  1415. break;
  1416. case Syntax.DoWhileStatement:
  1417. // Because `do 42 while (cond)` is Syntax Error. We need semicolon.
  1418. result = join('do', maybeBlock(stmt.body));
  1419. result = maybeBlockSuffix(stmt.body, result);
  1420. result = join(result, [
  1421. 'while' + space + '(',
  1422. generateExpression(stmt.test, {
  1423. precedence: Precedence.Sequence,
  1424. allowIn: true,
  1425. allowCall: true
  1426. }),
  1427. ')' + semicolon
  1428. ]);
  1429. break;
  1430. case Syntax.CatchClause:
  1431. withIndent(function () {
  1432. var guard;
  1433. result = [
  1434. 'catch' + space + '(',
  1435. generateExpression(stmt.param, {
  1436. precedence: Precedence.Sequence,
  1437. allowIn: true,
  1438. allowCall: true
  1439. }),
  1440. ')'
  1441. ];
  1442. if (stmt.guard) {
  1443. guard = generateExpression(stmt.guard, {
  1444. precedence: Precedence.Sequence,
  1445. allowIn: true,
  1446. allowCall: true
  1447. });
  1448. result.splice(2, 0, ' if ', guard);
  1449. }
  1450. });
  1451. result.push(maybeBlock(stmt.body));
  1452. break;
  1453. case Syntax.DebuggerStatement:
  1454. result = 'debugger' + semicolon;
  1455. break;
  1456. case Syntax.EmptyStatement:
  1457. result = ';';
  1458. break;
  1459. case Syntax.ExportDeclaration:
  1460. result = 'export ';
  1461. if (stmt.declaration) {
  1462. // FunctionDeclaration or VariableDeclaration
  1463. result = [result, generateStatement(stmt.declaration, { semicolonOptional: semicolon === '' })];
  1464. break;
  1465. }
  1466. break;
  1467. case Syntax.ExpressionStatement:
  1468. result = [generateExpression(stmt.expression, {
  1469. precedence: Precedence.Sequence,
  1470. allowIn: true,
  1471. allowCall: true
  1472. })];
  1473. // 12.4 '{', 'function' is not allowed in this position.
  1474. // wrap expression with parentheses
  1475. fragment = toSourceNodeWhenNeeded(result).toString();
  1476. if (fragment.charAt(0) === '{' || // ObjectExpression
  1477. (fragment.slice(0, 8) === 'function' && '* ('.indexOf(fragment.charAt(8)) >= 0) || // function or generator
  1478. (directive && directiveContext && stmt.expression.type === Syntax.Literal && typeof stmt.expression.value === 'string')) {
  1479. result = ['(', result, ')' + semicolon];
  1480. } else {
  1481. result.push(semicolon);
  1482. }
  1483. break;
  1484. case Syntax.VariableDeclarator:
  1485. if (stmt.init) {
  1486. result = [
  1487. generateExpression(stmt.id, {
  1488. precedence: Precedence.Assignment,
  1489. allowIn: allowIn,
  1490. allowCall: true
  1491. }),
  1492. space,
  1493. '=',
  1494. space,
  1495. generateExpression(stmt.init, {
  1496. precedence: Precedence.Assignment,
  1497. allowIn: allowIn,
  1498. allowCall: true
  1499. })
  1500. ];
  1501. } else {
  1502. result = generatePattern(stmt.id, {
  1503. precedence: Precedence.Assignment,
  1504. allowIn: allowIn
  1505. });
  1506. }
  1507. break;
  1508. case Syntax.VariableDeclaration:
  1509. result = [stmt.kind];
  1510. // special path for
  1511. // var x = function () {
  1512. // };
  1513. if (stmt.declarations.length === 1 && stmt.declarations[0].init &&
  1514. stmt.declarations[0].init.type === Syntax.FunctionExpression) {
  1515. result.push(noEmptySpace());
  1516. result.push(generateStatement(stmt.declarations[0], {
  1517. allowIn: allowIn
  1518. }));
  1519. } else {
  1520. // VariableDeclarator is typed as Statement,
  1521. // but joined with comma (not LineTerminator).
  1522. // So if comment is attached to target node, we should specialize.
  1523. withIndent(function () {
  1524. node = stmt.declarations[0];
  1525. if (extra.comment && node.leadingComments) {
  1526. result.push('\n');
  1527. result.push(addIndent(generateStatement(node, {
  1528. allowIn: allowIn
  1529. })));
  1530. } else {
  1531. result.push(noEmptySpace());
  1532. result.push(generateStatement(node, {
  1533. allowIn: allowIn
  1534. }));
  1535. }
  1536. for (i = 1, len = stmt.declarations.length; i < len; ++i) {
  1537. node = stmt.declarations[i];
  1538. if (extra.comment && node.leadingComments) {
  1539. result.push(',' + newline);
  1540. result.push(addIndent(generateStatement(node, {
  1541. allowIn: allowIn
  1542. })));
  1543. } else {
  1544. result.push(',' + space);
  1545. result.push(generateStatement(node, {
  1546. allowIn: allowIn
  1547. }));
  1548. }
  1549. }
  1550. });
  1551. }
  1552. result.push(semicolon);
  1553. break;
  1554. case Syntax.ThrowStatement:
  1555. result = [join(
  1556. 'throw',
  1557. generateExpression(stmt.argument, {
  1558. precedence: Precedence.Sequence,
  1559. allowIn: true,
  1560. allowCall: true
  1561. })
  1562. ), semicolon];
  1563. break;
  1564. case Syntax.TryStatement:
  1565. result = ['try', maybeBlock(stmt.block)];
  1566. result = maybeBlockSuffix(stmt.block, result);
  1567. if (stmt.handlers) {
  1568. // old interface
  1569. for (i = 0, len = stmt.handlers.length; i < len; ++i) {
  1570. result = join(result, generateStatement(stmt.handlers[i]));
  1571. if (stmt.finalizer || i + 1 !== len) {
  1572. result = maybeBlockSuffix(stmt.handlers[i].body, result);
  1573. }
  1574. }
  1575. } else {
  1576. stmt.guardedHandlers = stmt.guardedHandlers || [];
  1577. for (i = 0, len = stmt.guardedHandlers.length; i < len; ++i) {
  1578. result = join(result, generateStatement(stmt.guardedHandlers[i]));
  1579. if (stmt.finalizer || i + 1 !== len) {
  1580. result = maybeBlockSuffix(stmt.guardedHandlers[i].body, result);
  1581. }
  1582. }
  1583. // new interface
  1584. if (stmt.handler) {
  1585. if (isArray(stmt.handler)) {
  1586. for (i = 0, len = stmt.handler.length; i < len; ++i) {
  1587. result = join(result, generateStatement(stmt.handler[i]));
  1588. if (stmt.finalizer || i + 1 !== len) {
  1589. result = maybeBlockSuffix(stmt.handler[i].body, result);
  1590. }
  1591. }
  1592. } else {
  1593. result = join(result, generateStatement(stmt.handler));
  1594. if (stmt.finalizer) {
  1595. result = maybeBlockSuffix(stmt.handler.body, result);
  1596. }
  1597. }
  1598. }
  1599. }
  1600. if (stmt.finalizer) {
  1601. result = join(result, ['finally', maybeBlock(stmt.finalizer)]);
  1602. }
  1603. break;
  1604. case Syntax.SwitchStatement:
  1605. withIndent(function () {
  1606. result = [
  1607. 'switch' + space + '(',
  1608. generateExpression(stmt.discriminant, {
  1609. precedence: Precedence.Sequence,
  1610. allowIn: true,
  1611. allowCall: true
  1612. }),
  1613. ')' + space + '{' + newline
  1614. ];
  1615. });
  1616. if (stmt.cases) {
  1617. for (i = 0, len = stmt.cases.length; i < len; ++i) {
  1618. fragment = addIndent(generateStatement(stmt.cases[i], {semicolonOptional: i === len - 1}));
  1619. result.push(fragment);
  1620. if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
  1621. result.push(newline);
  1622. }
  1623. }
  1624. }
  1625. result.push(addIndent('}'));
  1626. break;
  1627. case Syntax.SwitchCase:
  1628. withIndent(function () {
  1629. if (stmt.test) {
  1630. result = [
  1631. join('case', generateExpression(stmt.test, {
  1632. precedence: Precedence.Sequence,
  1633. allowIn: true,
  1634. allowCall: true
  1635. })),
  1636. ':'
  1637. ];
  1638. } else {
  1639. result = ['default:'];
  1640. }
  1641. i = 0;
  1642. len = stmt.consequent.length;
  1643. if (len && stmt.consequent[0].type === Syntax.BlockStatement) {
  1644. fragment = maybeBlock(stmt.consequent[0]);
  1645. result.push(fragment);
  1646. i = 1;
  1647. }
  1648. if (i !== len && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
  1649. result.push(newline);
  1650. }
  1651. for (; i < len; ++i) {
  1652. fragment = addIndent(generateStatement(stmt.consequent[i], {semicolonOptional: i === len - 1 && semicolon === ''}));
  1653. result.push(fragment);
  1654. if (i + 1 !== len && !endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
  1655. result.push(newline);
  1656. }
  1657. }
  1658. });
  1659. break;
  1660. case Syntax.IfStatement:
  1661. withIndent(function () {
  1662. result = [
  1663. 'if' + space + '(',
  1664. generateExpression(stmt.test, {
  1665. precedence: Precedence.Sequence,
  1666. allowIn: true,
  1667. allowCall: true
  1668. }),
  1669. ')'
  1670. ];
  1671. });
  1672. if (stmt.alternate) {
  1673. result.push(maybeBlock(stmt.consequent));
  1674. result = maybeBlockSuffix(stmt.consequent, result);
  1675. if (stmt.alternate.type === Syntax.IfStatement) {
  1676. result = join(result, ['else ', generateStatement(stmt.alternate, {semicolonOptional: semicolon === ''})]);
  1677. } else {
  1678. result = join(result, join('else', maybeBlock(stmt.alternate, semicolon === '')));
  1679. }
  1680. } else {
  1681. result.push(maybeBlock(stmt.consequent, semicolon === ''));
  1682. }
  1683. break;
  1684. case Syntax.ForStatement:
  1685. withIndent(function () {
  1686. result = ['for' + space + '('];
  1687. if (stmt.init) {
  1688. if (stmt.init.type === Syntax.VariableDeclaration) {
  1689. result.push(generateStatement(stmt.init, {allowIn: false}));
  1690. } else {
  1691. result.push(generateExpression(stmt.init, {
  1692. precedence: Precedence.Sequence,
  1693. allowIn: false,
  1694. allowCall: true
  1695. }));
  1696. result.push(';');
  1697. }
  1698. } else {
  1699. result.push(';');
  1700. }
  1701. if (stmt.test) {
  1702. result.push(space);
  1703. result.push(generateExpression(stmt.test, {
  1704. precedence: Precedence.Sequence,
  1705. allowIn: true,
  1706. allowCall: true
  1707. }));
  1708. result.push(';');
  1709. } else {
  1710. result.push(';');
  1711. }
  1712. if (stmt.update) {
  1713. result.push(space);
  1714. result.push(generateExpression(stmt.update, {
  1715. precedence: Precedence.Sequence,
  1716. allowIn: true,
  1717. allowCall: true
  1718. }));
  1719. result.push(')');
  1720. } else {
  1721. result.push(')');
  1722. }
  1723. });
  1724. result.push(maybeBlock(stmt.body, semicolon === ''));
  1725. break;
  1726. case Syntax.ForInStatement:
  1727. result = generateIterationForStatement('in', stmt, semicolon === '');
  1728. break;
  1729. case Syntax.ForOfStatement:
  1730. result = generateIterationForStatement('of', stmt, semicolon === '');
  1731. break;
  1732. case Syntax.LabeledStatement:
  1733. result = [stmt.label.name + ':', maybeBlock(stmt.body, semicolon === '')];
  1734. break;
  1735. case Syntax.Program:
  1736. len = stmt.body.length;
  1737. result = [safeConcatenation && len > 0 ? '\n' : ''];
  1738. for (i = 0; i < len; ++i) {
  1739. fragment = addIndent(
  1740. generateStatement(stmt.body[i], {
  1741. semicolonOptional: !safeConcatenation && i === len - 1,
  1742. directiveContext: true
  1743. })
  1744. );
  1745. result.push(fragment);
  1746. if (i + 1 < len && !endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
  1747. result.push(newline);
  1748. }
  1749. }
  1750. break;
  1751. case Syntax.FunctionDeclaration:
  1752. isGenerator = stmt.generator && !extra.moz.starlessGenerator;
  1753. result = [
  1754. (isGenerator ? 'function*' : 'function'),
  1755. (isGenerator ? space : noEmptySpace()),
  1756. generateIdentifier(stmt.id),
  1757. generateFunctionBody(stmt)
  1758. ];
  1759. break;
  1760. case Syntax.ReturnStatement:
  1761. if (stmt.argument) {
  1762. result = [join(
  1763. 'return',
  1764. generateExpression(stmt.argument, {
  1765. precedence: Precedence.Sequence,
  1766. allowIn: true,
  1767. allowCall: true
  1768. })
  1769. ), semicolon];
  1770. } else {
  1771. result = ['return' + semicolon];
  1772. }
  1773. break;
  1774. case Syntax.WhileStatement:
  1775. withIndent(function () {
  1776. result = [
  1777. 'while' + space + '(',
  1778. generateExpression(stmt.test, {
  1779. precedence: Precedence.Sequence,
  1780. allowIn: true,
  1781. allowCall: true
  1782. }),
  1783. ')'
  1784. ];
  1785. });
  1786. result.push(maybeBlock(stmt.body, semicolon === ''));
  1787. break;
  1788. case Syntax.WithStatement:
  1789. withIndent(function () {
  1790. result = [
  1791. 'with' + space + '(',
  1792. generateExpression(stmt.object, {
  1793. precedence: Precedence.Sequence,
  1794. allowIn: true,
  1795. allowCall: true
  1796. }),
  1797. ')'
  1798. ];
  1799. });
  1800. result.push(maybeBlock(stmt.body, semicolon === ''));
  1801. break;
  1802. default:
  1803. throw new Error('Unknown statement type: ' + stmt.type);
  1804. }
  1805. // Attach comments
  1806. if (extra.comment) {
  1807. result = addCommentsToStatement(stmt, result);
  1808. }
  1809. fragment = toSourceNodeWhenNeeded(result).toString();
  1810. if (stmt.type === Syntax.Program && !safeConcatenation && newline === '' && fragment.charAt(fragment.length - 1) === '\n') {
  1811. result = sourceMap ? toSourceNodeWhenNeeded(result).replaceRight(/\s+$/, '') : fragment.replace(/\s+$/, '');
  1812. }
  1813. return toSourceNodeWhenNeeded(result, stmt);
  1814. }
  1815. function generate(node, options) {
  1816. var defaultOptions = getDefaultOptions(), result, pair;
  1817. if (options != null) {
  1818. // Obsolete options
  1819. //
  1820. // `options.indent`
  1821. // `options.base`
  1822. //
  1823. // Instead of them, we can use `option.format.indent`.
  1824. if (typeof options.indent === 'string') {
  1825. defaultOptions.format.indent.style = options.indent;
  1826. }
  1827. if (typeof options.base === 'number') {
  1828. defaultOptions.format.indent.base = options.base;
  1829. }
  1830. options = updateDeeply(defaultOptions, options);
  1831. indent = options.format.indent.style;
  1832. if (typeof options.base === 'string') {
  1833. base = options.base;
  1834. } else {
  1835. base = stringRepeat(indent, options.format.indent.base);
  1836. }
  1837. } else {
  1838. options = defaultOptions;
  1839. indent = options.format.indent.style;
  1840. base = stringRepeat(indent, options.format.indent.base);
  1841. }
  1842. json = options.format.json;
  1843. renumber = options.format.renumber;
  1844. hexadecimal = json ? false : options.format.hexadecimal;
  1845. quotes = json ? 'double' : options.format.quotes;
  1846. escapeless = options.format.escapeless;
  1847. newline = options.format.newline;
  1848. space = options.format.space;
  1849. if (options.format.compact) {
  1850. newline = space = indent = base = '';
  1851. }
  1852. parentheses = options.format.parentheses;
  1853. semicolons = options.format.semicolons;
  1854. safeConcatenation = options.format.safeConcatenation;
  1855. directive = options.directive;
  1856. parse = json ? null : options.parse;
  1857. sourceMap = options.sourceMap;
  1858. extra = options;
  1859. if (sourceMap) {
  1860. if (!exports.browser) {
  1861. // We assume environment is node.js
  1862. // And prevent from including source-map by browserify
  1863. SourceNode = require('source-map').SourceNode;
  1864. } else {
  1865. SourceNode = global.sourceMap.SourceNode;
  1866. }
  1867. }
  1868. switch (node.type) {
  1869. case Syntax.BlockStatement:
  1870. case Syntax.BreakStatement:
  1871. case Syntax.CatchClause:
  1872. case Syntax.ContinueStatement:
  1873. case Syntax.DirectiveStatement:
  1874. case Syntax.DoWhileStatement:
  1875. case Syntax.DebuggerStatement:
  1876. case Syntax.EmptyStatement:
  1877. case Syntax.ExpressionStatement:
  1878. case Syntax.ForStatement:
  1879. case Syntax.ForInStatement:
  1880. case Syntax.ForOfStatement:
  1881. case Syntax.FunctionDeclaration:
  1882. case Syntax.IfStatement:
  1883. case Syntax.LabeledStatement:
  1884. case Syntax.Program:
  1885. case Syntax.ReturnStatement:
  1886. case Syntax.SwitchStatement:
  1887. case Syntax.SwitchCase:
  1888. case Syntax.ThrowStatement:
  1889. case Syntax.TryStatement:
  1890. case Syntax.VariableDeclaration:
  1891. case Syntax.VariableDeclarator:
  1892. case Syntax.WhileStatement:
  1893. case Syntax.WithStatement:
  1894. result = generateStatement(node);
  1895. break;
  1896. case Syntax.AssignmentExpression:
  1897. case Syntax.ArrayExpression:
  1898. case Syntax.ArrayPattern:
  1899. case Syntax.BinaryExpression:
  1900. case Syntax.CallExpression:
  1901. case Syntax.ConditionalExpression:
  1902. case Syntax.FunctionExpression:
  1903. case Syntax.Identifier:
  1904. case Syntax.Literal:
  1905. case Syntax.LogicalExpression:
  1906. case Syntax.MemberExpression:
  1907. case Syntax.NewExpression:
  1908. case Syntax.ObjectExpression:
  1909. case Syntax.ObjectPattern:
  1910. case Syntax.Property:
  1911. case Syntax.SequenceExpression:
  1912. case Syntax.ThisExpression:
  1913. case Syntax.UnaryExpression:
  1914. case Syntax.UpdateExpression:
  1915. case Syntax.YieldExpression:
  1916. result = generateExpression(node, {
  1917. precedence: Precedence.Sequence,
  1918. allowIn: true,
  1919. allowCall: true
  1920. });
  1921. break;
  1922. default:
  1923. throw new Error('Unknown node type: ' + node.type);
  1924. }
  1925. if (!sourceMap) {
  1926. return result.toString();
  1927. }
  1928. pair = result.toStringWithSourceMap({
  1929. file: options.file,
  1930. sourceRoot: options.sourceMapRoot
  1931. });
  1932. if (options.sourceContent) {
  1933. pair.map.setSourceContent(options.sourceMap,
  1934. options.sourceContent);
  1935. }
  1936. if (options.sourceMapWithCode) {
  1937. return pair;
  1938. }
  1939. return pair.map.toString();
  1940. }
  1941. FORMAT_MINIFY = {
  1942. indent: {
  1943. style: '',
  1944. base: 0
  1945. },
  1946. renumber: true,
  1947. hexadecimal: true,
  1948. quotes: 'auto',
  1949. escapeless: true,
  1950. compact: true,
  1951. parentheses: false,
  1952. semicolons: false
  1953. };
  1954. FORMAT_DEFAULTS = getDefaultOptions().format;
  1955. exports.version = require('./package.json').version;
  1956. exports.generate = generate;
  1957. exports.attachComments = estraverse.attachComments;
  1958. exports.browser = false;
  1959. exports.FORMAT_MINIFY = FORMAT_MINIFY;
  1960. exports.FORMAT_DEFAULTS = FORMAT_DEFAULTS;
  1961. }());
  1962. /* vim: set sw=4 ts=4 et tw=80 : */