compiler_stmt.go 28 KB

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