compiler.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  1. package goja
  2. import (
  3. "fmt"
  4. "sort"
  5. "github.com/dop251/goja/ast"
  6. "github.com/dop251/goja/file"
  7. "github.com/dop251/goja/unistring"
  8. )
  9. type blockType int
  10. const (
  11. blockLoop blockType = iota
  12. blockLoopEnum
  13. blockTry
  14. blockLabel
  15. blockSwitch
  16. blockWith
  17. blockScope
  18. blockIterScope
  19. )
  20. const (
  21. maskConst = 1 << 31
  22. maskVar = 1 << 30
  23. maskDeletable = maskConst
  24. maskTyp = maskConst | maskVar
  25. )
  26. type varType byte
  27. const (
  28. varTypeVar varType = iota
  29. varTypeLet
  30. varTypeConst
  31. )
  32. type CompilerError struct {
  33. Message string
  34. File *file.File
  35. Offset int
  36. }
  37. type CompilerSyntaxError struct {
  38. CompilerError
  39. }
  40. type CompilerReferenceError struct {
  41. CompilerError
  42. }
  43. type srcMapItem struct {
  44. pc int
  45. srcPos int
  46. }
  47. type Program struct {
  48. code []instruction
  49. values []Value
  50. funcName unistring.String
  51. src *file.File
  52. srcMap []srcMapItem
  53. }
  54. type compiler struct {
  55. p *Program
  56. scope *scope
  57. block *block
  58. enumGetExpr compiledEnumGetExpr
  59. evalVM *vm
  60. }
  61. type binding struct {
  62. scope *scope
  63. name unistring.String
  64. accessPoints map[*scope]*[]int
  65. isConst bool
  66. isArg bool
  67. isVar bool
  68. inStash bool
  69. }
  70. func (b *binding) getAccessPointsForScope(s *scope) *[]int {
  71. m := b.accessPoints[s]
  72. if m == nil {
  73. a := make([]int, 0, 1)
  74. m = &a
  75. if b.accessPoints == nil {
  76. b.accessPoints = make(map[*scope]*[]int)
  77. }
  78. b.accessPoints[s] = m
  79. }
  80. return m
  81. }
  82. func (b *binding) markAccessPoint() {
  83. scope := b.scope.c.scope
  84. m := b.getAccessPointsForScope(scope)
  85. *m = append(*m, len(scope.prg.code)-scope.base)
  86. }
  87. func (b *binding) emitGet() {
  88. b.markAccessPoint()
  89. if b.isVar && !b.isArg {
  90. b.scope.c.emit(loadStash(0))
  91. } else {
  92. b.scope.c.emit(loadStashLex(0))
  93. }
  94. }
  95. func (b *binding) emitGetP() {
  96. if b.isVar && !b.isArg {
  97. // no-op
  98. } else {
  99. // make sure TDZ is checked
  100. b.markAccessPoint()
  101. b.scope.c.emit(loadStashLex(0), pop)
  102. }
  103. }
  104. func (b *binding) emitSet() {
  105. if b.isConst {
  106. b.scope.c.emit(throwAssignToConst)
  107. return
  108. }
  109. b.markAccessPoint()
  110. if b.isVar && !b.isArg {
  111. b.scope.c.emit(storeStash(0))
  112. } else {
  113. b.scope.c.emit(storeStashLex(0))
  114. }
  115. }
  116. func (b *binding) emitSetP() {
  117. if b.isConst {
  118. b.scope.c.emit(throwAssignToConst)
  119. return
  120. }
  121. b.markAccessPoint()
  122. if b.isVar && !b.isArg {
  123. b.scope.c.emit(storeStashP(0))
  124. } else {
  125. b.scope.c.emit(storeStashLexP(0))
  126. }
  127. }
  128. func (b *binding) emitInit() {
  129. b.markAccessPoint()
  130. b.scope.c.emit(initStash(0))
  131. }
  132. func (b *binding) emitGetVar(callee bool) {
  133. b.markAccessPoint()
  134. if b.isVar && !b.isArg {
  135. b.scope.c.emit(&loadMixed{name: b.name, callee: callee})
  136. } else {
  137. b.scope.c.emit(&loadMixedLex{name: b.name, callee: callee})
  138. }
  139. }
  140. func (b *binding) emitResolveVar(strict bool) {
  141. b.markAccessPoint()
  142. if b.isVar && !b.isArg {
  143. b.scope.c.emit(&resolveMixed{name: b.name, strict: strict, typ: varTypeVar})
  144. } else {
  145. var typ varType
  146. if b.isConst {
  147. typ = varTypeConst
  148. } else {
  149. typ = varTypeLet
  150. }
  151. b.scope.c.emit(&resolveMixed{name: b.name, strict: strict, typ: typ})
  152. }
  153. }
  154. func (b *binding) moveToStash() {
  155. if b.isArg && !b.scope.argsInStash {
  156. b.scope.moveArgsToStash()
  157. } else {
  158. b.inStash = true
  159. b.scope.needStash = true
  160. }
  161. }
  162. func (b *binding) useCount() (count int) {
  163. for _, a := range b.accessPoints {
  164. count += len(*a)
  165. }
  166. return
  167. }
  168. type scope struct {
  169. c *compiler
  170. prg *Program
  171. outer *scope
  172. nested []*scope
  173. boundNames map[unistring.String]*binding
  174. bindings []*binding
  175. base int
  176. numArgs int
  177. // in strict mode
  178. strict bool
  179. // eval top-level scope
  180. eval bool
  181. // at least one inner scope has direct eval() which can lookup names dynamically (by name)
  182. dynLookup bool
  183. // at least one binding has been marked for placement in stash
  184. needStash bool
  185. // is a function or a top-level lexical environment
  186. function bool
  187. // a function scope that has at least one direct eval() and non-strict, so the variables can be added dynamically
  188. dynamic bool
  189. // arguments have been marked for placement in stash (functions only)
  190. argsInStash bool
  191. // need 'arguments' object (functions only)
  192. argsNeeded bool
  193. // 'this' is used and non-strict, so need to box it (functions only)
  194. thisNeeded bool
  195. }
  196. type block struct {
  197. typ blockType
  198. label unistring.String
  199. cont int
  200. breaks []int
  201. conts []int
  202. outer *block
  203. breaking *block // set when the 'finally' block is an empty break statement sequence
  204. needResult bool
  205. }
  206. func (c *compiler) leaveScopeBlock(enter *enterBlock) {
  207. c.updateEnterBlock(enter)
  208. leave := &leaveBlock{
  209. stackSize: enter.stackSize,
  210. popStash: enter.stashSize > 0,
  211. }
  212. c.emit(leave)
  213. for _, pc := range c.block.breaks {
  214. c.p.code[pc] = leave
  215. }
  216. c.block.breaks = nil
  217. c.leaveBlock()
  218. }
  219. func (c *compiler) leaveBlock() {
  220. lbl := len(c.p.code)
  221. for _, item := range c.block.breaks {
  222. c.p.code[item] = jump(lbl - item)
  223. }
  224. if t := c.block.typ; t == blockLoop || t == blockLoopEnum {
  225. for _, item := range c.block.conts {
  226. c.p.code[item] = jump(c.block.cont - item)
  227. }
  228. }
  229. c.block = c.block.outer
  230. }
  231. func (e *CompilerSyntaxError) Error() string {
  232. if e.File != nil {
  233. return fmt.Sprintf("SyntaxError: %s at %s", e.Message, e.File.Position(e.Offset))
  234. }
  235. return fmt.Sprintf("SyntaxError: %s", e.Message)
  236. }
  237. func (e *CompilerReferenceError) Error() string {
  238. return fmt.Sprintf("ReferenceError: %s", e.Message)
  239. }
  240. func (c *compiler) newScope() {
  241. strict := false
  242. if c.scope != nil {
  243. strict = c.scope.strict
  244. }
  245. c.scope = &scope{
  246. c: c,
  247. prg: c.p,
  248. outer: c.scope,
  249. strict: strict,
  250. }
  251. }
  252. func (c *compiler) newBlockScope() {
  253. c.newScope()
  254. if outer := c.scope.outer; outer != nil {
  255. outer.nested = append(outer.nested, c.scope)
  256. }
  257. c.scope.base = len(c.p.code)
  258. }
  259. func (c *compiler) popScope() {
  260. c.scope = c.scope.outer
  261. }
  262. func newCompiler() *compiler {
  263. c := &compiler{
  264. p: &Program{},
  265. }
  266. c.enumGetExpr.init(c, file.Idx(0))
  267. return c
  268. }
  269. func (p *Program) defineLiteralValue(val Value) uint32 {
  270. for idx, v := range p.values {
  271. if v.SameAs(val) {
  272. return uint32(idx)
  273. }
  274. }
  275. idx := uint32(len(p.values))
  276. p.values = append(p.values, val)
  277. return idx
  278. }
  279. func (p *Program) dumpCode(logger func(format string, args ...interface{})) {
  280. p._dumpCode("", logger)
  281. }
  282. func (p *Program) _dumpCode(indent string, logger func(format string, args ...interface{})) {
  283. logger("values: %+v", p.values)
  284. for pc, ins := range p.code {
  285. logger("%s %d: %T(%v)", indent, pc, ins, ins)
  286. if f, ok := ins.(*newFunc); ok {
  287. f.prg._dumpCode(indent+">", logger)
  288. }
  289. }
  290. }
  291. func (p *Program) sourceOffset(pc int) int {
  292. i := sort.Search(len(p.srcMap), func(idx int) bool {
  293. return p.srcMap[idx].pc > pc
  294. }) - 1
  295. if i >= 0 {
  296. return p.srcMap[i].srcPos
  297. }
  298. return 0
  299. }
  300. func (s *scope) lookupName(name unistring.String) (binding *binding, noDynamics bool) {
  301. noDynamics = true
  302. toStash := false
  303. for curScope := s; curScope != nil; curScope = curScope.outer {
  304. if curScope.dynamic {
  305. noDynamics = false
  306. } else {
  307. if b, exists := curScope.boundNames[name]; exists {
  308. if toStash && !b.inStash {
  309. b.moveToStash()
  310. }
  311. binding = b
  312. return
  313. }
  314. }
  315. if name == "arguments" && curScope.function {
  316. curScope.argsNeeded = true
  317. binding, _ = curScope.bindName(name)
  318. return
  319. }
  320. if curScope.function {
  321. toStash = true
  322. }
  323. }
  324. return
  325. }
  326. func (s *scope) ensureBoundNamesCreated() {
  327. if s.boundNames == nil {
  328. s.boundNames = make(map[unistring.String]*binding)
  329. }
  330. }
  331. func (s *scope) bindNameLexical(name unistring.String, unique bool, offset int) (*binding, bool) {
  332. if b := s.boundNames[name]; b != nil {
  333. if unique {
  334. s.c.throwSyntaxError(offset, "Identifier '%s' has already been declared", name)
  335. }
  336. return b, false
  337. }
  338. if len(s.bindings) >= (1<<24)-1 {
  339. s.c.throwSyntaxError(offset, "Too many variables")
  340. }
  341. b := &binding{
  342. scope: s,
  343. name: name,
  344. }
  345. s.bindings = append(s.bindings, b)
  346. s.ensureBoundNamesCreated()
  347. s.boundNames[name] = b
  348. return b, true
  349. }
  350. func (s *scope) bindName(name unistring.String) (*binding, bool) {
  351. if !s.function && s.outer != nil {
  352. return s.outer.bindName(name)
  353. }
  354. b, created := s.bindNameLexical(name, false, 0)
  355. if created {
  356. b.isVar = true
  357. }
  358. return b, created
  359. }
  360. func (s *scope) bindNameShadow(name unistring.String) (*binding, bool) {
  361. if !s.function && s.outer != nil {
  362. return s.outer.bindNameShadow(name)
  363. }
  364. _, exists := s.boundNames[name]
  365. b := &binding{
  366. scope: s,
  367. name: name,
  368. }
  369. s.bindings = append(s.bindings, b)
  370. s.ensureBoundNamesCreated()
  371. s.boundNames[name] = b
  372. return b, !exists
  373. }
  374. func (s *scope) nearestFunction() *scope {
  375. for sc := s; sc != nil; sc = sc.outer {
  376. if sc.function {
  377. return sc
  378. }
  379. }
  380. return nil
  381. }
  382. func (s *scope) finaliseVarAlloc(stackOffset int) (stashSize, stackSize int) {
  383. argsInStash := false
  384. if f := s.nearestFunction(); f != nil {
  385. argsInStash = f.argsInStash
  386. }
  387. stackIdx, stashIdx := 0, 0
  388. allInStash := s.isDynamic()
  389. for i, b := range s.bindings {
  390. if allInStash || b.inStash {
  391. for scope, aps := range b.accessPoints {
  392. var level uint32
  393. for sc := scope; sc != nil && sc != s; sc = sc.outer {
  394. if sc.needStash || sc.isDynamic() {
  395. level++
  396. }
  397. }
  398. if level > 255 {
  399. s.c.throwSyntaxError(0, "Maximum nesting level (256) exceeded")
  400. }
  401. idx := (level << 24) | uint32(stashIdx)
  402. base := scope.base
  403. code := scope.prg.code
  404. for _, pc := range *aps {
  405. ap := &code[base+pc]
  406. switch i := (*ap).(type) {
  407. case loadStash:
  408. *ap = loadStash(idx)
  409. case storeStash:
  410. *ap = storeStash(idx)
  411. case storeStashP:
  412. *ap = storeStashP(idx)
  413. case loadStashLex:
  414. *ap = loadStashLex(idx)
  415. case storeStashLex:
  416. *ap = storeStashLex(idx)
  417. case storeStashLexP:
  418. *ap = storeStashLexP(idx)
  419. case initStash:
  420. *ap = initStash(idx)
  421. case *loadMixed:
  422. i.idx = idx
  423. case *resolveMixed:
  424. i.idx = idx
  425. }
  426. }
  427. }
  428. stashIdx++
  429. } else {
  430. var idx int
  431. if i < s.numArgs {
  432. idx = -(i + 1)
  433. } else {
  434. stackIdx++
  435. idx = stackIdx + stackOffset
  436. }
  437. for scope, aps := range b.accessPoints {
  438. var level int
  439. for sc := scope; sc != nil && sc != s; sc = sc.outer {
  440. if sc.needStash || sc.isDynamic() {
  441. level++
  442. }
  443. }
  444. if level > 255 {
  445. s.c.throwSyntaxError(0, "Maximum nesting level (256) exceeded")
  446. }
  447. code := scope.prg.code
  448. base := scope.base
  449. if argsInStash {
  450. for _, pc := range *aps {
  451. ap := &code[base+pc]
  452. switch i := (*ap).(type) {
  453. case loadStash:
  454. *ap = loadStack1(idx)
  455. case storeStash:
  456. *ap = storeStack1(idx)
  457. case storeStashP:
  458. *ap = storeStack1P(idx)
  459. case loadStashLex:
  460. *ap = loadStack1Lex(idx)
  461. case storeStashLex:
  462. *ap = storeStack1Lex(idx)
  463. case storeStashLexP:
  464. *ap = storeStack1LexP(idx)
  465. case initStash:
  466. *ap = initStack1(idx)
  467. case *loadMixed:
  468. *ap = &loadMixedStack1{name: i.name, idx: idx, level: uint8(level), callee: i.callee}
  469. case *loadMixedLex:
  470. *ap = &loadMixedStack1Lex{name: i.name, idx: idx, level: uint8(level), callee: i.callee}
  471. case *resolveMixed:
  472. *ap = &resolveMixedStack1{typ: i.typ, name: i.name, idx: idx, level: uint8(level), strict: i.strict}
  473. }
  474. }
  475. } else {
  476. for _, pc := range *aps {
  477. ap := &code[base+pc]
  478. switch i := (*ap).(type) {
  479. case loadStash:
  480. *ap = loadStack(idx)
  481. case storeStash:
  482. *ap = storeStack(idx)
  483. case storeStashP:
  484. *ap = storeStackP(idx)
  485. case loadStashLex:
  486. *ap = loadStackLex(idx)
  487. case storeStashLex:
  488. *ap = storeStackLex(idx)
  489. case storeStashLexP:
  490. *ap = storeStackLexP(idx)
  491. case initStash:
  492. *ap = initStack(idx)
  493. case *loadMixed:
  494. *ap = &loadMixedStack{name: i.name, idx: idx, level: uint8(level), callee: i.callee}
  495. case *loadMixedLex:
  496. *ap = &loadMixedStackLex{name: i.name, idx: idx, level: uint8(level), callee: i.callee}
  497. case *resolveMixed:
  498. *ap = &resolveMixedStack{typ: i.typ, name: i.name, idx: idx, level: uint8(level), strict: i.strict}
  499. }
  500. }
  501. }
  502. }
  503. }
  504. }
  505. for _, nested := range s.nested {
  506. nested.finaliseVarAlloc(stackIdx + stackOffset)
  507. }
  508. return stashIdx, stackIdx
  509. }
  510. func (s *scope) moveArgsToStash() {
  511. for _, b := range s.bindings {
  512. if !b.isArg {
  513. break
  514. }
  515. b.inStash = true
  516. }
  517. s.argsInStash = true
  518. s.needStash = true
  519. }
  520. func (s *scope) adjustBase(delta int) {
  521. s.base += delta
  522. for _, nested := range s.nested {
  523. nested.adjustBase(delta)
  524. }
  525. }
  526. func (s *scope) makeNamesMap() map[unistring.String]uint32 {
  527. l := len(s.bindings)
  528. if l == 0 {
  529. return nil
  530. }
  531. names := make(map[unistring.String]uint32, l)
  532. for i, b := range s.bindings {
  533. idx := uint32(i)
  534. if b.isConst {
  535. idx |= maskConst
  536. }
  537. if b.isVar {
  538. idx |= maskVar
  539. }
  540. names[b.name] = idx
  541. }
  542. return names
  543. }
  544. func (s *scope) isDynamic() bool {
  545. return s.dynLookup || s.dynamic
  546. }
  547. func (s *scope) deleteBinding(b *binding) {
  548. idx := 0
  549. for i, bb := range s.bindings {
  550. if bb == b {
  551. idx = i
  552. goto found
  553. }
  554. }
  555. return
  556. found:
  557. delete(s.boundNames, b.name)
  558. copy(s.bindings[idx:], s.bindings[idx+1:])
  559. l := len(s.bindings) - 1
  560. s.bindings[l] = nil
  561. s.bindings = s.bindings[:l]
  562. }
  563. func (c *compiler) compile(in *ast.Program, strict, eval, inGlobal bool) {
  564. c.p.src = in.File
  565. c.newScope()
  566. scope := c.scope
  567. scope.dynamic = true
  568. scope.eval = eval
  569. if !strict && len(in.Body) > 0 {
  570. strict = c.isStrict(in.Body)
  571. }
  572. scope.strict = strict
  573. ownVarScope := eval && strict
  574. ownLexScope := !inGlobal || eval
  575. if ownVarScope {
  576. c.newBlockScope()
  577. scope = c.scope
  578. scope.function = true
  579. }
  580. funcs := c.extractFunctions(in.Body)
  581. c.createFunctionBindings(funcs)
  582. numFuncs := len(scope.bindings)
  583. if inGlobal && !ownVarScope {
  584. if numFuncs == len(funcs) {
  585. c.compileFunctionsGlobalAllUnique(funcs)
  586. } else {
  587. c.compileFunctionsGlobal(funcs)
  588. }
  589. }
  590. c.compileDeclList(in.DeclarationList, false)
  591. numVars := len(scope.bindings) - numFuncs
  592. vars := make([]unistring.String, len(scope.bindings))
  593. for i, b := range scope.bindings {
  594. vars[i] = b.name
  595. }
  596. if len(vars) > 0 && !ownVarScope && ownLexScope {
  597. if inGlobal {
  598. c.emit(&bindGlobal{
  599. vars: vars[numFuncs:],
  600. funcs: vars[:numFuncs],
  601. deletable: eval,
  602. })
  603. } else {
  604. c.emit(&bindVars{names: vars, deletable: eval})
  605. }
  606. }
  607. var enter *enterBlock
  608. if c.compileLexicalDeclarations(in.Body, ownVarScope || !ownLexScope) {
  609. if ownLexScope {
  610. c.block = &block{
  611. outer: c.block,
  612. typ: blockScope,
  613. needResult: true,
  614. }
  615. enter = &enterBlock{}
  616. c.emit(enter)
  617. }
  618. }
  619. if len(scope.bindings) > 0 && !ownLexScope {
  620. var lets, consts []unistring.String
  621. for _, b := range c.scope.bindings[numFuncs+numVars:] {
  622. if b.isConst {
  623. consts = append(consts, b.name)
  624. } else {
  625. lets = append(lets, b.name)
  626. }
  627. }
  628. c.emit(&bindGlobal{
  629. vars: vars[numFuncs:],
  630. funcs: vars[:numFuncs],
  631. lets: lets,
  632. consts: consts,
  633. })
  634. }
  635. if !inGlobal || ownVarScope {
  636. c.compileFunctions(funcs)
  637. }
  638. c.compileStatements(in.Body, true)
  639. if enter != nil {
  640. c.leaveScopeBlock(enter)
  641. c.popScope()
  642. }
  643. c.p.code = append(c.p.code, halt)
  644. scope.finaliseVarAlloc(0)
  645. }
  646. func (c *compiler) compileDeclList(v []*ast.VariableDeclaration, inFunc bool) {
  647. for _, value := range v {
  648. c.compileVarDecl(value, inFunc)
  649. }
  650. }
  651. func (c *compiler) extractLabelled(st ast.Statement) ast.Statement {
  652. if st, ok := st.(*ast.LabelledStatement); ok {
  653. return c.extractLabelled(st.Statement)
  654. }
  655. return st
  656. }
  657. func (c *compiler) extractFunctions(list []ast.Statement) (funcs []*ast.FunctionDeclaration) {
  658. for _, st := range list {
  659. var decl *ast.FunctionDeclaration
  660. switch st := c.extractLabelled(st).(type) {
  661. case *ast.FunctionDeclaration:
  662. decl = st
  663. case *ast.LabelledStatement:
  664. if st1, ok := st.Statement.(*ast.FunctionDeclaration); ok {
  665. decl = st1
  666. } else {
  667. continue
  668. }
  669. default:
  670. continue
  671. }
  672. funcs = append(funcs, decl)
  673. }
  674. return
  675. }
  676. func (c *compiler) createFunctionBindings(funcs []*ast.FunctionDeclaration) {
  677. s := c.scope
  678. if s.outer != nil {
  679. unique := !s.function && s.strict
  680. for _, decl := range funcs {
  681. s.bindNameLexical(decl.Function.Name.Name, unique, int(decl.Function.Name.Idx1())-1)
  682. }
  683. } else {
  684. for _, decl := range funcs {
  685. s.bindName(decl.Function.Name.Name)
  686. }
  687. }
  688. }
  689. func (c *compiler) compileFunctions(list []*ast.FunctionDeclaration) {
  690. for _, decl := range list {
  691. c.compileFunction(decl)
  692. }
  693. }
  694. func (c *compiler) compileFunctionsGlobalAllUnique(list []*ast.FunctionDeclaration) {
  695. for _, decl := range list {
  696. c.compileFunctionLiteral(decl.Function, false).emitGetter(true)
  697. }
  698. }
  699. func (c *compiler) compileFunctionsGlobal(list []*ast.FunctionDeclaration) {
  700. m := make(map[unistring.String]int, len(list))
  701. for i := len(list) - 1; i >= 0; i-- {
  702. name := list[i].Function.Name.Name
  703. if _, exists := m[name]; !exists {
  704. m[name] = i
  705. }
  706. }
  707. for i, decl := range list {
  708. if m[decl.Function.Name.Name] == i {
  709. c.compileFunctionLiteral(decl.Function, false).emitGetter(true)
  710. } else {
  711. leave := c.enterDummyMode()
  712. c.compileFunctionLiteral(decl.Function, false).emitGetter(false)
  713. leave()
  714. }
  715. }
  716. }
  717. func (c *compiler) compileVarDecl(v *ast.VariableDeclaration, inFunc bool) {
  718. for _, item := range v.List {
  719. if c.scope.strict {
  720. c.checkIdentifierLName(item.Name, int(item.Idx)-1)
  721. c.checkIdentifierName(item.Name, int(item.Idx)-1)
  722. }
  723. if !inFunc || item.Name != "arguments" {
  724. c.scope.bindName(item.Name)
  725. }
  726. }
  727. }
  728. func (c *compiler) compileFunction(v *ast.FunctionDeclaration) {
  729. name := v.Function.Name.Name
  730. b := c.scope.boundNames[name]
  731. if b == nil || b.isVar {
  732. e := &compiledIdentifierExpr{
  733. name: v.Function.Name.Name,
  734. }
  735. e.init(c, v.Function.Idx0())
  736. e.emitSetter(c.compileFunctionLiteral(v.Function, false), false)
  737. } else {
  738. c.compileFunctionLiteral(v.Function, false).emitGetter(true)
  739. b.emitInit()
  740. }
  741. }
  742. func (c *compiler) compileStandaloneFunctionDecl(v *ast.FunctionDeclaration) {
  743. if c.scope.strict {
  744. c.throwSyntaxError(int(v.Idx0())-1, "In strict mode code, functions can only be declared at top level or inside a block.")
  745. }
  746. c.throwSyntaxError(int(v.Idx0())-1, "In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement.")
  747. }
  748. func (c *compiler) emit(instructions ...instruction) {
  749. c.p.code = append(c.p.code, instructions...)
  750. }
  751. func (c *compiler) throwSyntaxError(offset int, format string, args ...interface{}) {
  752. panic(&CompilerSyntaxError{
  753. CompilerError: CompilerError{
  754. File: c.p.src,
  755. Offset: offset,
  756. Message: fmt.Sprintf(format, args...),
  757. },
  758. })
  759. }
  760. func (c *compiler) isStrict(list []ast.Statement) bool {
  761. for _, st := range list {
  762. if st, ok := st.(*ast.ExpressionStatement); ok {
  763. if e, ok := st.Expression.(*ast.StringLiteral); ok {
  764. if e.Literal == `"use strict"` || e.Literal == `'use strict'` {
  765. return true
  766. }
  767. } else {
  768. break
  769. }
  770. } else {
  771. break
  772. }
  773. }
  774. return false
  775. }
  776. func (c *compiler) isStrictStatement(s ast.Statement) bool {
  777. if s, ok := s.(*ast.BlockStatement); ok {
  778. return c.isStrict(s.List)
  779. }
  780. return false
  781. }
  782. func (c *compiler) checkIdentifierName(name unistring.String, offset int) {
  783. switch name {
  784. case "implements", "interface", "let", "package", "private", "protected", "public", "static", "yield":
  785. c.throwSyntaxError(offset, "Unexpected strict mode reserved word")
  786. }
  787. }
  788. func (c *compiler) checkIdentifierLName(name unistring.String, offset int) {
  789. switch name {
  790. case "eval", "arguments":
  791. c.throwSyntaxError(offset, "Assignment to eval or arguments is not allowed in strict mode")
  792. }
  793. }
  794. // Enter a 'dummy' compilation mode. Any code produced after this method is called will be discarded after
  795. // leaveFunc is called with no additional side effects. This is useful for compiling code inside a
  796. // constant falsy condition 'if' branch or a loop (i.e 'if (false) { ... } or while (false) { ... }).
  797. // Such code should not be included in the final compilation result as it's never called, but it must
  798. // still produce compilation errors if there are any.
  799. // TODO: make sure variable lookups do not de-optimise parent scopes
  800. func (c *compiler) enterDummyMode() (leaveFunc func()) {
  801. savedBlock, savedProgram := c.block, c.p
  802. if savedBlock != nil {
  803. c.block = &block{
  804. typ: savedBlock.typ,
  805. label: savedBlock.label,
  806. outer: savedBlock.outer,
  807. breaking: savedBlock.breaking,
  808. }
  809. }
  810. c.p = &Program{}
  811. c.newScope()
  812. return func() {
  813. c.block, c.p = savedBlock, savedProgram
  814. c.popScope()
  815. }
  816. }
  817. func (c *compiler) compileStatementDummy(statement ast.Statement) {
  818. leave := c.enterDummyMode()
  819. c.compileStatement(statement, false)
  820. leave()
  821. }