1package goja 2 3import ( 4 "fmt" 5 "github.com/dop251/goja/ast" 6 "github.com/dop251/goja/file" 7 "github.com/dop251/goja/token" 8 "github.com/dop251/goja/unistring" 9) 10 11type compiledExpr interface { 12 emitGetter(putOnStack bool) 13 emitSetter(valueExpr compiledExpr, putOnStack bool) 14 emitRef() 15 emitUnary(prepare, body func(), postfix, putOnStack bool) 16 deleteExpr() compiledExpr 17 constant() bool 18 addSrcMap() 19} 20 21type compiledExprOrRef interface { 22 compiledExpr 23 emitGetterOrRef() 24} 25 26type compiledCallExpr struct { 27 baseCompiledExpr 28 args []compiledExpr 29 callee compiledExpr 30 31 isVariadic bool 32} 33 34type compiledNewExpr struct { 35 compiledCallExpr 36} 37 38type compiledObjectLiteral struct { 39 baseCompiledExpr 40 expr *ast.ObjectLiteral 41} 42 43type compiledArrayLiteral struct { 44 baseCompiledExpr 45 expr *ast.ArrayLiteral 46} 47 48type compiledRegexpLiteral struct { 49 baseCompiledExpr 50 expr *ast.RegExpLiteral 51} 52 53type compiledLiteral struct { 54 baseCompiledExpr 55 val Value 56} 57 58type compiledTemplateLiteral struct { 59 baseCompiledExpr 60 tag compiledExpr 61 elements []*ast.TemplateElement 62 expressions []compiledExpr 63} 64 65type compiledAssignExpr struct { 66 baseCompiledExpr 67 left, right compiledExpr 68 operator token.Token 69} 70 71type compiledObjectAssignmentPattern struct { 72 baseCompiledExpr 73 expr *ast.ObjectPattern 74} 75 76type compiledArrayAssignmentPattern struct { 77 baseCompiledExpr 78 expr *ast.ArrayPattern 79} 80 81type deleteGlobalExpr struct { 82 baseCompiledExpr 83 name unistring.String 84} 85 86type deleteVarExpr struct { 87 baseCompiledExpr 88 name unistring.String 89} 90 91type deletePropExpr struct { 92 baseCompiledExpr 93 left compiledExpr 94 name unistring.String 95} 96 97type deleteElemExpr struct { 98 baseCompiledExpr 99 left, member compiledExpr 100} 101 102type constantExpr struct { 103 baseCompiledExpr 104 val Value 105} 106 107type baseCompiledExpr struct { 108 c *compiler 109 offset int 110} 111 112type compiledIdentifierExpr struct { 113 baseCompiledExpr 114 name unistring.String 115} 116 117type compiledFunctionLiteral struct { 118 baseCompiledExpr 119 name *ast.Identifier 120 parameterList *ast.ParameterList 121 body []ast.Statement 122 source string 123 declarationList []*ast.VariableDeclaration 124 lhsName unistring.String 125 strict *ast.StringLiteral 126 isExpr bool 127 isArrow bool 128} 129 130type compiledBracketExpr struct { 131 baseCompiledExpr 132 left, member compiledExpr 133} 134 135type compiledThisExpr struct { 136 baseCompiledExpr 137} 138 139type compiledNewTarget struct { 140 baseCompiledExpr 141} 142 143type compiledSequenceExpr struct { 144 baseCompiledExpr 145 sequence []compiledExpr 146} 147 148type compiledUnaryExpr struct { 149 baseCompiledExpr 150 operand compiledExpr 151 operator token.Token 152 postfix bool 153} 154 155type compiledConditionalExpr struct { 156 baseCompiledExpr 157 test, consequent, alternate compiledExpr 158} 159 160type compiledLogicalOr struct { 161 baseCompiledExpr 162 left, right compiledExpr 163} 164 165type compiledLogicalAnd struct { 166 baseCompiledExpr 167 left, right compiledExpr 168} 169 170type compiledBinaryExpr struct { 171 baseCompiledExpr 172 left, right compiledExpr 173 operator token.Token 174} 175 176type compiledEnumGetExpr struct { 177 baseCompiledExpr 178} 179 180type defaultDeleteExpr struct { 181 baseCompiledExpr 182 expr compiledExpr 183} 184 185type compiledSpreadCallArgument struct { 186 baseCompiledExpr 187 expr compiledExpr 188} 189 190func (e *defaultDeleteExpr) emitGetter(putOnStack bool) { 191 e.expr.emitGetter(false) 192 if putOnStack { 193 e.c.emit(loadVal(e.c.p.defineLiteralValue(valueTrue))) 194 } 195} 196 197func (c *compiler) compileExpression(v ast.Expression) compiledExpr { 198 // log.Printf("compileExpression: %T", v) 199 switch v := v.(type) { 200 case nil: 201 return nil 202 case *ast.AssignExpression: 203 return c.compileAssignExpression(v) 204 case *ast.NumberLiteral: 205 return c.compileNumberLiteral(v) 206 case *ast.StringLiteral: 207 return c.compileStringLiteral(v) 208 case *ast.TemplateLiteral: 209 return c.compileTemplateLiteral(v) 210 case *ast.BooleanLiteral: 211 return c.compileBooleanLiteral(v) 212 case *ast.NullLiteral: 213 r := &compiledLiteral{ 214 val: _null, 215 } 216 r.init(c, v.Idx0()) 217 return r 218 case *ast.Identifier: 219 return c.compileIdentifierExpression(v) 220 case *ast.CallExpression: 221 return c.compileCallExpression(v) 222 case *ast.ObjectLiteral: 223 return c.compileObjectLiteral(v) 224 case *ast.ArrayLiteral: 225 return c.compileArrayLiteral(v) 226 case *ast.RegExpLiteral: 227 return c.compileRegexpLiteral(v) 228 case *ast.BinaryExpression: 229 return c.compileBinaryExpression(v) 230 case *ast.UnaryExpression: 231 return c.compileUnaryExpression(v) 232 case *ast.ConditionalExpression: 233 return c.compileConditionalExpression(v) 234 case *ast.FunctionLiteral: 235 return c.compileFunctionLiteral(v, true) 236 case *ast.ArrowFunctionLiteral: 237 return c.compileArrowFunctionLiteral(v) 238 case *ast.DotExpression: 239 r := &compiledDotExpr{ 240 left: c.compileExpression(v.Left), 241 name: v.Identifier.Name, 242 } 243 r.init(c, v.Idx0()) 244 return r 245 case *ast.BracketExpression: 246 r := &compiledBracketExpr{ 247 left: c.compileExpression(v.Left), 248 member: c.compileExpression(v.Member), 249 } 250 r.init(c, v.Idx0()) 251 return r 252 case *ast.ThisExpression: 253 r := &compiledThisExpr{} 254 r.init(c, v.Idx0()) 255 return r 256 case *ast.SequenceExpression: 257 return c.compileSequenceExpression(v) 258 case *ast.NewExpression: 259 return c.compileNewExpression(v) 260 case *ast.MetaProperty: 261 return c.compileMetaProperty(v) 262 case *ast.ObjectPattern: 263 return c.compileObjectAssignmentPattern(v) 264 case *ast.ArrayPattern: 265 return c.compileArrayAssignmentPattern(v) 266 default: 267 panic(fmt.Errorf("Unknown expression type: %T", v)) 268 } 269} 270 271func (e *baseCompiledExpr) constant() bool { 272 return false 273} 274 275func (e *baseCompiledExpr) init(c *compiler, idx file.Idx) { 276 e.c = c 277 e.offset = int(idx) - 1 278} 279 280func (e *baseCompiledExpr) emitSetter(compiledExpr, bool) { 281 e.c.throwSyntaxError(e.offset, "Not a valid left-value expression") 282} 283 284func (e *baseCompiledExpr) emitRef() { 285 e.c.throwSyntaxError(e.offset, "Cannot emit reference for this type of expression") 286} 287 288func (e *baseCompiledExpr) deleteExpr() compiledExpr { 289 r := &constantExpr{ 290 val: valueTrue, 291 } 292 r.init(e.c, file.Idx(e.offset+1)) 293 return r 294} 295 296func (e *baseCompiledExpr) emitUnary(func(), func(), bool, bool) { 297 e.c.throwSyntaxError(e.offset, "Not a valid left-value expression") 298} 299 300func (e *baseCompiledExpr) addSrcMap() { 301 if e.offset > 0 { 302 e.c.p.srcMap = append(e.c.p.srcMap, srcMapItem{pc: len(e.c.p.code), srcPos: e.offset}) 303 } 304} 305 306func (e *constantExpr) emitGetter(putOnStack bool) { 307 if putOnStack { 308 e.addSrcMap() 309 e.c.emit(loadVal(e.c.p.defineLiteralValue(e.val))) 310 } 311} 312 313func (e *compiledIdentifierExpr) emitGetter(putOnStack bool) { 314 e.addSrcMap() 315 if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics { 316 if b != nil { 317 if putOnStack { 318 b.emitGet() 319 } else { 320 b.emitGetP() 321 } 322 } else { 323 panic("No dynamics and not found") 324 } 325 } else { 326 if b != nil { 327 b.emitGetVar(false) 328 } else { 329 e.c.emit(loadDynamic(e.name)) 330 } 331 if !putOnStack { 332 e.c.emit(pop) 333 } 334 } 335} 336 337func (e *compiledIdentifierExpr) emitGetterOrRef() { 338 e.addSrcMap() 339 if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics { 340 if b != nil { 341 b.emitGet() 342 } else { 343 panic("No dynamics and not found") 344 } 345 } else { 346 if b != nil { 347 b.emitGetVar(false) 348 } else { 349 e.c.emit(loadDynamicRef(e.name)) 350 } 351 } 352} 353 354func (e *compiledIdentifierExpr) emitGetterAndCallee() { 355 e.addSrcMap() 356 if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics { 357 if b != nil { 358 e.c.emit(loadUndef) 359 b.emitGet() 360 } else { 361 panic("No dynamics and not found") 362 } 363 } else { 364 if b != nil { 365 b.emitGetVar(true) 366 } else { 367 e.c.emit(loadDynamicCallee(e.name)) 368 } 369 } 370} 371 372func (c *compiler) emitVarSetter1(name unistring.String, offset int, putOnStack bool, emitRight func(isRef bool)) { 373 if c.scope.strict { 374 c.checkIdentifierLName(name, offset) 375 } 376 377 if b, noDynamics := c.scope.lookupName(name); noDynamics { 378 emitRight(false) 379 if b != nil { 380 if putOnStack { 381 b.emitSet() 382 } else { 383 b.emitSetP() 384 } 385 } else { 386 if c.scope.strict { 387 c.emit(setGlobalStrict(name)) 388 } else { 389 c.emit(setGlobal(name)) 390 } 391 if !putOnStack { 392 c.emit(pop) 393 } 394 } 395 } else { 396 if b != nil { 397 b.emitResolveVar(c.scope.strict) 398 } else { 399 if c.scope.strict { 400 c.emit(resolveVar1Strict(name)) 401 } else { 402 c.emit(resolveVar1(name)) 403 } 404 } 405 emitRight(true) 406 if putOnStack { 407 c.emit(putValue) 408 } else { 409 c.emit(putValueP) 410 } 411 } 412} 413 414func (c *compiler) emitVarSetter(name unistring.String, offset int, valueExpr compiledExpr, putOnStack bool) { 415 c.emitVarSetter1(name, offset, putOnStack, func(bool) { 416 c.emitExpr(valueExpr, true) 417 }) 418} 419 420func (c *compiler) emitVarRef(name unistring.String, offset int) { 421 if c.scope.strict { 422 c.checkIdentifierLName(name, offset) 423 } 424 425 b, _ := c.scope.lookupName(name) 426 if b != nil { 427 b.emitResolveVar(c.scope.strict) 428 } else { 429 if c.scope.strict { 430 c.emit(resolveVar1Strict(name)) 431 } else { 432 c.emit(resolveVar1(name)) 433 } 434 } 435} 436 437func (e *compiledIdentifierExpr) emitRef() { 438 e.c.emitVarRef(e.name, e.offset) 439} 440 441func (e *compiledIdentifierExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) { 442 e.c.emitVarSetter(e.name, e.offset, valueExpr, putOnStack) 443} 444 445func (e *compiledIdentifierExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) { 446 if putOnStack { 447 e.c.emitVarSetter1(e.name, e.offset, true, func(isRef bool) { 448 e.c.emit(loadUndef) 449 if isRef { 450 e.c.emit(getValue) 451 } else { 452 e.emitGetter(true) 453 } 454 if prepare != nil { 455 prepare() 456 } 457 if !postfix { 458 body() 459 } 460 e.c.emit(rdupN(1)) 461 if postfix { 462 body() 463 } 464 }) 465 e.c.emit(pop) 466 } else { 467 e.c.emitVarSetter1(e.name, e.offset, false, func(isRef bool) { 468 if isRef { 469 e.c.emit(getValue) 470 } else { 471 e.emitGetter(true) 472 } 473 body() 474 }) 475 } 476} 477 478func (e *compiledIdentifierExpr) deleteExpr() compiledExpr { 479 if e.c.scope.strict { 480 e.c.throwSyntaxError(e.offset, "Delete of an unqualified identifier in strict mode") 481 panic("Unreachable") 482 } 483 if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics { 484 if b == nil { 485 r := &deleteGlobalExpr{ 486 name: e.name, 487 } 488 r.init(e.c, file.Idx(0)) 489 return r 490 } 491 } else { 492 if b == nil { 493 r := &deleteVarExpr{ 494 name: e.name, 495 } 496 r.init(e.c, file.Idx(e.offset+1)) 497 return r 498 } 499 } 500 r := &compiledLiteral{ 501 val: valueFalse, 502 } 503 r.init(e.c, file.Idx(e.offset+1)) 504 return r 505} 506 507type compiledDotExpr struct { 508 baseCompiledExpr 509 left compiledExpr 510 name unistring.String 511} 512 513func (e *compiledDotExpr) emitGetter(putOnStack bool) { 514 e.left.emitGetter(true) 515 e.addSrcMap() 516 e.c.emit(getProp(e.name)) 517 if !putOnStack { 518 e.c.emit(pop) 519 } 520} 521 522func (e *compiledDotExpr) emitRef() { 523 e.left.emitGetter(true) 524 if e.c.scope.strict { 525 e.c.emit(getPropRefStrict(e.name)) 526 } else { 527 e.c.emit(getPropRef(e.name)) 528 } 529} 530 531func (e *compiledDotExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) { 532 e.left.emitGetter(true) 533 valueExpr.emitGetter(true) 534 if e.c.scope.strict { 535 if putOnStack { 536 e.c.emit(setPropStrict(e.name)) 537 } else { 538 e.c.emit(setPropStrictP(e.name)) 539 } 540 } else { 541 if putOnStack { 542 e.c.emit(setProp(e.name)) 543 } else { 544 e.c.emit(setPropP(e.name)) 545 } 546 } 547} 548 549func (e *compiledDotExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) { 550 if !putOnStack { 551 e.left.emitGetter(true) 552 e.c.emit(dup) 553 e.c.emit(getProp(e.name)) 554 body() 555 if e.c.scope.strict { 556 e.c.emit(setPropStrict(e.name), pop) 557 } else { 558 e.c.emit(setProp(e.name), pop) 559 } 560 } else { 561 if !postfix { 562 e.left.emitGetter(true) 563 e.c.emit(dup) 564 e.c.emit(getProp(e.name)) 565 if prepare != nil { 566 prepare() 567 } 568 body() 569 if e.c.scope.strict { 570 e.c.emit(setPropStrict(e.name)) 571 } else { 572 e.c.emit(setProp(e.name)) 573 } 574 } else { 575 e.c.emit(loadUndef) 576 e.left.emitGetter(true) 577 e.c.emit(dup) 578 e.c.emit(getProp(e.name)) 579 if prepare != nil { 580 prepare() 581 } 582 e.c.emit(rdupN(2)) 583 body() 584 if e.c.scope.strict { 585 e.c.emit(setPropStrict(e.name)) 586 } else { 587 e.c.emit(setProp(e.name)) 588 } 589 e.c.emit(pop) 590 } 591 } 592} 593 594func (e *compiledDotExpr) deleteExpr() compiledExpr { 595 r := &deletePropExpr{ 596 left: e.left, 597 name: e.name, 598 } 599 r.init(e.c, file.Idx(0)) 600 return r 601} 602 603func (e *compiledBracketExpr) emitGetter(putOnStack bool) { 604 e.left.emitGetter(true) 605 e.member.emitGetter(true) 606 e.addSrcMap() 607 e.c.emit(getElem) 608 if !putOnStack { 609 e.c.emit(pop) 610 } 611} 612 613func (e *compiledBracketExpr) emitRef() { 614 e.left.emitGetter(true) 615 e.member.emitGetter(true) 616 if e.c.scope.strict { 617 e.c.emit(getElemRefStrict) 618 } else { 619 e.c.emit(getElemRef) 620 } 621} 622 623func (e *compiledBracketExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) { 624 e.left.emitGetter(true) 625 e.member.emitGetter(true) 626 valueExpr.emitGetter(true) 627 if e.c.scope.strict { 628 if putOnStack { 629 e.c.emit(setElemStrict) 630 } else { 631 e.c.emit(setElemStrictP) 632 } 633 } else { 634 if putOnStack { 635 e.c.emit(setElem) 636 } else { 637 e.c.emit(setElemP) 638 } 639 } 640} 641 642func (e *compiledBracketExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) { 643 if !putOnStack { 644 e.left.emitGetter(true) 645 e.member.emitGetter(true) 646 e.c.emit(dupN(1), dupN(1)) 647 e.c.emit(getElem) 648 body() 649 if e.c.scope.strict { 650 e.c.emit(setElemStrict, pop) 651 } else { 652 e.c.emit(setElem, pop) 653 } 654 } else { 655 if !postfix { 656 e.left.emitGetter(true) 657 e.member.emitGetter(true) 658 e.c.emit(dupN(1), dupN(1)) 659 e.c.emit(getElem) 660 if prepare != nil { 661 prepare() 662 } 663 body() 664 if e.c.scope.strict { 665 e.c.emit(setElemStrict) 666 } else { 667 e.c.emit(setElem) 668 } 669 } else { 670 e.c.emit(loadUndef) 671 e.left.emitGetter(true) 672 e.member.emitGetter(true) 673 e.c.emit(dupN(1), dupN(1)) 674 e.c.emit(getElem) 675 if prepare != nil { 676 prepare() 677 } 678 e.c.emit(rdupN(3)) 679 body() 680 if e.c.scope.strict { 681 e.c.emit(setElemStrict, pop) 682 } else { 683 e.c.emit(setElem, pop) 684 } 685 } 686 } 687} 688 689func (e *compiledBracketExpr) deleteExpr() compiledExpr { 690 r := &deleteElemExpr{ 691 left: e.left, 692 member: e.member, 693 } 694 r.init(e.c, file.Idx(0)) 695 return r 696} 697 698func (e *deleteElemExpr) emitGetter(putOnStack bool) { 699 e.left.emitGetter(true) 700 e.member.emitGetter(true) 701 e.addSrcMap() 702 if e.c.scope.strict { 703 e.c.emit(deleteElemStrict) 704 } else { 705 e.c.emit(deleteElem) 706 } 707 if !putOnStack { 708 e.c.emit(pop) 709 } 710} 711 712func (e *deletePropExpr) emitGetter(putOnStack bool) { 713 e.left.emitGetter(true) 714 e.addSrcMap() 715 if e.c.scope.strict { 716 e.c.emit(deletePropStrict(e.name)) 717 } else { 718 e.c.emit(deleteProp(e.name)) 719 } 720 if !putOnStack { 721 e.c.emit(pop) 722 } 723} 724 725func (e *deleteVarExpr) emitGetter(putOnStack bool) { 726 /*if e.c.scope.strict { 727 e.c.throwSyntaxError(e.offset, "Delete of an unqualified identifier in strict mode") 728 return 729 }*/ 730 e.c.emit(deleteVar(e.name)) 731 if !putOnStack { 732 e.c.emit(pop) 733 } 734} 735 736func (e *deleteGlobalExpr) emitGetter(putOnStack bool) { 737 /*if e.c.scope.strict { 738 e.c.throwSyntaxError(e.offset, "Delete of an unqualified identifier in strict mode") 739 return 740 }*/ 741 742 e.c.emit(deleteGlobal(e.name)) 743 if !putOnStack { 744 e.c.emit(pop) 745 } 746} 747 748func (e *compiledAssignExpr) emitGetter(putOnStack bool) { 749 e.addSrcMap() 750 switch e.operator { 751 case token.ASSIGN: 752 if fn, ok := e.right.(*compiledFunctionLiteral); ok { 753 if fn.name == nil { 754 if id, ok := e.left.(*compiledIdentifierExpr); ok { 755 fn.lhsName = id.name 756 } 757 } 758 } 759 e.left.emitSetter(e.right, putOnStack) 760 case token.PLUS: 761 e.left.emitUnary(nil, func() { 762 e.right.emitGetter(true) 763 e.c.emit(add) 764 }, false, putOnStack) 765 case token.MINUS: 766 e.left.emitUnary(nil, func() { 767 e.right.emitGetter(true) 768 e.c.emit(sub) 769 }, false, putOnStack) 770 case token.MULTIPLY: 771 e.left.emitUnary(nil, func() { 772 e.right.emitGetter(true) 773 e.c.emit(mul) 774 }, false, putOnStack) 775 case token.SLASH: 776 e.left.emitUnary(nil, func() { 777 e.right.emitGetter(true) 778 e.c.emit(div) 779 }, false, putOnStack) 780 case token.REMAINDER: 781 e.left.emitUnary(nil, func() { 782 e.right.emitGetter(true) 783 e.c.emit(mod) 784 }, false, putOnStack) 785 case token.OR: 786 e.left.emitUnary(nil, func() { 787 e.right.emitGetter(true) 788 e.c.emit(or) 789 }, false, putOnStack) 790 case token.AND: 791 e.left.emitUnary(nil, func() { 792 e.right.emitGetter(true) 793 e.c.emit(and) 794 }, false, putOnStack) 795 case token.EXCLUSIVE_OR: 796 e.left.emitUnary(nil, func() { 797 e.right.emitGetter(true) 798 e.c.emit(xor) 799 }, false, putOnStack) 800 case token.SHIFT_LEFT: 801 e.left.emitUnary(nil, func() { 802 e.right.emitGetter(true) 803 e.c.emit(sal) 804 }, false, putOnStack) 805 case token.SHIFT_RIGHT: 806 e.left.emitUnary(nil, func() { 807 e.right.emitGetter(true) 808 e.c.emit(sar) 809 }, false, putOnStack) 810 case token.UNSIGNED_SHIFT_RIGHT: 811 e.left.emitUnary(nil, func() { 812 e.right.emitGetter(true) 813 e.c.emit(shr) 814 }, false, putOnStack) 815 default: 816 panic(fmt.Errorf("Unknown assign operator: %s", e.operator.String())) 817 } 818} 819 820func (e *compiledLiteral) emitGetter(putOnStack bool) { 821 if putOnStack { 822 e.addSrcMap() 823 e.c.emit(loadVal(e.c.p.defineLiteralValue(e.val))) 824 } 825} 826 827func (e *compiledLiteral) constant() bool { 828 return true 829} 830 831func (e *compiledTemplateLiteral) emitGetter(putOnStack bool) { 832 if e.tag == nil { 833 if len(e.elements) == 0 { 834 e.c.emit(loadVal(e.c.p.defineLiteralValue(stringEmpty))) 835 } else { 836 tail := e.elements[len(e.elements)-1].Parsed 837 if len(e.elements) == 1 { 838 e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(tail)))) 839 } else { 840 stringCount := 0 841 if head := e.elements[0].Parsed; head != "" { 842 e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(head)))) 843 stringCount++ 844 } 845 e.expressions[0].emitGetter(true) 846 e.c.emit(_toString{}) 847 stringCount++ 848 for i := 1; i < len(e.elements)-1; i++ { 849 if elt := e.elements[i].Parsed; elt != "" { 850 e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(elt)))) 851 stringCount++ 852 } 853 e.expressions[i].emitGetter(true) 854 e.c.emit(_toString{}) 855 stringCount++ 856 } 857 if tail != "" { 858 e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(tail)))) 859 stringCount++ 860 } 861 e.c.emit(concatStrings(stringCount)) 862 } 863 } 864 } else { 865 cooked := make([]Value, len(e.elements)) 866 raw := make([]Value, len(e.elements)) 867 for i, elt := range e.elements { 868 raw[i] = &valueProperty{ 869 enumerable: true, 870 value: newStringValue(elt.Literal), 871 } 872 var cookedVal Value 873 if elt.Valid { 874 cookedVal = stringValueFromRaw(elt.Parsed) 875 } else { 876 cookedVal = _undefined 877 } 878 cooked[i] = &valueProperty{ 879 enumerable: true, 880 value: cookedVal, 881 } 882 } 883 e.c.emitCallee(e.tag) 884 e.c.emit(&getTaggedTmplObject{ 885 raw: raw, 886 cooked: cooked, 887 }) 888 for _, expr := range e.expressions { 889 expr.emitGetter(true) 890 } 891 e.c.emit(call(len(e.expressions) + 1)) 892 } 893 if !putOnStack { 894 e.c.emit(pop) 895 } 896} 897 898func (c *compiler) compileParameterBindingIdentifier(name unistring.String, offset int) (*binding, bool) { 899 if c.scope.strict { 900 c.checkIdentifierName(name, offset) 901 c.checkIdentifierLName(name, offset) 902 } 903 return c.scope.bindNameShadow(name) 904} 905 906func (c *compiler) compileParameterPatternIdBinding(name unistring.String, offset int) { 907 if _, unique := c.compileParameterBindingIdentifier(name, offset); !unique { 908 c.throwSyntaxError(offset, "Duplicate parameter name not allowed in this context") 909 } 910} 911 912func (c *compiler) compileParameterPatternBinding(item ast.Expression) { 913 c.createBindings(item, c.compileParameterPatternIdBinding) 914} 915 916func (e *compiledFunctionLiteral) emitGetter(putOnStack bool) { 917 savedPrg := e.c.p 918 e.c.p = &Program{ 919 src: e.c.p.src, 920 } 921 e.c.newScope() 922 s := e.c.scope 923 s.function = true 924 s.arrow = e.isArrow 925 926 var name unistring.String 927 if e.name != nil { 928 name = e.name.Name 929 } else { 930 name = e.lhsName 931 } 932 933 if name != "" { 934 e.c.p.funcName = name 935 } 936 savedBlock := e.c.block 937 defer func() { 938 e.c.block = savedBlock 939 }() 940 941 e.c.block = &block{ 942 typ: blockScope, 943 } 944 945 if !s.strict { 946 s.strict = e.strict != nil 947 } 948 949 hasPatterns := false 950 hasInits := false 951 firstDupIdx := -1 952 length := 0 953 954 if e.parameterList.Rest != nil { 955 hasPatterns = true // strictly speaking not, but we need to activate all the checks 956 } 957 958 // First, make sure that the first bindings correspond to the formal parameters 959 for _, item := range e.parameterList.List { 960 switch tgt := item.Target.(type) { 961 case *ast.Identifier: 962 offset := int(tgt.Idx) - 1 963 b, unique := e.c.compileParameterBindingIdentifier(tgt.Name, offset) 964 if !unique { 965 firstDupIdx = offset 966 } 967 b.isArg = true 968 case ast.Pattern: 969 b := s.addBinding(int(item.Idx0()) - 1) 970 b.isArg = true 971 hasPatterns = true 972 default: 973 e.c.throwSyntaxError(int(item.Idx0())-1, "Unsupported BindingElement type: %T", item) 974 return 975 } 976 if item.Initializer != nil { 977 hasInits = true 978 } 979 980 if firstDupIdx >= 0 && (hasPatterns || hasInits || s.strict || e.isArrow) { 981 e.c.throwSyntaxError(firstDupIdx, "Duplicate parameter name not allowed in this context") 982 return 983 } 984 985 if (hasPatterns || hasInits) && e.strict != nil { 986 e.c.throwSyntaxError(int(e.strict.Idx)-1, "Illegal 'use strict' directive in function with non-simple parameter list") 987 return 988 } 989 990 if !hasInits { 991 length++ 992 } 993 } 994 995 // create pattern bindings 996 if hasPatterns { 997 for _, item := range e.parameterList.List { 998 switch tgt := item.Target.(type) { 999 case *ast.Identifier: 1000 // we already created those in the previous loop, skipping 1001 default: 1002 e.c.compileParameterPatternBinding(tgt) 1003 } 1004 } 1005 if rest := e.parameterList.Rest; rest != nil { 1006 e.c.compileParameterPatternBinding(rest) 1007 } 1008 } 1009 1010 paramsCount := len(e.parameterList.List) 1011 1012 s.numArgs = paramsCount 1013 body := e.body 1014 funcs := e.c.extractFunctions(body) 1015 var calleeBinding *binding 1016 preambleLen := 4 // enter, boxThis, createArgs, set 1017 e.c.p.code = make([]instruction, preambleLen, 8) 1018 1019 emitArgsRestMark := -1 1020 firstForwardRef := -1 1021 enterFunc2Mark := -1 1022 1023 if hasPatterns || hasInits { 1024 if e.isExpr && e.name != nil { 1025 if b, created := s.bindNameLexical(e.name.Name, false, 0); created { 1026 b.isConst = true 1027 calleeBinding = b 1028 } 1029 } 1030 if calleeBinding != nil { 1031 e.c.emit(loadCallee) 1032 calleeBinding.emitInit() 1033 } 1034 for i, item := range e.parameterList.List { 1035 if pattern, ok := item.Target.(ast.Pattern); ok { 1036 i := i 1037 e.c.compilePatternInitExpr(func() { 1038 if firstForwardRef == -1 { 1039 s.bindings[i].emitGet() 1040 } else { 1041 e.c.emit(loadStackLex(-i - 1)) 1042 } 1043 }, item.Initializer, item.Target.Idx0()).emitGetter(true) 1044 e.c.emitPattern(pattern, func(target, init compiledExpr) { 1045 e.c.emitPatternLexicalAssign(target, init, false) 1046 }, false) 1047 } else if item.Initializer != nil { 1048 markGet := len(e.c.p.code) 1049 e.c.emit(nil) 1050 mark := len(e.c.p.code) 1051 e.c.emit(nil) 1052 e.c.compileExpression(item.Initializer).emitGetter(true) 1053 if firstForwardRef == -1 && (s.isDynamic() || s.bindings[i].useCount() > 0) { 1054 firstForwardRef = i 1055 } 1056 if firstForwardRef == -1 { 1057 s.bindings[i].emitGetAt(markGet) 1058 } else { 1059 e.c.p.code[markGet] = loadStackLex(-i - 1) 1060 } 1061 s.bindings[i].emitInit() 1062 e.c.p.code[mark] = jdefP(len(e.c.p.code) - mark) 1063 } else { 1064 if firstForwardRef == -1 && s.bindings[i].useCount() > 0 { 1065 firstForwardRef = i 1066 } 1067 if firstForwardRef != -1 { 1068 e.c.emit(loadStackLex(-i - 1)) 1069 s.bindings[i].emitInit() 1070 } 1071 } 1072 } 1073 if rest := e.parameterList.Rest; rest != nil { 1074 e.c.emitAssign(rest, e.c.compileEmitterExpr( 1075 func() { 1076 emitArgsRestMark = len(e.c.p.code) 1077 e.c.emit(createArgsRestStack(paramsCount)) 1078 }, rest.Idx0()), 1079 func(target, init compiledExpr) { 1080 e.c.emitPatternLexicalAssign(target, init, false) 1081 }) 1082 } 1083 if firstForwardRef != -1 { 1084 for _, b := range s.bindings { 1085 b.inStash = true 1086 } 1087 s.argsInStash = true 1088 s.needStash = true 1089 } 1090 1091 e.c.newBlockScope() 1092 varScope := e.c.scope 1093 varScope.variable = true 1094 enterFunc2Mark = len(e.c.p.code) 1095 e.c.emit(nil) 1096 e.c.compileDeclList(e.declarationList, false) 1097 e.c.createFunctionBindings(funcs) 1098 e.c.compileLexicalDeclarationsFuncBody(body, calleeBinding) 1099 for _, b := range varScope.bindings { 1100 if b.isVar { 1101 if parentBinding := s.boundNames[b.name]; parentBinding != nil && parentBinding != calleeBinding { 1102 parentBinding.emitGet() 1103 b.emitSetP() 1104 } 1105 } 1106 } 1107 } else { 1108 // To avoid triggering variable conflict when binding from non-strict direct eval(). 1109 // Parameters are supposed to be in a parent scope, hence no conflict. 1110 for _, b := range s.bindings[:paramsCount] { 1111 b.isVar = true 1112 } 1113 e.c.compileDeclList(e.declarationList, true) 1114 e.c.createFunctionBindings(funcs) 1115 e.c.compileLexicalDeclarations(body, true) 1116 if e.isExpr && e.name != nil { 1117 if b, created := s.bindNameLexical(e.name.Name, false, 0); created { 1118 b.isConst = true 1119 calleeBinding = b 1120 } 1121 } 1122 if calleeBinding != nil { 1123 e.c.emit(loadCallee) 1124 calleeBinding.emitInit() 1125 } 1126 } 1127 1128 e.c.compileFunctions(funcs) 1129 e.c.compileStatements(body, false) 1130 1131 var last ast.Statement 1132 if l := len(body); l > 0 { 1133 last = body[l-1] 1134 } 1135 if _, ok := last.(*ast.ReturnStatement); !ok { 1136 e.c.emit(loadUndef, ret) 1137 } 1138 1139 delta := 0 1140 code := e.c.p.code 1141 1142 if calleeBinding != nil && !s.isDynamic() && calleeBinding.useCount() == 1 { 1143 s.deleteBinding(calleeBinding) 1144 preambleLen += 2 1145 } 1146 1147 if !s.argsInStash && (s.argsNeeded || s.isDynamic()) { 1148 s.moveArgsToStash() 1149 } 1150 1151 if s.argsNeeded { 1152 b, created := s.bindNameLexical("arguments", false, 0) 1153 if !created && !b.isVar { 1154 s.argsNeeded = false 1155 } else { 1156 if s.strict { 1157 b.isConst = true 1158 } else { 1159 b.isVar = e.c.scope.function 1160 } 1161 pos := preambleLen - 2 1162 delta += 2 1163 if s.strict || hasPatterns || hasInits { 1164 code[pos] = createArgsUnmapped(paramsCount) 1165 } else { 1166 code[pos] = createArgsMapped(paramsCount) 1167 } 1168 pos++ 1169 b.markAccessPointAtScope(s, pos) 1170 code[pos] = storeStashP(0) 1171 } 1172 } 1173 1174 stashSize, stackSize := s.finaliseVarAlloc(0) 1175 1176 if !s.strict && s.thisNeeded { 1177 delta++ 1178 code[preambleLen-delta] = boxThis 1179 } 1180 delta++ 1181 delta = preambleLen - delta 1182 var enter instruction 1183 if stashSize > 0 || s.argsInStash { 1184 if firstForwardRef == -1 { 1185 enter1 := enterFunc{ 1186 numArgs: uint32(paramsCount), 1187 argsToStash: s.argsInStash, 1188 stashSize: uint32(stashSize), 1189 stackSize: uint32(stackSize), 1190 extensible: s.dynamic, 1191 } 1192 if s.isDynamic() { 1193 enter1.names = s.makeNamesMap() 1194 } 1195 enter = &enter1 1196 if enterFunc2Mark != -1 { 1197 ef2 := &enterFuncBody{ 1198 extensible: e.c.scope.dynamic, 1199 } 1200 e.c.updateEnterBlock(&ef2.enterBlock) 1201 e.c.p.code[enterFunc2Mark] = ef2 1202 } 1203 } else { 1204 enter1 := enterFunc1{ 1205 stashSize: uint32(stashSize), 1206 numArgs: uint32(paramsCount), 1207 argsToCopy: uint32(firstForwardRef), 1208 extensible: s.dynamic, 1209 } 1210 if s.isDynamic() { 1211 enter1.names = s.makeNamesMap() 1212 } 1213 enter = &enter1 1214 if enterFunc2Mark != -1 { 1215 ef2 := &enterFuncBody{ 1216 adjustStack: true, 1217 extensible: e.c.scope.dynamic, 1218 } 1219 e.c.updateEnterBlock(&ef2.enterBlock) 1220 e.c.p.code[enterFunc2Mark] = ef2 1221 } 1222 } 1223 if emitArgsRestMark != -1 && s.argsInStash { 1224 e.c.p.code[emitArgsRestMark] = createArgsRestStash 1225 } 1226 } else { 1227 enter = &enterFuncStashless{ 1228 stackSize: uint32(stackSize), 1229 args: uint32(paramsCount), 1230 } 1231 if enterFunc2Mark != -1 { 1232 ef2 := &enterFuncBody{ 1233 extensible: e.c.scope.dynamic, 1234 } 1235 e.c.updateEnterBlock(&ef2.enterBlock) 1236 e.c.p.code[enterFunc2Mark] = ef2 1237 } 1238 } 1239 code[delta] = enter 1240 if delta != 0 { 1241 e.c.p.code = code[delta:] 1242 for i := range e.c.p.srcMap { 1243 e.c.p.srcMap[i].pc -= delta 1244 } 1245 s.adjustBase(-delta) 1246 } 1247 1248 strict := s.strict 1249 p := e.c.p 1250 // e.c.p.dumpCode() 1251 if enterFunc2Mark != -1 { 1252 e.c.popScope() 1253 } 1254 e.c.popScope() 1255 e.c.p = savedPrg 1256 if e.isArrow { 1257 e.c.emit(&newArrowFunc{newFunc: newFunc{prg: p, length: uint32(length), name: name, source: e.source, strict: strict}}) 1258 } else { 1259 e.c.emit(&newFunc{prg: p, length: uint32(length), name: name, source: e.source, strict: strict}) 1260 } 1261 if !putOnStack { 1262 e.c.emit(pop) 1263 } 1264} 1265 1266func (c *compiler) compileFunctionLiteral(v *ast.FunctionLiteral, isExpr bool) *compiledFunctionLiteral { 1267 strictBody := c.isStrictStatement(v.Body) 1268 if v.Name != nil && (c.scope.strict || strictBody != nil) { 1269 c.checkIdentifierLName(v.Name.Name, int(v.Name.Idx)-1) 1270 } 1271 r := &compiledFunctionLiteral{ 1272 name: v.Name, 1273 parameterList: v.ParameterList, 1274 body: v.Body.List, 1275 source: v.Source, 1276 declarationList: v.DeclarationList, 1277 isExpr: isExpr, 1278 strict: strictBody, 1279 } 1280 r.init(c, v.Idx0()) 1281 return r 1282} 1283 1284func (c *compiler) compileArrowFunctionLiteral(v *ast.ArrowFunctionLiteral) *compiledFunctionLiteral { 1285 var strictBody *ast.StringLiteral 1286 var body []ast.Statement 1287 switch b := v.Body.(type) { 1288 case *ast.BlockStatement: 1289 strictBody = c.isStrictStatement(b) 1290 body = b.List 1291 case *ast.ExpressionBody: 1292 body = []ast.Statement{ 1293 &ast.ReturnStatement{ 1294 Argument: b.Expression, 1295 }, 1296 } 1297 default: 1298 c.throwSyntaxError(int(b.Idx0())-1, "Unsupported ConciseBody type: %T", b) 1299 } 1300 r := &compiledFunctionLiteral{ 1301 parameterList: v.ParameterList, 1302 body: body, 1303 source: v.Source, 1304 declarationList: v.DeclarationList, 1305 isExpr: true, 1306 isArrow: true, 1307 strict: strictBody, 1308 } 1309 r.init(c, v.Idx0()) 1310 return r 1311} 1312 1313func (e *compiledThisExpr) emitGetter(putOnStack bool) { 1314 if putOnStack { 1315 e.addSrcMap() 1316 scope := e.c.scope 1317 for ; scope != nil && (scope.arrow || !scope.function && !scope.eval); scope = scope.outer { 1318 } 1319 1320 if scope != nil { 1321 scope.thisNeeded = true 1322 e.c.emit(loadStack(0)) 1323 } else { 1324 e.c.emit(loadGlobalObject) 1325 } 1326 } 1327} 1328 1329func (e *compiledNewExpr) emitGetter(putOnStack bool) { 1330 if e.isVariadic { 1331 e.c.emit(startVariadic) 1332 } 1333 e.callee.emitGetter(true) 1334 for _, expr := range e.args { 1335 expr.emitGetter(true) 1336 } 1337 e.addSrcMap() 1338 if e.isVariadic { 1339 e.c.emit(newVariadic, endVariadic) 1340 } else { 1341 e.c.emit(_new(len(e.args))) 1342 } 1343 if !putOnStack { 1344 e.c.emit(pop) 1345 } 1346} 1347 1348func (c *compiler) compileCallArgs(list []ast.Expression) (args []compiledExpr, isVariadic bool) { 1349 args = make([]compiledExpr, len(list)) 1350 for i, argExpr := range list { 1351 if spread, ok := argExpr.(*ast.SpreadElement); ok { 1352 args[i] = c.compileSpreadCallArgument(spread) 1353 isVariadic = true 1354 } else { 1355 args[i] = c.compileExpression(argExpr) 1356 } 1357 } 1358 return 1359} 1360 1361func (c *compiler) compileNewExpression(v *ast.NewExpression) compiledExpr { 1362 args, isVariadic := c.compileCallArgs(v.ArgumentList) 1363 r := &compiledNewExpr{ 1364 compiledCallExpr: compiledCallExpr{ 1365 callee: c.compileExpression(v.Callee), 1366 args: args, 1367 isVariadic: isVariadic, 1368 }, 1369 } 1370 r.init(c, v.Idx0()) 1371 return r 1372} 1373 1374func (e *compiledNewTarget) emitGetter(putOnStack bool) { 1375 if putOnStack { 1376 e.addSrcMap() 1377 e.c.emit(loadNewTarget) 1378 } 1379} 1380 1381func (c *compiler) compileMetaProperty(v *ast.MetaProperty) compiledExpr { 1382 if v.Meta.Name == "new" || v.Property.Name != "target" { 1383 r := &compiledNewTarget{} 1384 r.init(c, v.Idx0()) 1385 return r 1386 } 1387 c.throwSyntaxError(int(v.Idx)-1, "Unsupported meta property: %s.%s", v.Meta.Name, v.Property.Name) 1388 return nil 1389} 1390 1391func (e *compiledSequenceExpr) emitGetter(putOnStack bool) { 1392 if len(e.sequence) > 0 { 1393 for i := 0; i < len(e.sequence)-1; i++ { 1394 e.sequence[i].emitGetter(false) 1395 } 1396 e.sequence[len(e.sequence)-1].emitGetter(putOnStack) 1397 } 1398} 1399 1400func (c *compiler) compileSequenceExpression(v *ast.SequenceExpression) compiledExpr { 1401 s := make([]compiledExpr, len(v.Sequence)) 1402 for i, expr := range v.Sequence { 1403 s[i] = c.compileExpression(expr) 1404 } 1405 r := &compiledSequenceExpr{ 1406 sequence: s, 1407 } 1408 var idx file.Idx 1409 if len(v.Sequence) > 0 { 1410 idx = v.Idx0() 1411 } 1412 r.init(c, idx) 1413 return r 1414} 1415 1416func (c *compiler) emitThrow(v Value) { 1417 if o, ok := v.(*Object); ok { 1418 t := nilSafe(o.self.getStr("name", nil)).toString().String() 1419 switch t { 1420 case "TypeError": 1421 c.emit(loadDynamic(t)) 1422 msg := o.self.getStr("message", nil) 1423 if msg != nil { 1424 c.emit(loadVal(c.p.defineLiteralValue(msg))) 1425 c.emit(_new(1)) 1426 } else { 1427 c.emit(_new(0)) 1428 } 1429 c.emit(throw) 1430 return 1431 } 1432 } 1433 panic(fmt.Errorf("unknown exception type thrown while evaliating constant expression: %s", v.String())) 1434} 1435 1436func (c *compiler) emitConst(expr compiledExpr, putOnStack bool) { 1437 v, ex := c.evalConst(expr) 1438 if ex == nil { 1439 if putOnStack { 1440 c.emit(loadVal(c.p.defineLiteralValue(v))) 1441 } 1442 } else { 1443 c.emitThrow(ex.val) 1444 } 1445} 1446 1447func (c *compiler) emitExpr(expr compiledExpr, putOnStack bool) { 1448 if expr.constant() { 1449 c.emitConst(expr, putOnStack) 1450 } else { 1451 expr.emitGetter(putOnStack) 1452 } 1453} 1454 1455func (c *compiler) evalConst(expr compiledExpr) (Value, *Exception) { 1456 if expr, ok := expr.(*compiledLiteral); ok { 1457 return expr.val, nil 1458 } 1459 if c.evalVM == nil { 1460 c.evalVM = New().vm 1461 } 1462 var savedPrg *Program 1463 createdPrg := false 1464 if c.evalVM.prg == nil { 1465 c.evalVM.prg = &Program{} 1466 savedPrg = c.p 1467 c.p = c.evalVM.prg 1468 createdPrg = true 1469 } 1470 savedPc := len(c.p.code) 1471 expr.emitGetter(true) 1472 c.emit(halt) 1473 c.evalVM.pc = savedPc 1474 ex := c.evalVM.runTry() 1475 if createdPrg { 1476 c.evalVM.prg = nil 1477 c.evalVM.pc = 0 1478 c.p = savedPrg 1479 } else { 1480 c.evalVM.prg.code = c.evalVM.prg.code[:savedPc] 1481 c.p.code = c.evalVM.prg.code 1482 } 1483 if ex == nil { 1484 return c.evalVM.pop(), nil 1485 } 1486 return nil, ex 1487} 1488 1489func (e *compiledUnaryExpr) constant() bool { 1490 return e.operand.constant() 1491} 1492 1493func (e *compiledUnaryExpr) emitGetter(putOnStack bool) { 1494 var prepare, body func() 1495 1496 toNumber := func() { 1497 e.c.emit(toNumber) 1498 } 1499 1500 switch e.operator { 1501 case token.NOT: 1502 e.operand.emitGetter(true) 1503 e.c.emit(not) 1504 goto end 1505 case token.BITWISE_NOT: 1506 e.operand.emitGetter(true) 1507 e.c.emit(bnot) 1508 goto end 1509 case token.TYPEOF: 1510 if o, ok := e.operand.(compiledExprOrRef); ok { 1511 o.emitGetterOrRef() 1512 } else { 1513 e.operand.emitGetter(true) 1514 } 1515 e.c.emit(typeof) 1516 goto end 1517 case token.DELETE: 1518 e.operand.deleteExpr().emitGetter(putOnStack) 1519 return 1520 case token.MINUS: 1521 e.c.emitExpr(e.operand, true) 1522 e.c.emit(neg) 1523 goto end 1524 case token.PLUS: 1525 e.c.emitExpr(e.operand, true) 1526 e.c.emit(plus) 1527 goto end 1528 case token.INCREMENT: 1529 prepare = toNumber 1530 body = func() { 1531 e.c.emit(inc) 1532 } 1533 case token.DECREMENT: 1534 prepare = toNumber 1535 body = func() { 1536 e.c.emit(dec) 1537 } 1538 case token.VOID: 1539 e.c.emitExpr(e.operand, false) 1540 if putOnStack { 1541 e.c.emit(loadUndef) 1542 } 1543 return 1544 default: 1545 panic(fmt.Errorf("Unknown unary operator: %s", e.operator.String())) 1546 } 1547 1548 e.operand.emitUnary(prepare, body, e.postfix, putOnStack) 1549 return 1550 1551end: 1552 if !putOnStack { 1553 e.c.emit(pop) 1554 } 1555} 1556 1557func (c *compiler) compileUnaryExpression(v *ast.UnaryExpression) compiledExpr { 1558 r := &compiledUnaryExpr{ 1559 operand: c.compileExpression(v.Operand), 1560 operator: v.Operator, 1561 postfix: v.Postfix, 1562 } 1563 r.init(c, v.Idx0()) 1564 return r 1565} 1566 1567func (e *compiledConditionalExpr) emitGetter(putOnStack bool) { 1568 e.test.emitGetter(true) 1569 j := len(e.c.p.code) 1570 e.c.emit(nil) 1571 e.consequent.emitGetter(putOnStack) 1572 j1 := len(e.c.p.code) 1573 e.c.emit(nil) 1574 e.c.p.code[j] = jne(len(e.c.p.code) - j) 1575 e.alternate.emitGetter(putOnStack) 1576 e.c.p.code[j1] = jump(len(e.c.p.code) - j1) 1577} 1578 1579func (c *compiler) compileConditionalExpression(v *ast.ConditionalExpression) compiledExpr { 1580 r := &compiledConditionalExpr{ 1581 test: c.compileExpression(v.Test), 1582 consequent: c.compileExpression(v.Consequent), 1583 alternate: c.compileExpression(v.Alternate), 1584 } 1585 r.init(c, v.Idx0()) 1586 return r 1587} 1588 1589func (e *compiledLogicalOr) constant() bool { 1590 if e.left.constant() { 1591 if v, ex := e.c.evalConst(e.left); ex == nil { 1592 if v.ToBoolean() { 1593 return true 1594 } 1595 return e.right.constant() 1596 } else { 1597 return true 1598 } 1599 } 1600 1601 return false 1602} 1603 1604func (e *compiledLogicalOr) emitGetter(putOnStack bool) { 1605 if e.left.constant() { 1606 if v, ex := e.c.evalConst(e.left); ex == nil { 1607 if !v.ToBoolean() { 1608 e.c.emitExpr(e.right, putOnStack) 1609 } else { 1610 if putOnStack { 1611 e.c.emit(loadVal(e.c.p.defineLiteralValue(v))) 1612 } 1613 } 1614 } else { 1615 e.c.emitThrow(ex.val) 1616 } 1617 return 1618 } 1619 e.c.emitExpr(e.left, true) 1620 j := len(e.c.p.code) 1621 e.addSrcMap() 1622 e.c.emit(nil) 1623 e.c.emit(pop) 1624 e.c.emitExpr(e.right, true) 1625 e.c.p.code[j] = jeq1(len(e.c.p.code) - j) 1626 if !putOnStack { 1627 e.c.emit(pop) 1628 } 1629} 1630 1631func (e *compiledLogicalAnd) constant() bool { 1632 if e.left.constant() { 1633 if v, ex := e.c.evalConst(e.left); ex == nil { 1634 if !v.ToBoolean() { 1635 return true 1636 } else { 1637 return e.right.constant() 1638 } 1639 } else { 1640 return true 1641 } 1642 } 1643 1644 return false 1645} 1646 1647func (e *compiledLogicalAnd) emitGetter(putOnStack bool) { 1648 var j int 1649 if e.left.constant() { 1650 if v, ex := e.c.evalConst(e.left); ex == nil { 1651 if !v.ToBoolean() { 1652 e.c.emit(loadVal(e.c.p.defineLiteralValue(v))) 1653 } else { 1654 e.c.emitExpr(e.right, putOnStack) 1655 } 1656 } else { 1657 e.c.emitThrow(ex.val) 1658 } 1659 return 1660 } 1661 e.left.emitGetter(true) 1662 j = len(e.c.p.code) 1663 e.addSrcMap() 1664 e.c.emit(nil) 1665 e.c.emit(pop) 1666 e.c.emitExpr(e.right, true) 1667 e.c.p.code[j] = jneq1(len(e.c.p.code) - j) 1668 if !putOnStack { 1669 e.c.emit(pop) 1670 } 1671} 1672 1673func (e *compiledBinaryExpr) constant() bool { 1674 return e.left.constant() && e.right.constant() 1675} 1676 1677func (e *compiledBinaryExpr) emitGetter(putOnStack bool) { 1678 e.c.emitExpr(e.left, true) 1679 e.c.emitExpr(e.right, true) 1680 e.addSrcMap() 1681 1682 switch e.operator { 1683 case token.LESS: 1684 e.c.emit(op_lt) 1685 case token.GREATER: 1686 e.c.emit(op_gt) 1687 case token.LESS_OR_EQUAL: 1688 e.c.emit(op_lte) 1689 case token.GREATER_OR_EQUAL: 1690 e.c.emit(op_gte) 1691 case token.EQUAL: 1692 e.c.emit(op_eq) 1693 case token.NOT_EQUAL: 1694 e.c.emit(op_neq) 1695 case token.STRICT_EQUAL: 1696 e.c.emit(op_strict_eq) 1697 case token.STRICT_NOT_EQUAL: 1698 e.c.emit(op_strict_neq) 1699 case token.PLUS: 1700 e.c.emit(add) 1701 case token.MINUS: 1702 e.c.emit(sub) 1703 case token.MULTIPLY: 1704 e.c.emit(mul) 1705 case token.SLASH: 1706 e.c.emit(div) 1707 case token.REMAINDER: 1708 e.c.emit(mod) 1709 case token.AND: 1710 e.c.emit(and) 1711 case token.OR: 1712 e.c.emit(or) 1713 case token.EXCLUSIVE_OR: 1714 e.c.emit(xor) 1715 case token.INSTANCEOF: 1716 e.c.emit(op_instanceof) 1717 case token.IN: 1718 e.c.emit(op_in) 1719 case token.SHIFT_LEFT: 1720 e.c.emit(sal) 1721 case token.SHIFT_RIGHT: 1722 e.c.emit(sar) 1723 case token.UNSIGNED_SHIFT_RIGHT: 1724 e.c.emit(shr) 1725 default: 1726 panic(fmt.Errorf("Unknown operator: %s", e.operator.String())) 1727 } 1728 1729 if !putOnStack { 1730 e.c.emit(pop) 1731 } 1732} 1733 1734func (c *compiler) compileBinaryExpression(v *ast.BinaryExpression) compiledExpr { 1735 1736 switch v.Operator { 1737 case token.LOGICAL_OR: 1738 return c.compileLogicalOr(v.Left, v.Right, v.Idx0()) 1739 case token.LOGICAL_AND: 1740 return c.compileLogicalAnd(v.Left, v.Right, v.Idx0()) 1741 } 1742 1743 r := &compiledBinaryExpr{ 1744 left: c.compileExpression(v.Left), 1745 right: c.compileExpression(v.Right), 1746 operator: v.Operator, 1747 } 1748 r.init(c, v.Idx0()) 1749 return r 1750} 1751 1752func (c *compiler) compileLogicalOr(left, right ast.Expression, idx file.Idx) compiledExpr { 1753 r := &compiledLogicalOr{ 1754 left: c.compileExpression(left), 1755 right: c.compileExpression(right), 1756 } 1757 r.init(c, idx) 1758 return r 1759} 1760 1761func (c *compiler) compileLogicalAnd(left, right ast.Expression, idx file.Idx) compiledExpr { 1762 r := &compiledLogicalAnd{ 1763 left: c.compileExpression(left), 1764 right: c.compileExpression(right), 1765 } 1766 r.init(c, idx) 1767 return r 1768} 1769 1770func (e *compiledObjectLiteral) emitGetter(putOnStack bool) { 1771 e.addSrcMap() 1772 e.c.emit(newObject) 1773 for _, prop := range e.expr.Value { 1774 switch prop := prop.(type) { 1775 case *ast.PropertyKeyed: 1776 keyExpr := e.c.compileExpression(prop.Key) 1777 computed := false 1778 var key unistring.String 1779 switch keyExpr := keyExpr.(type) { 1780 case *compiledLiteral: 1781 key = keyExpr.val.string() 1782 default: 1783 keyExpr.emitGetter(true) 1784 computed = true 1785 } 1786 valueExpr := e.c.compileExpression(prop.Value) 1787 var anonFn *compiledFunctionLiteral 1788 if fn, ok := valueExpr.(*compiledFunctionLiteral); ok { 1789 if fn.name == nil { 1790 anonFn = fn 1791 fn.lhsName = key 1792 } 1793 } 1794 if computed { 1795 e.c.emit(_toPropertyKey{}) 1796 valueExpr.emitGetter(true) 1797 switch prop.Kind { 1798 case ast.PropertyKindValue, ast.PropertyKindMethod: 1799 if anonFn != nil { 1800 e.c.emit(setElem1Named) 1801 } else { 1802 e.c.emit(setElem1) 1803 } 1804 case ast.PropertyKindGet: 1805 e.c.emit(setPropGetter1) 1806 case ast.PropertyKindSet: 1807 e.c.emit(setPropSetter1) 1808 default: 1809 panic(fmt.Errorf("unknown property kind: %s", prop.Kind)) 1810 } 1811 } else { 1812 if anonFn != nil { 1813 anonFn.lhsName = key 1814 } 1815 valueExpr.emitGetter(true) 1816 switch prop.Kind { 1817 case ast.PropertyKindValue: 1818 if key == __proto__ { 1819 e.c.emit(setProto) 1820 } else { 1821 e.c.emit(setProp1(key)) 1822 } 1823 case ast.PropertyKindMethod: 1824 e.c.emit(setProp1(key)) 1825 case ast.PropertyKindGet: 1826 e.c.emit(setPropGetter(key)) 1827 case ast.PropertyKindSet: 1828 e.c.emit(setPropSetter(key)) 1829 default: 1830 panic(fmt.Errorf("unknown property kind: %s", prop.Kind)) 1831 } 1832 } 1833 case *ast.PropertyShort: 1834 key := prop.Name.Name 1835 if prop.Initializer != nil { 1836 e.c.throwSyntaxError(int(prop.Initializer.Idx0())-1, "Invalid shorthand property initializer") 1837 } 1838 if e.c.scope.strict && key == "let" { 1839 e.c.throwSyntaxError(e.offset, "'let' cannot be used as a shorthand property in strict mode") 1840 } 1841 e.c.compileIdentifierExpression(&prop.Name).emitGetter(true) 1842 e.c.emit(setProp1(key)) 1843 case *ast.SpreadElement: 1844 e.c.compileExpression(prop.Expression).emitGetter(true) 1845 e.c.emit(copySpread) 1846 default: 1847 panic(fmt.Errorf("unknown Property type: %T", prop)) 1848 } 1849 } 1850 if !putOnStack { 1851 e.c.emit(pop) 1852 } 1853} 1854 1855func (c *compiler) compileObjectLiteral(v *ast.ObjectLiteral) compiledExpr { 1856 r := &compiledObjectLiteral{ 1857 expr: v, 1858 } 1859 r.init(c, v.Idx0()) 1860 return r 1861} 1862 1863func (e *compiledArrayLiteral) emitGetter(putOnStack bool) { 1864 e.addSrcMap() 1865 hasSpread := false 1866 mark := len(e.c.p.code) 1867 e.c.emit(nil) 1868 for _, v := range e.expr.Value { 1869 if spread, ok := v.(*ast.SpreadElement); ok { 1870 hasSpread = true 1871 e.c.compileExpression(spread.Expression).emitGetter(true) 1872 e.c.emit(pushArraySpread) 1873 } else { 1874 if v != nil { 1875 e.c.compileExpression(v).emitGetter(true) 1876 } else { 1877 e.c.emit(loadNil) 1878 } 1879 e.c.emit(pushArrayItem) 1880 } 1881 } 1882 var objCount uint32 1883 if !hasSpread { 1884 objCount = uint32(len(e.expr.Value)) 1885 } 1886 e.c.p.code[mark] = newArray(objCount) 1887 if !putOnStack { 1888 e.c.emit(pop) 1889 } 1890} 1891 1892func (c *compiler) compileArrayLiteral(v *ast.ArrayLiteral) compiledExpr { 1893 r := &compiledArrayLiteral{ 1894 expr: v, 1895 } 1896 r.init(c, v.Idx0()) 1897 return r 1898} 1899 1900func (e *compiledRegexpLiteral) emitGetter(putOnStack bool) { 1901 if putOnStack { 1902 pattern, err := compileRegexp(e.expr.Pattern, e.expr.Flags) 1903 if err != nil { 1904 e.c.throwSyntaxError(e.offset, err.Error()) 1905 } 1906 1907 e.c.emit(&newRegexp{pattern: pattern, src: newStringValue(e.expr.Pattern)}) 1908 } 1909} 1910 1911func (c *compiler) compileRegexpLiteral(v *ast.RegExpLiteral) compiledExpr { 1912 r := &compiledRegexpLiteral{ 1913 expr: v, 1914 } 1915 r.init(c, v.Idx0()) 1916 return r 1917} 1918 1919func (c *compiler) emitCallee(callee compiledExpr) (calleeName unistring.String) { 1920 switch callee := callee.(type) { 1921 case *compiledDotExpr: 1922 callee.left.emitGetter(true) 1923 c.emit(dup) 1924 c.emit(getPropCallee(callee.name)) 1925 case *compiledBracketExpr: 1926 callee.left.emitGetter(true) 1927 c.emit(dup) 1928 callee.member.emitGetter(true) 1929 c.emit(getElemCallee) 1930 case *compiledIdentifierExpr: 1931 calleeName = callee.name 1932 callee.emitGetterAndCallee() 1933 default: 1934 c.emit(loadUndef) 1935 callee.emitGetter(true) 1936 } 1937 return 1938} 1939 1940func (e *compiledCallExpr) emitGetter(putOnStack bool) { 1941 if e.isVariadic { 1942 e.c.emit(startVariadic) 1943 } 1944 calleeName := e.c.emitCallee(e.callee) 1945 1946 for _, expr := range e.args { 1947 expr.emitGetter(true) 1948 } 1949 1950 e.addSrcMap() 1951 if calleeName == "eval" { 1952 foundFunc, foundVar := false, false 1953 for sc := e.c.scope; sc != nil; sc = sc.outer { 1954 if !foundFunc && sc.function && !sc.arrow { 1955 foundFunc = true 1956 sc.thisNeeded, sc.argsNeeded = true, true 1957 } 1958 if !foundVar && (sc.variable || sc.function) { 1959 foundVar = true 1960 if !sc.strict { 1961 sc.dynamic = true 1962 } 1963 } 1964 sc.dynLookup = true 1965 } 1966 1967 if e.c.scope.strict { 1968 if e.isVariadic { 1969 e.c.emit(callEvalVariadicStrict) 1970 } else { 1971 e.c.emit(callEvalStrict(len(e.args))) 1972 } 1973 } else { 1974 if e.isVariadic { 1975 e.c.emit(callEvalVariadic) 1976 } else { 1977 e.c.emit(callEval(len(e.args))) 1978 } 1979 } 1980 } else { 1981 if e.isVariadic { 1982 e.c.emit(callVariadic) 1983 } else { 1984 e.c.emit(call(len(e.args))) 1985 } 1986 } 1987 if e.isVariadic { 1988 e.c.emit(endVariadic) 1989 } 1990 if !putOnStack { 1991 e.c.emit(pop) 1992 } 1993} 1994 1995func (e *compiledCallExpr) deleteExpr() compiledExpr { 1996 r := &defaultDeleteExpr{ 1997 expr: e, 1998 } 1999 r.init(e.c, file.Idx(e.offset+1)) 2000 return r 2001} 2002 2003func (c *compiler) compileSpreadCallArgument(spread *ast.SpreadElement) compiledExpr { 2004 r := &compiledSpreadCallArgument{ 2005 expr: c.compileExpression(spread.Expression), 2006 } 2007 r.init(c, spread.Idx0()) 2008 return r 2009} 2010 2011func (c *compiler) compileCallExpression(v *ast.CallExpression) compiledExpr { 2012 2013 args := make([]compiledExpr, len(v.ArgumentList)) 2014 isVariadic := false 2015 for i, argExpr := range v.ArgumentList { 2016 if spread, ok := argExpr.(*ast.SpreadElement); ok { 2017 args[i] = c.compileSpreadCallArgument(spread) 2018 isVariadic = true 2019 } else { 2020 args[i] = c.compileExpression(argExpr) 2021 } 2022 } 2023 2024 r := &compiledCallExpr{ 2025 args: args, 2026 callee: c.compileExpression(v.Callee), 2027 isVariadic: isVariadic, 2028 } 2029 r.init(c, v.LeftParenthesis) 2030 return r 2031} 2032 2033func (c *compiler) compileIdentifierExpression(v *ast.Identifier) compiledExpr { 2034 if c.scope.strict { 2035 c.checkIdentifierName(v.Name, int(v.Idx)-1) 2036 } 2037 2038 r := &compiledIdentifierExpr{ 2039 name: v.Name, 2040 } 2041 r.offset = int(v.Idx) - 1 2042 r.init(c, v.Idx0()) 2043 return r 2044} 2045 2046func (c *compiler) compileNumberLiteral(v *ast.NumberLiteral) compiledExpr { 2047 if c.scope.strict && len(v.Literal) > 1 && v.Literal[0] == '0' && v.Literal[1] <= '7' && v.Literal[1] >= '0' { 2048 c.throwSyntaxError(int(v.Idx)-1, "Octal literals are not allowed in strict mode") 2049 panic("Unreachable") 2050 } 2051 var val Value 2052 switch num := v.Value.(type) { 2053 case int64: 2054 val = intToValue(num) 2055 case float64: 2056 val = floatToValue(num) 2057 default: 2058 panic(fmt.Errorf("Unsupported number literal type: %T", v.Value)) 2059 } 2060 r := &compiledLiteral{ 2061 val: val, 2062 } 2063 r.init(c, v.Idx0()) 2064 return r 2065} 2066 2067func (c *compiler) compileStringLiteral(v *ast.StringLiteral) compiledExpr { 2068 r := &compiledLiteral{ 2069 val: stringValueFromRaw(v.Value), 2070 } 2071 r.init(c, v.Idx0()) 2072 return r 2073} 2074 2075func (c *compiler) compileTemplateLiteral(v *ast.TemplateLiteral) compiledExpr { 2076 r := &compiledTemplateLiteral{} 2077 if v.Tag != nil { 2078 r.tag = c.compileExpression(v.Tag) 2079 } 2080 ce := make([]compiledExpr, len(v.Expressions)) 2081 for i, expr := range v.Expressions { 2082 ce[i] = c.compileExpression(expr) 2083 } 2084 r.expressions = ce 2085 r.elements = v.Elements 2086 r.init(c, v.Idx0()) 2087 return r 2088} 2089 2090func (c *compiler) compileBooleanLiteral(v *ast.BooleanLiteral) compiledExpr { 2091 var val Value 2092 if v.Value { 2093 val = valueTrue 2094 } else { 2095 val = valueFalse 2096 } 2097 2098 r := &compiledLiteral{ 2099 val: val, 2100 } 2101 r.init(c, v.Idx0()) 2102 return r 2103} 2104 2105func (c *compiler) compileAssignExpression(v *ast.AssignExpression) compiledExpr { 2106 // log.Printf("compileAssignExpression(): %+v", v) 2107 2108 r := &compiledAssignExpr{ 2109 left: c.compileExpression(v.Left), 2110 right: c.compileExpression(v.Right), 2111 operator: v.Operator, 2112 } 2113 r.init(c, v.Idx0()) 2114 return r 2115} 2116 2117func (e *compiledEnumGetExpr) emitGetter(putOnStack bool) { 2118 e.c.emit(enumGet) 2119 if !putOnStack { 2120 e.c.emit(pop) 2121 } 2122} 2123 2124func (c *compiler) compileObjectAssignmentPattern(v *ast.ObjectPattern) compiledExpr { 2125 r := &compiledObjectAssignmentPattern{ 2126 expr: v, 2127 } 2128 r.init(c, v.Idx0()) 2129 return r 2130} 2131 2132func (e *compiledObjectAssignmentPattern) emitGetter(putOnStack bool) { 2133 if putOnStack { 2134 e.c.emit(loadUndef) 2135 } 2136} 2137 2138func (c *compiler) compileArrayAssignmentPattern(v *ast.ArrayPattern) compiledExpr { 2139 r := &compiledArrayAssignmentPattern{ 2140 expr: v, 2141 } 2142 r.init(c, v.Idx0()) 2143 return r 2144} 2145 2146func (e *compiledArrayAssignmentPattern) emitGetter(putOnStack bool) { 2147 if putOnStack { 2148 e.c.emit(loadUndef) 2149 } 2150} 2151 2152func (c *compiler) emitNamed(expr compiledExpr, name unistring.String) { 2153 if en, ok := expr.(interface { 2154 emitNamed(name unistring.String) 2155 }); ok { 2156 en.emitNamed(name) 2157 } else { 2158 expr.emitGetter(true) 2159 } 2160} 2161 2162func (e *compiledFunctionLiteral) emitNamed(name unistring.String) { 2163 e.lhsName = name 2164 e.emitGetter(true) 2165} 2166 2167func (c *compiler) emitPattern(pattern ast.Pattern, emitter func(target, init compiledExpr), putOnStack bool) { 2168 switch pattern := pattern.(type) { 2169 case *ast.ObjectPattern: 2170 c.emitObjectPattern(pattern, emitter, putOnStack) 2171 case *ast.ArrayPattern: 2172 c.emitArrayPattern(pattern, emitter, putOnStack) 2173 default: 2174 panic(fmt.Errorf("unsupported Pattern: %T", pattern)) 2175 } 2176} 2177 2178func (c *compiler) emitAssign(target ast.Expression, init compiledExpr, emitAssignSimple func(target, init compiledExpr)) { 2179 pattern, isPattern := target.(ast.Pattern) 2180 if isPattern { 2181 init.emitGetter(true) 2182 c.emitPattern(pattern, emitAssignSimple, false) 2183 } else { 2184 emitAssignSimple(c.compileExpression(target), init) 2185 } 2186} 2187 2188func (c *compiler) emitObjectPattern(pattern *ast.ObjectPattern, emitAssign func(target, init compiledExpr), putOnStack bool) { 2189 if pattern.Rest != nil { 2190 c.emit(createDestructSrc) 2191 } else { 2192 c.emit(checkObjectCoercible) 2193 } 2194 for _, prop := range pattern.Properties { 2195 switch prop := prop.(type) { 2196 case *ast.PropertyShort: 2197 c.emit(dup) 2198 emitAssign(c.compileIdentifierExpression(&prop.Name), c.compilePatternInitExpr(func() { 2199 c.emit(getProp(prop.Name.Name)) 2200 }, prop.Initializer, prop.Idx0())) 2201 case *ast.PropertyKeyed: 2202 c.emit(dup) 2203 c.compileExpression(prop.Key).emitGetter(true) 2204 c.emit(_toPropertyKey{}) 2205 var target ast.Expression 2206 var initializer ast.Expression 2207 if e, ok := prop.Value.(*ast.AssignExpression); ok { 2208 target = e.Left 2209 initializer = e.Right 2210 } else { 2211 target = prop.Value 2212 } 2213 c.emitAssign(target, c.compilePatternInitExpr(func() { 2214 c.emit(getKey) 2215 }, initializer, prop.Idx0()), emitAssign) 2216 default: 2217 c.throwSyntaxError(int(prop.Idx0()-1), "Unsupported AssignmentProperty type: %T", prop) 2218 } 2219 } 2220 if pattern.Rest != nil { 2221 emitAssign(c.compileExpression(pattern.Rest), c.compileEmitterExpr(func() { 2222 c.emit(copyRest) 2223 }, pattern.Rest.Idx0())) 2224 c.emit(pop) 2225 } 2226 if !putOnStack { 2227 c.emit(pop) 2228 } 2229} 2230 2231func (c *compiler) emitArrayPattern(pattern *ast.ArrayPattern, emitAssign func(target, init compiledExpr), putOnStack bool) { 2232 var marks []int 2233 c.emit(iterate) 2234 for _, elt := range pattern.Elements { 2235 switch elt := elt.(type) { 2236 case nil: 2237 marks = append(marks, len(c.p.code)) 2238 c.emit(nil) 2239 case *ast.AssignExpression: 2240 c.emitAssign(elt.Left, c.compilePatternInitExpr(func() { 2241 marks = append(marks, len(c.p.code)) 2242 c.emit(nil, enumGet) 2243 }, elt.Right, elt.Idx0()), emitAssign) 2244 default: 2245 c.emitAssign(elt, c.compileEmitterExpr(func() { 2246 marks = append(marks, len(c.p.code)) 2247 c.emit(nil, enumGet) 2248 }, elt.Idx0()), emitAssign) 2249 } 2250 } 2251 if pattern.Rest != nil { 2252 c.emitAssign(pattern.Rest, c.compileEmitterExpr(func() { 2253 c.emit(newArrayFromIter) 2254 }, pattern.Rest.Idx0()), emitAssign) 2255 } else { 2256 c.emit(enumPopClose) 2257 } 2258 mark1 := len(c.p.code) 2259 c.emit(nil) 2260 2261 for i, elt := range pattern.Elements { 2262 switch elt := elt.(type) { 2263 case nil: 2264 c.p.code[marks[i]] = iterNext(len(c.p.code) - marks[i]) 2265 case *ast.Identifier: 2266 emitAssign(c.compileIdentifierExpression(elt), c.compileEmitterExpr(func() { 2267 c.p.code[marks[i]] = iterNext(len(c.p.code) - marks[i]) 2268 c.emit(loadUndef) 2269 }, elt.Idx0())) 2270 case *ast.AssignExpression: 2271 c.emitAssign(elt.Left, c.compileNamedEmitterExpr(func(name unistring.String) { 2272 c.p.code[marks[i]] = iterNext(len(c.p.code) - marks[i]) 2273 c.emitNamed(c.compileExpression(elt.Right), name) 2274 }, elt.Idx0()), emitAssign) 2275 default: 2276 c.emitAssign(elt, c.compileEmitterExpr( 2277 func() { 2278 c.p.code[marks[i]] = iterNext(len(c.p.code) - marks[i]) 2279 c.emit(loadUndef) 2280 }, elt.Idx0()), emitAssign) 2281 } 2282 } 2283 c.emit(enumPop) 2284 if pattern.Rest != nil { 2285 c.emitAssign(pattern.Rest, c.compileExpression( 2286 &ast.ArrayLiteral{ 2287 LeftBracket: pattern.Rest.Idx0(), 2288 RightBracket: pattern.Rest.Idx0(), 2289 }), emitAssign) 2290 } 2291 c.p.code[mark1] = jump(len(c.p.code) - mark1) 2292 2293 if !putOnStack { 2294 c.emit(pop) 2295 } 2296} 2297 2298func (e *compiledObjectAssignmentPattern) emitSetter(valueExpr compiledExpr, putOnStack bool) { 2299 valueExpr.emitGetter(true) 2300 e.c.emitObjectPattern(e.expr, e.c.emitPatternAssign, putOnStack) 2301} 2302 2303func (e *compiledArrayAssignmentPattern) emitSetter(valueExpr compiledExpr, putOnStack bool) { 2304 valueExpr.emitGetter(true) 2305 e.c.emitArrayPattern(e.expr, e.c.emitPatternAssign, putOnStack) 2306} 2307 2308type compiledPatternInitExpr struct { 2309 baseCompiledExpr 2310 emitSrc func() 2311 def compiledExpr 2312} 2313 2314func (e *compiledPatternInitExpr) emitGetter(putOnStack bool) { 2315 if !putOnStack { 2316 return 2317 } 2318 e.emitSrc() 2319 if e.def != nil { 2320 mark := len(e.c.p.code) 2321 e.c.emit(nil) 2322 e.def.emitGetter(true) 2323 e.c.p.code[mark] = jdef(len(e.c.p.code) - mark) 2324 } 2325} 2326 2327func (e *compiledPatternInitExpr) emitNamed(name unistring.String) { 2328 e.emitSrc() 2329 if e.def != nil { 2330 mark := len(e.c.p.code) 2331 e.c.emit(nil) 2332 e.c.emitNamed(e.def, name) 2333 e.c.p.code[mark] = jdef(len(e.c.p.code) - mark) 2334 } 2335} 2336 2337func (c *compiler) compilePatternInitExpr(emitSrc func(), def ast.Expression, idx file.Idx) compiledExpr { 2338 r := &compiledPatternInitExpr{ 2339 emitSrc: emitSrc, 2340 def: c.compileExpression(def), 2341 } 2342 r.init(c, idx) 2343 return r 2344} 2345 2346type compiledEmitterExpr struct { 2347 baseCompiledExpr 2348 emitter func() 2349 namedEmitter func(name unistring.String) 2350} 2351 2352func (e *compiledEmitterExpr) emitGetter(putOnStack bool) { 2353 if e.emitter != nil { 2354 e.emitter() 2355 } else { 2356 e.namedEmitter("") 2357 } 2358 if !putOnStack { 2359 e.c.emit(pop) 2360 } 2361} 2362 2363func (e *compiledEmitterExpr) emitNamed(name unistring.String) { 2364 if e.namedEmitter != nil { 2365 e.namedEmitter(name) 2366 } else { 2367 e.emitter() 2368 } 2369} 2370 2371func (c *compiler) compileEmitterExpr(emitter func(), idx file.Idx) *compiledEmitterExpr { 2372 r := &compiledEmitterExpr{ 2373 emitter: emitter, 2374 } 2375 r.init(c, idx) 2376 return r 2377} 2378 2379func (c *compiler) compileNamedEmitterExpr(namedEmitter func(unistring.String), idx file.Idx) *compiledEmitterExpr { 2380 r := &compiledEmitterExpr{ 2381 namedEmitter: namedEmitter, 2382 } 2383 r.init(c, idx) 2384 return r 2385} 2386 2387func (e *compiledSpreadCallArgument) emitGetter(putOnStack bool) { 2388 e.expr.emitGetter(putOnStack) 2389 if putOnStack { 2390 e.c.emit(pushSpread) 2391 } 2392} 2393