compiler_stmt.go 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116
  1. package goja
  2. import (
  3. "fmt"
  4. "github.com/dop251/goja/ast"
  5. "github.com/dop251/goja/file"
  6. "github.com/dop251/goja/token"
  7. "github.com/dop251/goja/unistring"
  8. )
  9. func (c *compiler) compileStatement(v ast.Statement, needResult bool) {
  10. switch v := v.(type) {
  11. case *ast.BlockStatement:
  12. c.compileBlockStatement(v, needResult)
  13. case *ast.ExpressionStatement:
  14. c.compileExpressionStatement(v, needResult)
  15. case *ast.VariableStatement:
  16. c.compileVariableStatement(v)
  17. case *ast.LexicalDeclaration:
  18. c.compileLexicalDeclaration(v)
  19. case *ast.ReturnStatement:
  20. c.compileReturnStatement(v)
  21. case *ast.IfStatement:
  22. c.compileIfStatement(v, needResult)
  23. case *ast.DoWhileStatement:
  24. c.compileDoWhileStatement(v, needResult)
  25. case *ast.ForStatement:
  26. c.compileForStatement(v, needResult)
  27. case *ast.ForInStatement:
  28. c.compileForInStatement(v, needResult)
  29. case *ast.ForOfStatement:
  30. c.compileForOfStatement(v, needResult)
  31. case *ast.WhileStatement:
  32. c.compileWhileStatement(v, needResult)
  33. case *ast.BranchStatement:
  34. c.compileBranchStatement(v)
  35. case *ast.TryStatement:
  36. c.compileTryStatement(v, needResult)
  37. case *ast.ThrowStatement:
  38. c.compileThrowStatement(v)
  39. case *ast.SwitchStatement:
  40. c.compileSwitchStatement(v, needResult)
  41. case *ast.LabelledStatement:
  42. c.compileLabeledStatement(v, needResult)
  43. case *ast.EmptyStatement:
  44. c.compileEmptyStatement(needResult)
  45. case *ast.FunctionDeclaration:
  46. c.compileStandaloneFunctionDecl(v)
  47. // note functions inside blocks are hoisted to the top of the block and are compiled using compileFunctions()
  48. case *ast.WithStatement:
  49. c.compileWithStatement(v, needResult)
  50. case *ast.DebuggerStatement:
  51. default:
  52. panic(fmt.Errorf("Unknown statement type: %T", v))
  53. }
  54. }
  55. func (c *compiler) compileLabeledStatement(v *ast.LabelledStatement, needResult bool) {
  56. label := v.Label.Name
  57. if c.scope.strict {
  58. c.checkIdentifierName(label, int(v.Label.Idx)-1)
  59. }
  60. for b := c.block; b != nil; b = b.outer {
  61. if b.label == label {
  62. c.throwSyntaxError(int(v.Label.Idx-1), "Label '%s' has already been declared", label)
  63. }
  64. }
  65. switch s := v.Statement.(type) {
  66. case *ast.ForInStatement:
  67. c.compileLabeledForInStatement(s, needResult, label)
  68. case *ast.ForOfStatement:
  69. c.compileLabeledForOfStatement(s, needResult, label)
  70. case *ast.ForStatement:
  71. c.compileLabeledForStatement(s, needResult, label)
  72. case *ast.WhileStatement:
  73. c.compileLabeledWhileStatement(s, needResult, label)
  74. case *ast.DoWhileStatement:
  75. c.compileLabeledDoWhileStatement(s, needResult, label)
  76. default:
  77. c.compileGenericLabeledStatement(s, needResult, label)
  78. }
  79. }
  80. func (c *compiler) updateEnterBlock(enter *enterBlock) {
  81. scope := c.scope
  82. stashSize, stackSize := 0, 0
  83. if scope.dynLookup {
  84. stashSize = len(scope.bindings)
  85. enter.names = scope.makeNamesMap()
  86. } else {
  87. for _, b := range scope.bindings {
  88. if b.inStash {
  89. stashSize++
  90. } else {
  91. stackSize++
  92. }
  93. }
  94. }
  95. enter.stashSize, enter.stackSize = uint32(stashSize), uint32(stackSize)
  96. }
  97. func (c *compiler) compileTryStatement(v *ast.TryStatement, needResult bool) {
  98. c.block = &block{
  99. typ: blockTry,
  100. outer: c.block,
  101. }
  102. var lp int
  103. var bodyNeedResult bool
  104. var finallyBreaking *block
  105. if v.Finally != nil {
  106. lp, finallyBreaking = c.scanStatements(v.Finally.List)
  107. }
  108. if finallyBreaking != nil {
  109. c.block.breaking = finallyBreaking
  110. if lp == -1 {
  111. bodyNeedResult = finallyBreaking.needResult
  112. }
  113. } else {
  114. bodyNeedResult = needResult
  115. }
  116. lbl := len(c.p.code)
  117. c.emit(nil)
  118. if needResult {
  119. c.emit(clearResult)
  120. }
  121. c.compileBlockStatement(v.Body, bodyNeedResult)
  122. c.emit(halt)
  123. lbl2 := len(c.p.code)
  124. c.emit(nil)
  125. var catchOffset int
  126. if v.Catch != nil {
  127. catchOffset = len(c.p.code) - lbl
  128. if v.Catch.Parameter != nil {
  129. c.block = &block{
  130. typ: blockScope,
  131. outer: c.block,
  132. }
  133. c.newBlockScope()
  134. list := v.Catch.Body.List
  135. funcs := c.extractFunctions(list)
  136. if _, ok := v.Catch.Parameter.(ast.Pattern); ok {
  137. // add anonymous binding for the catch parameter, note it must be first
  138. c.scope.addBinding(int(v.Catch.Idx0()) - 1)
  139. }
  140. c.createBindings(v.Catch.Parameter, func(name unistring.String, offset int) {
  141. if c.scope.strict {
  142. switch name {
  143. case "arguments", "eval":
  144. c.throwSyntaxError(offset, "Catch variable may not be eval or arguments in strict mode")
  145. }
  146. }
  147. c.scope.bindNameLexical(name, true, offset)
  148. })
  149. enter := &enterBlock{}
  150. c.emit(enter)
  151. if pattern, ok := v.Catch.Parameter.(ast.Pattern); ok {
  152. c.scope.bindings[0].emitGet()
  153. c.emitPattern(pattern, func(target, init compiledExpr) {
  154. c.emitPatternLexicalAssign(target, init)
  155. }, false)
  156. }
  157. for _, decl := range funcs {
  158. c.scope.bindNameLexical(decl.Function.Name.Name, true, int(decl.Function.Name.Idx1())-1)
  159. }
  160. c.compileLexicalDeclarations(list, true)
  161. c.compileFunctions(funcs)
  162. c.compileStatements(list, bodyNeedResult)
  163. c.leaveScopeBlock(enter)
  164. if c.scope.dynLookup || c.scope.bindings[0].inStash {
  165. c.p.code[lbl+catchOffset] = &enterCatchBlock{
  166. names: enter.names,
  167. stashSize: enter.stashSize,
  168. stackSize: enter.stackSize,
  169. }
  170. } else {
  171. enter.stackSize--
  172. }
  173. c.popScope()
  174. } else {
  175. c.emit(pop)
  176. c.compileBlockStatement(v.Catch.Body, bodyNeedResult)
  177. }
  178. c.emit(halt)
  179. }
  180. var finallyOffset int
  181. if v.Finally != nil {
  182. lbl1 := len(c.p.code)
  183. c.emit(nil)
  184. finallyOffset = len(c.p.code) - lbl
  185. if bodyNeedResult && finallyBreaking != nil && lp == -1 {
  186. c.emit(clearResult)
  187. }
  188. c.compileBlockStatement(v.Finally, false)
  189. c.emit(halt, retFinally)
  190. c.p.code[lbl1] = jump(len(c.p.code) - lbl1)
  191. }
  192. c.p.code[lbl] = try{catchOffset: int32(catchOffset), finallyOffset: int32(finallyOffset)}
  193. c.p.code[lbl2] = jump(len(c.p.code) - lbl2)
  194. c.leaveBlock()
  195. }
  196. func (c *compiler) addSrcMap(node ast.Node) {
  197. c.p.addSrcMap(int(node.Idx0()) - 1)
  198. }
  199. func (c *compiler) compileThrowStatement(v *ast.ThrowStatement) {
  200. c.compileExpression(v.Argument).emitGetter(true)
  201. c.addSrcMap(v)
  202. c.emit(throw)
  203. }
  204. func (c *compiler) compileDoWhileStatement(v *ast.DoWhileStatement, needResult bool) {
  205. c.compileLabeledDoWhileStatement(v, needResult, "")
  206. }
  207. func (c *compiler) compileLabeledDoWhileStatement(v *ast.DoWhileStatement, needResult bool, label unistring.String) {
  208. c.block = &block{
  209. typ: blockLoop,
  210. outer: c.block,
  211. label: label,
  212. needResult: needResult,
  213. }
  214. start := len(c.p.code)
  215. c.compileStatement(v.Body, needResult)
  216. c.block.cont = len(c.p.code)
  217. c.emitExpr(c.compileExpression(v.Test), true)
  218. c.emit(jeq(start - len(c.p.code)))
  219. c.leaveBlock()
  220. }
  221. func (c *compiler) compileForStatement(v *ast.ForStatement, needResult bool) {
  222. c.compileLabeledForStatement(v, needResult, "")
  223. }
  224. func (c *compiler) compileForHeadLexDecl(decl *ast.LexicalDeclaration, needResult bool) *enterBlock {
  225. c.block = &block{
  226. typ: blockIterScope,
  227. outer: c.block,
  228. needResult: needResult,
  229. }
  230. c.newBlockScope()
  231. enterIterBlock := &enterBlock{}
  232. c.emit(enterIterBlock)
  233. c.createLexicalBindings(decl)
  234. c.compileLexicalDeclaration(decl)
  235. return enterIterBlock
  236. }
  237. func (c *compiler) compileLabeledForStatement(v *ast.ForStatement, needResult bool, label unistring.String) {
  238. loopBlock := &block{
  239. typ: blockLoop,
  240. outer: c.block,
  241. label: label,
  242. needResult: needResult,
  243. }
  244. c.block = loopBlock
  245. var enterIterBlock *enterBlock
  246. switch init := v.Initializer.(type) {
  247. case nil:
  248. // no-op
  249. case *ast.ForLoopInitializerLexicalDecl:
  250. enterIterBlock = c.compileForHeadLexDecl(&init.LexicalDeclaration, needResult)
  251. case *ast.ForLoopInitializerVarDeclList:
  252. for _, expr := range init.List {
  253. c.compileVarBinding(expr)
  254. }
  255. case *ast.ForLoopInitializerExpression:
  256. c.compileExpression(init.Expression).emitGetter(false)
  257. default:
  258. panic(fmt.Sprintf("Unsupported for loop initializer: %T", init))
  259. }
  260. if needResult {
  261. c.emit(clearResult) // initial result
  262. }
  263. if enterIterBlock != nil {
  264. c.emit(jump(1))
  265. }
  266. start := len(c.p.code)
  267. var j int
  268. testConst := false
  269. if v.Test != nil {
  270. expr := c.compileExpression(v.Test)
  271. if expr.constant() {
  272. r, ex := c.evalConst(expr)
  273. if ex == nil {
  274. if r.ToBoolean() {
  275. testConst = true
  276. } else {
  277. leave := c.enterDummyMode()
  278. c.compileStatement(v.Body, false)
  279. if v.Update != nil {
  280. c.compileExpression(v.Update).emitGetter(false)
  281. }
  282. leave()
  283. goto end
  284. }
  285. } else {
  286. expr.addSrcMap()
  287. c.emitThrow(ex.val)
  288. goto end
  289. }
  290. } else {
  291. expr.emitGetter(true)
  292. j = len(c.p.code)
  293. c.emit(nil)
  294. }
  295. }
  296. if needResult {
  297. c.emit(clearResult)
  298. }
  299. c.compileStatement(v.Body, needResult)
  300. loopBlock.cont = len(c.p.code)
  301. if enterIterBlock != nil {
  302. c.emit(jump(1))
  303. }
  304. if v.Update != nil {
  305. c.compileExpression(v.Update).emitGetter(false)
  306. }
  307. if enterIterBlock != nil {
  308. if c.scope.needStash || c.scope.isDynamic() {
  309. c.p.code[start-1] = copyStash{}
  310. c.p.code[loopBlock.cont] = copyStash{}
  311. } else {
  312. if l := len(c.p.code); l > loopBlock.cont {
  313. loopBlock.cont++
  314. } else {
  315. c.p.code = c.p.code[:l-1]
  316. }
  317. }
  318. }
  319. c.emit(jump(start - len(c.p.code)))
  320. if v.Test != nil {
  321. if !testConst {
  322. c.p.code[j] = jne(len(c.p.code) - j)
  323. }
  324. }
  325. end:
  326. if enterIterBlock != nil {
  327. c.leaveScopeBlock(enterIterBlock)
  328. c.popScope()
  329. }
  330. c.leaveBlock()
  331. }
  332. func (c *compiler) compileForInStatement(v *ast.ForInStatement, needResult bool) {
  333. c.compileLabeledForInStatement(v, needResult, "")
  334. }
  335. func (c *compiler) compileForInto(into ast.ForInto, needResult bool) (enter *enterBlock) {
  336. switch into := into.(type) {
  337. case *ast.ForIntoExpression:
  338. c.compileExpression(into.Expression).emitSetter(&c.enumGetExpr, false)
  339. case *ast.ForIntoVar:
  340. if c.scope.strict && into.Binding.Initializer != nil {
  341. c.throwSyntaxError(int(into.Binding.Initializer.Idx0())-1, "for-in loop variable declaration may not have an initializer.")
  342. }
  343. switch target := into.Binding.Target.(type) {
  344. case *ast.Identifier:
  345. c.compileIdentifierExpression(target).emitSetter(&c.enumGetExpr, false)
  346. case ast.Pattern:
  347. c.emit(enumGet)
  348. c.emitPattern(target, c.emitPatternVarAssign, false)
  349. default:
  350. c.throwSyntaxError(int(target.Idx0()-1), "unsupported for-in var target: %T", target)
  351. }
  352. case *ast.ForDeclaration:
  353. c.block = &block{
  354. typ: blockIterScope,
  355. outer: c.block,
  356. needResult: needResult,
  357. }
  358. c.newBlockScope()
  359. enter = &enterBlock{}
  360. c.emit(enter)
  361. switch target := into.Target.(type) {
  362. case *ast.Identifier:
  363. b := c.createLexicalIdBinding(target.Name, into.IsConst, int(into.Idx)-1)
  364. c.emit(enumGet)
  365. b.emitInit()
  366. case ast.Pattern:
  367. c.createLexicalBinding(target, into.IsConst)
  368. c.emit(enumGet)
  369. c.emitPattern(target, func(target, init compiledExpr) {
  370. c.emitPatternLexicalAssign(target, init)
  371. }, false)
  372. default:
  373. c.throwSyntaxError(int(into.Idx)-1, "Unsupported ForBinding: %T", into.Target)
  374. }
  375. default:
  376. panic(fmt.Sprintf("Unsupported for-into: %T", into))
  377. }
  378. return
  379. }
  380. func (c *compiler) compileLabeledForInOfStatement(into ast.ForInto, source ast.Expression, body ast.Statement, iter, needResult bool, label unistring.String) {
  381. c.block = &block{
  382. typ: blockLoopEnum,
  383. outer: c.block,
  384. label: label,
  385. needResult: needResult,
  386. }
  387. enterPos := -1
  388. if forDecl, ok := into.(*ast.ForDeclaration); ok {
  389. c.block = &block{
  390. typ: blockScope,
  391. outer: c.block,
  392. needResult: false,
  393. }
  394. c.newBlockScope()
  395. enterPos = len(c.p.code)
  396. c.emit(jump(1))
  397. c.createLexicalBinding(forDecl.Target, forDecl.IsConst)
  398. }
  399. c.compileExpression(source).emitGetter(true)
  400. if enterPos != -1 {
  401. s := c.scope
  402. used := len(c.block.breaks) > 0 || s.isDynamic()
  403. if !used {
  404. for _, b := range s.bindings {
  405. if b.useCount() > 0 {
  406. used = true
  407. break
  408. }
  409. }
  410. }
  411. if used {
  412. // We need the stack untouched because it contains the source.
  413. // This is not the most optimal way, but it's an edge case, hopefully quite rare.
  414. for _, b := range s.bindings {
  415. b.moveToStash()
  416. }
  417. enter := &enterBlock{}
  418. c.p.code[enterPos] = enter
  419. c.leaveScopeBlock(enter)
  420. } else {
  421. c.block = c.block.outer
  422. }
  423. c.popScope()
  424. }
  425. if iter {
  426. c.emit(iterateP)
  427. } else {
  428. c.emit(enumerate)
  429. }
  430. if needResult {
  431. c.emit(clearResult)
  432. }
  433. start := len(c.p.code)
  434. c.block.cont = start
  435. c.emit(nil)
  436. enterIterBlock := c.compileForInto(into, needResult)
  437. if needResult {
  438. c.emit(clearResult)
  439. }
  440. c.compileStatement(body, needResult)
  441. if enterIterBlock != nil {
  442. c.leaveScopeBlock(enterIterBlock)
  443. c.popScope()
  444. }
  445. c.emit(jump(start - len(c.p.code)))
  446. if iter {
  447. c.p.code[start] = iterNext(len(c.p.code) - start)
  448. } else {
  449. c.p.code[start] = enumNext(len(c.p.code) - start)
  450. }
  451. c.emit(enumPop, jump(2))
  452. c.leaveBlock()
  453. c.emit(enumPopClose)
  454. }
  455. func (c *compiler) compileLabeledForInStatement(v *ast.ForInStatement, needResult bool, label unistring.String) {
  456. c.compileLabeledForInOfStatement(v.Into, v.Source, v.Body, false, needResult, label)
  457. }
  458. func (c *compiler) compileForOfStatement(v *ast.ForOfStatement, needResult bool) {
  459. c.compileLabeledForOfStatement(v, needResult, "")
  460. }
  461. func (c *compiler) compileLabeledForOfStatement(v *ast.ForOfStatement, needResult bool, label unistring.String) {
  462. c.compileLabeledForInOfStatement(v.Into, v.Source, v.Body, true, needResult, label)
  463. }
  464. func (c *compiler) compileWhileStatement(v *ast.WhileStatement, needResult bool) {
  465. c.compileLabeledWhileStatement(v, needResult, "")
  466. }
  467. func (c *compiler) compileLabeledWhileStatement(v *ast.WhileStatement, needResult bool, label unistring.String) {
  468. c.block = &block{
  469. typ: blockLoop,
  470. outer: c.block,
  471. label: label,
  472. needResult: needResult,
  473. }
  474. if needResult {
  475. c.emit(clearResult)
  476. }
  477. start := len(c.p.code)
  478. c.block.cont = start
  479. expr := c.compileExpression(v.Test)
  480. testTrue := false
  481. var j int
  482. if expr.constant() {
  483. if t, ex := c.evalConst(expr); ex == nil {
  484. if t.ToBoolean() {
  485. testTrue = true
  486. } else {
  487. c.compileStatementDummy(v.Body)
  488. goto end
  489. }
  490. } else {
  491. c.emitThrow(ex.val)
  492. goto end
  493. }
  494. } else {
  495. expr.emitGetter(true)
  496. j = len(c.p.code)
  497. c.emit(nil)
  498. }
  499. if needResult {
  500. c.emit(clearResult)
  501. }
  502. c.compileStatement(v.Body, needResult)
  503. c.emit(jump(start - len(c.p.code)))
  504. if !testTrue {
  505. c.p.code[j] = jne(len(c.p.code) - j)
  506. }
  507. end:
  508. c.leaveBlock()
  509. }
  510. func (c *compiler) compileEmptyStatement(needResult bool) {
  511. if needResult {
  512. c.emit(clearResult)
  513. }
  514. }
  515. func (c *compiler) compileBranchStatement(v *ast.BranchStatement) {
  516. switch v.Token {
  517. case token.BREAK:
  518. c.compileBreak(v.Label, v.Idx)
  519. case token.CONTINUE:
  520. c.compileContinue(v.Label, v.Idx)
  521. default:
  522. panic(fmt.Errorf("Unknown branch statement token: %s", v.Token.String()))
  523. }
  524. }
  525. func (c *compiler) findBranchBlock(st *ast.BranchStatement) *block {
  526. switch st.Token {
  527. case token.BREAK:
  528. return c.findBreakBlock(st.Label, true)
  529. case token.CONTINUE:
  530. return c.findBreakBlock(st.Label, false)
  531. }
  532. return nil
  533. }
  534. func (c *compiler) findBreakBlock(label *ast.Identifier, isBreak bool) (res *block) {
  535. if label != nil {
  536. var found *block
  537. for b := c.block; b != nil; b = b.outer {
  538. if res == nil {
  539. if bb := b.breaking; bb != nil {
  540. res = bb
  541. if isBreak {
  542. return
  543. }
  544. }
  545. }
  546. if b.label == label.Name {
  547. found = b
  548. break
  549. }
  550. }
  551. if !isBreak && found != nil && found.typ != blockLoop && found.typ != blockLoopEnum {
  552. c.throwSyntaxError(int(label.Idx)-1, "Illegal continue statement: '%s' does not denote an iteration statement", label.Name)
  553. }
  554. if res == nil {
  555. res = found
  556. }
  557. } else {
  558. // find the nearest loop or switch (if break)
  559. L:
  560. for b := c.block; b != nil; b = b.outer {
  561. if bb := b.breaking; bb != nil {
  562. return bb
  563. }
  564. switch b.typ {
  565. case blockLoop, blockLoopEnum:
  566. res = b
  567. break L
  568. case blockSwitch:
  569. if isBreak {
  570. res = b
  571. break L
  572. }
  573. }
  574. }
  575. }
  576. return
  577. }
  578. func (c *compiler) emitBlockExitCode(label *ast.Identifier, idx file.Idx, isBreak bool) *block {
  579. block := c.findBreakBlock(label, isBreak)
  580. if block == nil {
  581. c.throwSyntaxError(int(idx)-1, "Could not find block")
  582. panic("unreachable")
  583. }
  584. L:
  585. for b := c.block; b != block; b = b.outer {
  586. switch b.typ {
  587. case blockIterScope:
  588. if !isBreak && b.outer == block {
  589. break L
  590. }
  591. fallthrough
  592. case blockScope:
  593. b.breaks = append(b.breaks, len(c.p.code))
  594. c.emit(nil)
  595. case blockTry:
  596. c.emit(halt)
  597. case blockWith:
  598. c.emit(leaveWith)
  599. case blockLoopEnum:
  600. c.emit(enumPopClose)
  601. }
  602. }
  603. return block
  604. }
  605. func (c *compiler) compileBreak(label *ast.Identifier, idx file.Idx) {
  606. block := c.emitBlockExitCode(label, idx, true)
  607. block.breaks = append(block.breaks, len(c.p.code))
  608. c.emit(nil)
  609. }
  610. func (c *compiler) compileContinue(label *ast.Identifier, idx file.Idx) {
  611. block := c.emitBlockExitCode(label, idx, false)
  612. block.conts = append(block.conts, len(c.p.code))
  613. c.emit(nil)
  614. }
  615. func (c *compiler) compileIfBody(s ast.Statement, needResult bool) {
  616. if !c.scope.strict {
  617. if s, ok := s.(*ast.FunctionDeclaration); ok {
  618. c.compileFunction(s)
  619. if needResult {
  620. c.emit(clearResult)
  621. }
  622. return
  623. }
  624. }
  625. c.compileStatement(s, needResult)
  626. }
  627. func (c *compiler) compileIfBodyDummy(s ast.Statement) {
  628. leave := c.enterDummyMode()
  629. defer leave()
  630. c.compileIfBody(s, false)
  631. }
  632. func (c *compiler) compileIfStatement(v *ast.IfStatement, needResult bool) {
  633. test := c.compileExpression(v.Test)
  634. if needResult {
  635. c.emit(clearResult)
  636. }
  637. if test.constant() {
  638. r, ex := c.evalConst(test)
  639. if ex != nil {
  640. test.addSrcMap()
  641. c.emitThrow(ex.val)
  642. return
  643. }
  644. if r.ToBoolean() {
  645. c.compileIfBody(v.Consequent, needResult)
  646. if v.Alternate != nil {
  647. c.compileIfBodyDummy(v.Alternate)
  648. }
  649. } else {
  650. c.compileIfBodyDummy(v.Consequent)
  651. if v.Alternate != nil {
  652. c.compileIfBody(v.Alternate, needResult)
  653. } else {
  654. if needResult {
  655. c.emit(clearResult)
  656. }
  657. }
  658. }
  659. return
  660. }
  661. test.emitGetter(true)
  662. jmp := len(c.p.code)
  663. c.emit(nil)
  664. c.compileIfBody(v.Consequent, needResult)
  665. if v.Alternate != nil {
  666. jmp1 := len(c.p.code)
  667. c.emit(nil)
  668. c.p.code[jmp] = jne(len(c.p.code) - jmp)
  669. c.compileIfBody(v.Alternate, needResult)
  670. c.p.code[jmp1] = jump(len(c.p.code) - jmp1)
  671. } else {
  672. if needResult {
  673. c.emit(jump(2))
  674. c.p.code[jmp] = jne(len(c.p.code) - jmp)
  675. c.emit(clearResult)
  676. } else {
  677. c.p.code[jmp] = jne(len(c.p.code) - jmp)
  678. }
  679. }
  680. }
  681. func (c *compiler) compileReturnStatement(v *ast.ReturnStatement) {
  682. if v.Argument != nil {
  683. c.emitExpr(c.compileExpression(v.Argument), true)
  684. } else {
  685. c.emit(loadUndef)
  686. }
  687. for b := c.block; b != nil; b = b.outer {
  688. switch b.typ {
  689. case blockTry:
  690. c.emit(halt)
  691. case blockLoopEnum:
  692. c.emit(enumPopClose)
  693. }
  694. }
  695. c.emit(ret)
  696. }
  697. func (c *compiler) checkVarConflict(name unistring.String, offset int) {
  698. for sc := c.scope; sc != nil; sc = sc.outer {
  699. if b, exists := sc.boundNames[name]; exists && !b.isVar && !(b.isArg && sc != c.scope) {
  700. c.throwSyntaxError(offset, "Identifier '%s' has already been declared", name)
  701. }
  702. if sc.function {
  703. break
  704. }
  705. }
  706. }
  707. func (c *compiler) emitVarAssign(name unistring.String, offset int, init compiledExpr) {
  708. c.checkVarConflict(name, offset)
  709. if init != nil {
  710. b, noDyn := c.scope.lookupName(name)
  711. if noDyn {
  712. c.emitNamedOrConst(init, name)
  713. c.p.addSrcMap(offset)
  714. b.emitInit()
  715. } else {
  716. c.emitVarRef(name, offset, b)
  717. c.emitNamedOrConst(init, name)
  718. c.p.addSrcMap(offset)
  719. c.emit(initValueP)
  720. }
  721. }
  722. }
  723. func (c *compiler) compileVarBinding(expr *ast.Binding) {
  724. switch target := expr.Target.(type) {
  725. case *ast.Identifier:
  726. c.emitVarAssign(target.Name, int(target.Idx)-1, c.compileExpression(expr.Initializer))
  727. case ast.Pattern:
  728. c.compileExpression(expr.Initializer).emitGetter(true)
  729. c.emitPattern(target, c.emitPatternVarAssign, false)
  730. default:
  731. c.throwSyntaxError(int(target.Idx0()-1), "unsupported variable binding target: %T", target)
  732. }
  733. }
  734. func (c *compiler) emitLexicalAssign(name unistring.String, offset int, init compiledExpr) {
  735. b := c.scope.boundNames[name]
  736. if b == nil {
  737. panic("Lexical declaration for an unbound name")
  738. }
  739. if init != nil {
  740. c.emitNamedOrConst(init, name)
  741. c.p.addSrcMap(offset)
  742. } else {
  743. if b.isConst {
  744. c.throwSyntaxError(offset, "Missing initializer in const declaration")
  745. }
  746. c.emit(loadUndef)
  747. }
  748. if c.scope.outer != nil {
  749. b.emitInit()
  750. } else {
  751. c.emit(initGlobal(name))
  752. }
  753. }
  754. func (c *compiler) emitPatternVarAssign(target, init compiledExpr) {
  755. id := target.(*compiledIdentifierExpr)
  756. c.emitVarAssign(id.name, id.offset, init)
  757. }
  758. func (c *compiler) emitPatternLexicalAssign(target, init compiledExpr) {
  759. id := target.(*compiledIdentifierExpr)
  760. c.emitLexicalAssign(id.name, id.offset, init)
  761. }
  762. func (c *compiler) emitPatternAssign(target, init compiledExpr) {
  763. if id, ok := target.(*compiledIdentifierExpr); ok {
  764. b, noDyn := c.scope.lookupName(id.name)
  765. if noDyn {
  766. c.emitNamedOrConst(init, id.name)
  767. b.emitSetP()
  768. } else {
  769. c.emitVarRef(id.name, id.offset, b)
  770. c.emitNamedOrConst(init, id.name)
  771. c.emit(putValueP)
  772. }
  773. } else {
  774. target.emitRef()
  775. c.emitExpr(init, true)
  776. c.emit(putValueP)
  777. }
  778. }
  779. func (c *compiler) compileLexicalBinding(expr *ast.Binding) {
  780. switch target := expr.Target.(type) {
  781. case *ast.Identifier:
  782. c.emitLexicalAssign(target.Name, int(target.Idx)-1, c.compileExpression(expr.Initializer))
  783. case ast.Pattern:
  784. c.compileExpression(expr.Initializer).emitGetter(true)
  785. c.emitPattern(target, func(target, init compiledExpr) {
  786. c.emitPatternLexicalAssign(target, init)
  787. }, false)
  788. default:
  789. c.throwSyntaxError(int(target.Idx0()-1), "unsupported lexical binding target: %T", target)
  790. }
  791. }
  792. func (c *compiler) compileVariableStatement(v *ast.VariableStatement) {
  793. for _, expr := range v.List {
  794. c.compileVarBinding(expr)
  795. }
  796. }
  797. func (c *compiler) compileLexicalDeclaration(v *ast.LexicalDeclaration) {
  798. for _, e := range v.List {
  799. c.compileLexicalBinding(e)
  800. }
  801. }
  802. func (c *compiler) isEmptyResult(st ast.Statement) bool {
  803. switch st := st.(type) {
  804. case *ast.EmptyStatement, *ast.VariableStatement, *ast.LexicalDeclaration, *ast.FunctionDeclaration,
  805. *ast.BranchStatement, *ast.DebuggerStatement:
  806. return true
  807. case *ast.LabelledStatement:
  808. return c.isEmptyResult(st.Statement)
  809. case *ast.BlockStatement:
  810. for _, s := range st.List {
  811. if _, ok := s.(*ast.BranchStatement); ok {
  812. return true
  813. }
  814. if !c.isEmptyResult(s) {
  815. return false
  816. }
  817. }
  818. return true
  819. }
  820. return false
  821. }
  822. func (c *compiler) scanStatements(list []ast.Statement) (lastProducingIdx int, breakingBlock *block) {
  823. lastProducingIdx = -1
  824. for i, st := range list {
  825. if bs, ok := st.(*ast.BranchStatement); ok {
  826. if blk := c.findBranchBlock(bs); blk != nil {
  827. breakingBlock = blk
  828. }
  829. break
  830. }
  831. if !c.isEmptyResult(st) {
  832. lastProducingIdx = i
  833. }
  834. }
  835. return
  836. }
  837. func (c *compiler) compileStatementsNeedResult(list []ast.Statement, lastProducingIdx int) {
  838. if lastProducingIdx >= 0 {
  839. for _, st := range list[:lastProducingIdx] {
  840. if _, ok := st.(*ast.FunctionDeclaration); ok {
  841. continue
  842. }
  843. c.compileStatement(st, false)
  844. }
  845. c.compileStatement(list[lastProducingIdx], true)
  846. }
  847. var leave func()
  848. defer func() {
  849. if leave != nil {
  850. leave()
  851. }
  852. }()
  853. for _, st := range list[lastProducingIdx+1:] {
  854. if _, ok := st.(*ast.FunctionDeclaration); ok {
  855. continue
  856. }
  857. c.compileStatement(st, false)
  858. if leave == nil {
  859. if _, ok := st.(*ast.BranchStatement); ok {
  860. leave = c.enterDummyMode()
  861. }
  862. }
  863. }
  864. }
  865. func (c *compiler) compileStatements(list []ast.Statement, needResult bool) {
  866. lastProducingIdx, blk := c.scanStatements(list)
  867. if blk != nil {
  868. needResult = blk.needResult
  869. }
  870. if needResult {
  871. c.compileStatementsNeedResult(list, lastProducingIdx)
  872. return
  873. }
  874. for _, st := range list {
  875. if _, ok := st.(*ast.FunctionDeclaration); ok {
  876. continue
  877. }
  878. c.compileStatement(st, false)
  879. }
  880. }
  881. func (c *compiler) compileGenericLabeledStatement(v ast.Statement, needResult bool, label unistring.String) {
  882. c.block = &block{
  883. typ: blockLabel,
  884. outer: c.block,
  885. label: label,
  886. needResult: needResult,
  887. }
  888. c.compileStatement(v, needResult)
  889. c.leaveBlock()
  890. }
  891. func (c *compiler) compileBlockStatement(v *ast.BlockStatement, needResult bool) {
  892. var scopeDeclared bool
  893. funcs := c.extractFunctions(v.List)
  894. if len(funcs) > 0 {
  895. c.newBlockScope()
  896. scopeDeclared = true
  897. }
  898. c.createFunctionBindings(funcs)
  899. scopeDeclared = c.compileLexicalDeclarations(v.List, scopeDeclared)
  900. var enter *enterBlock
  901. if scopeDeclared {
  902. c.block = &block{
  903. outer: c.block,
  904. typ: blockScope,
  905. needResult: needResult,
  906. }
  907. enter = &enterBlock{}
  908. c.emit(enter)
  909. }
  910. c.compileFunctions(funcs)
  911. c.compileStatements(v.List, needResult)
  912. if scopeDeclared {
  913. c.leaveScopeBlock(enter)
  914. c.popScope()
  915. }
  916. }
  917. func (c *compiler) compileExpressionStatement(v *ast.ExpressionStatement, needResult bool) {
  918. c.emitExpr(c.compileExpression(v.Expression), needResult)
  919. if needResult {
  920. c.emit(saveResult)
  921. }
  922. }
  923. func (c *compiler) compileWithStatement(v *ast.WithStatement, needResult bool) {
  924. if c.scope.strict {
  925. c.throwSyntaxError(int(v.With)-1, "Strict mode code may not include a with statement")
  926. return
  927. }
  928. c.compileExpression(v.Object).emitGetter(true)
  929. c.emit(enterWith)
  930. c.block = &block{
  931. outer: c.block,
  932. typ: blockWith,
  933. needResult: needResult,
  934. }
  935. c.newBlockScope()
  936. c.scope.dynamic = true
  937. c.compileStatement(v.Body, needResult)
  938. c.emit(leaveWith)
  939. c.leaveBlock()
  940. c.popScope()
  941. }
  942. func (c *compiler) compileSwitchStatement(v *ast.SwitchStatement, needResult bool) {
  943. c.block = &block{
  944. typ: blockSwitch,
  945. outer: c.block,
  946. needResult: needResult,
  947. }
  948. c.compileExpression(v.Discriminant).emitGetter(true)
  949. var funcs []*ast.FunctionDeclaration
  950. for _, s := range v.Body {
  951. f := c.extractFunctions(s.Consequent)
  952. funcs = append(funcs, f...)
  953. }
  954. var scopeDeclared bool
  955. if len(funcs) > 0 {
  956. c.newBlockScope()
  957. scopeDeclared = true
  958. c.createFunctionBindings(funcs)
  959. }
  960. for _, s := range v.Body {
  961. scopeDeclared = c.compileLexicalDeclarations(s.Consequent, scopeDeclared)
  962. }
  963. var enter *enterBlock
  964. var db *binding
  965. if scopeDeclared {
  966. c.block = &block{
  967. typ: blockScope,
  968. outer: c.block,
  969. needResult: needResult,
  970. }
  971. enter = &enterBlock{}
  972. c.emit(enter)
  973. // create anonymous variable for the discriminant
  974. bindings := c.scope.bindings
  975. var bb []*binding
  976. if cap(bindings) == len(bindings) {
  977. bb = make([]*binding, len(bindings)+1)
  978. } else {
  979. bb = bindings[:len(bindings)+1]
  980. }
  981. copy(bb[1:], bindings)
  982. db = &binding{
  983. scope: c.scope,
  984. isConst: true,
  985. isStrict: true,
  986. }
  987. bb[0] = db
  988. c.scope.bindings = bb
  989. }
  990. c.compileFunctions(funcs)
  991. if needResult {
  992. c.emit(clearResult)
  993. }
  994. jumps := make([]int, len(v.Body))
  995. for i, s := range v.Body {
  996. if s.Test != nil {
  997. if db != nil {
  998. db.emitGet()
  999. } else {
  1000. c.emit(dup)
  1001. }
  1002. c.compileExpression(s.Test).emitGetter(true)
  1003. c.emit(op_strict_eq)
  1004. if db != nil {
  1005. c.emit(jne(2))
  1006. } else {
  1007. c.emit(jne(3), pop)
  1008. }
  1009. jumps[i] = len(c.p.code)
  1010. c.emit(nil)
  1011. }
  1012. }
  1013. if db == nil {
  1014. c.emit(pop)
  1015. }
  1016. jumpNoMatch := -1
  1017. if v.Default != -1 {
  1018. if v.Default != 0 {
  1019. jumps[v.Default] = len(c.p.code)
  1020. c.emit(nil)
  1021. }
  1022. } else {
  1023. jumpNoMatch = len(c.p.code)
  1024. c.emit(nil)
  1025. }
  1026. for i, s := range v.Body {
  1027. if s.Test != nil || i != 0 {
  1028. c.p.code[jumps[i]] = jump(len(c.p.code) - jumps[i])
  1029. }
  1030. c.compileStatements(s.Consequent, needResult)
  1031. }
  1032. if jumpNoMatch != -1 {
  1033. c.p.code[jumpNoMatch] = jump(len(c.p.code) - jumpNoMatch)
  1034. }
  1035. if enter != nil {
  1036. c.leaveScopeBlock(enter)
  1037. enter.stackSize--
  1038. c.popScope()
  1039. }
  1040. c.leaveBlock()
  1041. }