compiler_stmt.go 27 KB

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