go.ketch.com/lib/goja@v0.0.1/compiler_expr.go (about) 1 package goja 2 3 import ( 4 "go.ketch.com/lib/goja/ast" 5 "go.ketch.com/lib/goja/file" 6 "go.ketch.com/lib/goja/token" 7 "go.ketch.com/lib/goja/unistring" 8 ) 9 10 type compiledExpr interface { 11 emitGetter(putOnStack bool) 12 emitSetter(valueExpr compiledExpr, putOnStack bool) 13 emitRef() 14 emitUnary(prepare, body func(), postfix, putOnStack bool) 15 deleteExpr() compiledExpr 16 constant() bool 17 addSrcMap() 18 } 19 20 type compiledExprOrRef interface { 21 compiledExpr 22 emitGetterOrRef() 23 } 24 25 type compiledCallExpr struct { 26 baseCompiledExpr 27 args []compiledExpr 28 callee compiledExpr 29 30 isVariadic bool 31 } 32 33 type compiledNewExpr struct { 34 compiledCallExpr 35 } 36 37 type compiledObjectLiteral struct { 38 baseCompiledExpr 39 expr *ast.ObjectLiteral 40 } 41 42 type compiledArrayLiteral struct { 43 baseCompiledExpr 44 expr *ast.ArrayLiteral 45 } 46 47 type compiledRegexpLiteral struct { 48 baseCompiledExpr 49 expr *ast.RegExpLiteral 50 } 51 52 type compiledLiteral struct { 53 baseCompiledExpr 54 val Value 55 } 56 57 type compiledTemplateLiteral struct { 58 baseCompiledExpr 59 tag compiledExpr 60 elements []*ast.TemplateElement 61 expressions []compiledExpr 62 } 63 64 type compiledAssignExpr struct { 65 baseCompiledExpr 66 left, right compiledExpr 67 operator token.Token 68 } 69 70 type compiledObjectAssignmentPattern struct { 71 baseCompiledExpr 72 expr *ast.ObjectPattern 73 } 74 75 type compiledArrayAssignmentPattern struct { 76 baseCompiledExpr 77 expr *ast.ArrayPattern 78 } 79 80 type deleteGlobalExpr struct { 81 baseCompiledExpr 82 name unistring.String 83 } 84 85 type deleteVarExpr struct { 86 baseCompiledExpr 87 name unistring.String 88 } 89 90 type deletePropExpr struct { 91 baseCompiledExpr 92 left compiledExpr 93 name unistring.String 94 } 95 96 type deleteElemExpr struct { 97 baseCompiledExpr 98 left, member compiledExpr 99 } 100 101 type constantExpr struct { 102 baseCompiledExpr 103 val Value 104 } 105 106 type baseCompiledExpr struct { 107 c *compiler 108 offset int 109 } 110 111 type compiledIdentifierExpr struct { 112 baseCompiledExpr 113 name unistring.String 114 } 115 116 type funcType uint8 117 118 const ( 119 funcNone funcType = iota 120 funcRegular 121 funcArrow 122 funcMethod 123 funcClsInit 124 funcCtor 125 funcDerivedCtor 126 ) 127 128 type compiledFunctionLiteral struct { 129 baseCompiledExpr 130 name *ast.Identifier 131 parameterList *ast.ParameterList 132 body []ast.Statement 133 source string 134 declarationList []*ast.VariableDeclaration 135 lhsName unistring.String 136 strict *ast.StringLiteral 137 homeObjOffset uint32 138 typ funcType 139 isExpr bool 140 } 141 142 type compiledBracketExpr struct { 143 baseCompiledExpr 144 left, member compiledExpr 145 } 146 147 type compiledThisExpr struct { 148 baseCompiledExpr 149 } 150 151 type compiledSuperExpr struct { 152 baseCompiledExpr 153 } 154 155 type compiledNewTarget struct { 156 baseCompiledExpr 157 } 158 159 type compiledSequenceExpr struct { 160 baseCompiledExpr 161 sequence []compiledExpr 162 } 163 164 type compiledUnaryExpr struct { 165 baseCompiledExpr 166 operand compiledExpr 167 operator token.Token 168 postfix bool 169 } 170 171 type compiledConditionalExpr struct { 172 baseCompiledExpr 173 test, consequent, alternate compiledExpr 174 } 175 176 type compiledLogicalOr struct { 177 baseCompiledExpr 178 left, right compiledExpr 179 } 180 181 type compiledCoalesce struct { 182 baseCompiledExpr 183 left, right compiledExpr 184 } 185 186 type compiledLogicalAnd struct { 187 baseCompiledExpr 188 left, right compiledExpr 189 } 190 191 type compiledBinaryExpr struct { 192 baseCompiledExpr 193 left, right compiledExpr 194 operator token.Token 195 } 196 197 type compiledEnumGetExpr struct { 198 baseCompiledExpr 199 } 200 201 type defaultDeleteExpr struct { 202 baseCompiledExpr 203 expr compiledExpr 204 } 205 206 type compiledSpreadCallArgument struct { 207 baseCompiledExpr 208 expr compiledExpr 209 } 210 211 type compiledOptionalChain struct { 212 baseCompiledExpr 213 expr compiledExpr 214 } 215 216 type compiledOptional struct { 217 baseCompiledExpr 218 expr compiledExpr 219 } 220 221 func (e *defaultDeleteExpr) emitGetter(putOnStack bool) { 222 e.expr.emitGetter(false) 223 if putOnStack { 224 e.c.emit(loadVal(e.c.p.defineLiteralValue(valueTrue))) 225 } 226 } 227 228 func (c *compiler) compileExpression(v ast.Expression) compiledExpr { 229 // log.Printf("compileExpression: %T", v) 230 switch v := v.(type) { 231 case nil: 232 return nil 233 case *ast.AssignExpression: 234 return c.compileAssignExpression(v) 235 case *ast.NumberLiteral: 236 return c.compileNumberLiteral(v) 237 case *ast.StringLiteral: 238 return c.compileStringLiteral(v) 239 case *ast.TemplateLiteral: 240 return c.compileTemplateLiteral(v) 241 case *ast.BooleanLiteral: 242 return c.compileBooleanLiteral(v) 243 case *ast.NullLiteral: 244 r := &compiledLiteral{ 245 val: _null, 246 } 247 r.init(c, v.Idx0()) 248 return r 249 case *ast.Identifier: 250 return c.compileIdentifierExpression(v) 251 case *ast.CallExpression: 252 return c.compileCallExpression(v) 253 case *ast.ObjectLiteral: 254 return c.compileObjectLiteral(v) 255 case *ast.ArrayLiteral: 256 return c.compileArrayLiteral(v) 257 case *ast.RegExpLiteral: 258 return c.compileRegexpLiteral(v) 259 case *ast.BinaryExpression: 260 return c.compileBinaryExpression(v) 261 case *ast.UnaryExpression: 262 return c.compileUnaryExpression(v) 263 case *ast.ConditionalExpression: 264 return c.compileConditionalExpression(v) 265 case *ast.FunctionLiteral: 266 return c.compileFunctionLiteral(v, true) 267 case *ast.ArrowFunctionLiteral: 268 return c.compileArrowFunctionLiteral(v) 269 case *ast.ClassLiteral: 270 return c.compileClassLiteral(v, true) 271 case *ast.DotExpression: 272 return c.compileDotExpression(v) 273 case *ast.PrivateDotExpression: 274 return c.compilePrivateDotExpression(v) 275 case *ast.BracketExpression: 276 return c.compileBracketExpression(v) 277 case *ast.ThisExpression: 278 r := &compiledThisExpr{} 279 r.init(c, v.Idx0()) 280 return r 281 case *ast.SuperExpression: 282 c.throwSyntaxError(int(v.Idx0())-1, "'super' keyword unexpected here") 283 panic("unreachable") 284 case *ast.SequenceExpression: 285 return c.compileSequenceExpression(v) 286 case *ast.NewExpression: 287 return c.compileNewExpression(v) 288 case *ast.MetaProperty: 289 return c.compileMetaProperty(v) 290 case *ast.ObjectPattern: 291 return c.compileObjectAssignmentPattern(v) 292 case *ast.ArrayPattern: 293 return c.compileArrayAssignmentPattern(v) 294 case *ast.OptionalChain: 295 r := &compiledOptionalChain{ 296 expr: c.compileExpression(v.Expression), 297 } 298 r.init(c, v.Idx0()) 299 return r 300 case *ast.Optional: 301 r := &compiledOptional{ 302 expr: c.compileExpression(v.Expression), 303 } 304 r.init(c, v.Idx0()) 305 return r 306 default: 307 c.assert(false, int(v.Idx0())-1, "Unknown expression type: %T", v) 308 panic("unreachable") 309 } 310 } 311 312 func (e *baseCompiledExpr) constant() bool { 313 return false 314 } 315 316 func (e *baseCompiledExpr) init(c *compiler, idx file.Idx) { 317 e.c = c 318 e.offset = int(idx) - 1 319 } 320 321 func (e *baseCompiledExpr) emitSetter(compiledExpr, bool) { 322 e.c.throwSyntaxError(e.offset, "Not a valid left-value expression") 323 } 324 325 func (e *baseCompiledExpr) emitRef() { 326 e.c.assert(false, e.offset, "Cannot emit reference for this type of expression") 327 } 328 329 func (e *baseCompiledExpr) deleteExpr() compiledExpr { 330 r := &constantExpr{ 331 val: valueTrue, 332 } 333 r.init(e.c, file.Idx(e.offset+1)) 334 return r 335 } 336 337 func (e *baseCompiledExpr) emitUnary(func(), func(), bool, bool) { 338 e.c.throwSyntaxError(e.offset, "Not a valid left-value expression") 339 } 340 341 func (e *baseCompiledExpr) addSrcMap() { 342 if e.offset >= 0 { 343 e.c.p.addSrcMap(e.offset) 344 } 345 } 346 347 func (e *constantExpr) emitGetter(putOnStack bool) { 348 if putOnStack { 349 e.addSrcMap() 350 e.c.emit(loadVal(e.c.p.defineLiteralValue(e.val))) 351 } 352 } 353 354 func (e *compiledIdentifierExpr) emitGetter(putOnStack bool) { 355 e.addSrcMap() 356 if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics { 357 e.c.assert(b != nil, e.offset, "No dynamics and not found") 358 if putOnStack { 359 b.emitGet() 360 } else { 361 b.emitGetP() 362 } 363 } else { 364 if b != nil { 365 b.emitGetVar(false) 366 } else { 367 e.c.emit(loadDynamic(e.name)) 368 } 369 if !putOnStack { 370 e.c.emit(pop) 371 } 372 } 373 } 374 375 func (e *compiledIdentifierExpr) emitGetterOrRef() { 376 e.addSrcMap() 377 if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics { 378 e.c.assert(b != nil, e.offset, "No dynamics and not found") 379 b.emitGet() 380 } else { 381 if b != nil { 382 b.emitGetVar(false) 383 } else { 384 e.c.emit(loadDynamicRef(e.name)) 385 } 386 } 387 } 388 389 func (e *compiledIdentifierExpr) emitGetterAndCallee() { 390 e.addSrcMap() 391 if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics { 392 e.c.assert(b != nil, e.offset, "No dynamics and not found") 393 e.c.emit(loadUndef) 394 b.emitGet() 395 } else { 396 if b != nil { 397 b.emitGetVar(true) 398 } else { 399 e.c.emit(loadDynamicCallee(e.name)) 400 } 401 } 402 } 403 404 func (e *compiledIdentifierExpr) emitVarSetter1(putOnStack bool, emitRight func(isRef bool)) { 405 e.addSrcMap() 406 c := e.c 407 408 if b, noDynamics := c.scope.lookupName(e.name); noDynamics { 409 if c.scope.strict { 410 c.checkIdentifierLName(e.name, e.offset) 411 } 412 emitRight(false) 413 if b != nil { 414 if putOnStack { 415 b.emitSet() 416 } else { 417 b.emitSetP() 418 } 419 } else { 420 if c.scope.strict { 421 c.emit(setGlobalStrict(e.name)) 422 } else { 423 c.emit(setGlobal(e.name)) 424 } 425 if !putOnStack { 426 c.emit(pop) 427 } 428 } 429 } else { 430 c.emitVarRef(e.name, e.offset, b) 431 emitRight(true) 432 if putOnStack { 433 c.emit(putValue) 434 } else { 435 c.emit(putValueP) 436 } 437 } 438 } 439 440 func (e *compiledIdentifierExpr) emitVarSetter(valueExpr compiledExpr, putOnStack bool) { 441 e.emitVarSetter1(putOnStack, func(bool) { 442 e.c.emitNamedOrConst(valueExpr, e.name) 443 }) 444 } 445 446 func (c *compiler) emitVarRef(name unistring.String, offset int, b *binding) { 447 if c.scope.strict { 448 c.checkIdentifierLName(name, offset) 449 } 450 451 if b != nil { 452 b.emitResolveVar(c.scope.strict) 453 } else { 454 if c.scope.strict { 455 c.emit(resolveVar1Strict(name)) 456 } else { 457 c.emit(resolveVar1(name)) 458 } 459 } 460 } 461 462 func (e *compiledIdentifierExpr) emitRef() { 463 b, _ := e.c.scope.lookupName(e.name) 464 e.c.emitVarRef(e.name, e.offset, b) 465 } 466 467 func (e *compiledIdentifierExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) { 468 e.emitVarSetter(valueExpr, putOnStack) 469 } 470 471 func (e *compiledIdentifierExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) { 472 if putOnStack { 473 e.emitVarSetter1(true, func(isRef bool) { 474 e.c.emit(loadUndef) 475 if isRef { 476 e.c.emit(getValue) 477 } else { 478 e.emitGetter(true) 479 } 480 if prepare != nil { 481 prepare() 482 } 483 if !postfix { 484 body() 485 } 486 e.c.emit(rdupN(1)) 487 if postfix { 488 body() 489 } 490 }) 491 e.c.emit(pop) 492 } else { 493 e.emitVarSetter1(false, func(isRef bool) { 494 if isRef { 495 e.c.emit(getValue) 496 } else { 497 e.emitGetter(true) 498 } 499 body() 500 }) 501 } 502 } 503 504 func (e *compiledIdentifierExpr) deleteExpr() compiledExpr { 505 if e.c.scope.strict { 506 e.c.throwSyntaxError(e.offset, "Delete of an unqualified identifier in strict mode") 507 panic("Unreachable") 508 } 509 if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics { 510 if b == nil { 511 r := &deleteGlobalExpr{ 512 name: e.name, 513 } 514 r.init(e.c, file.Idx(0)) 515 return r 516 } 517 } else { 518 if b == nil { 519 r := &deleteVarExpr{ 520 name: e.name, 521 } 522 r.init(e.c, file.Idx(e.offset+1)) 523 return r 524 } 525 } 526 r := &compiledLiteral{ 527 val: valueFalse, 528 } 529 r.init(e.c, file.Idx(e.offset+1)) 530 return r 531 } 532 533 type compiledSuperDotExpr struct { 534 baseCompiledExpr 535 name unistring.String 536 } 537 538 func (e *compiledSuperDotExpr) emitGetter(putOnStack bool) { 539 e.c.emitLoadThis() 540 e.c.emit(loadSuper) 541 e.addSrcMap() 542 e.c.emit(getPropRecv(e.name)) 543 if !putOnStack { 544 e.c.emit(pop) 545 } 546 } 547 548 func (e *compiledSuperDotExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) { 549 e.c.emitLoadThis() 550 e.c.emit(loadSuper) 551 valueExpr.emitGetter(true) 552 e.addSrcMap() 553 if putOnStack { 554 if e.c.scope.strict { 555 e.c.emit(setPropRecvStrict(e.name)) 556 } else { 557 e.c.emit(setPropRecv(e.name)) 558 } 559 } else { 560 if e.c.scope.strict { 561 e.c.emit(setPropRecvStrictP(e.name)) 562 } else { 563 e.c.emit(setPropRecvP(e.name)) 564 } 565 } 566 } 567 568 func (e *compiledSuperDotExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) { 569 if !putOnStack { 570 e.c.emitLoadThis() 571 e.c.emit(loadSuper, dupLast(2), getPropRecv(e.name)) 572 body() 573 e.addSrcMap() 574 if e.c.scope.strict { 575 e.c.emit(setPropRecvStrictP(e.name)) 576 } else { 577 e.c.emit(setPropRecvP(e.name)) 578 } 579 } else { 580 if !postfix { 581 e.c.emitLoadThis() 582 e.c.emit(loadSuper, dupLast(2), getPropRecv(e.name)) 583 if prepare != nil { 584 prepare() 585 } 586 body() 587 e.addSrcMap() 588 if e.c.scope.strict { 589 e.c.emit(setPropRecvStrict(e.name)) 590 } else { 591 e.c.emit(setPropRecv(e.name)) 592 } 593 } else { 594 e.c.emit(loadUndef) 595 e.c.emitLoadThis() 596 e.c.emit(loadSuper, dupLast(2), getPropRecv(e.name)) 597 if prepare != nil { 598 prepare() 599 } 600 e.c.emit(rdupN(3)) 601 body() 602 e.addSrcMap() 603 if e.c.scope.strict { 604 e.c.emit(setPropRecvStrictP(e.name)) 605 } else { 606 e.c.emit(setPropRecvP(e.name)) 607 } 608 } 609 } 610 } 611 612 func (e *compiledSuperDotExpr) emitRef() { 613 e.c.emitLoadThis() 614 e.c.emit(loadSuper) 615 if e.c.scope.strict { 616 e.c.emit(getPropRefRecvStrict(e.name)) 617 } else { 618 e.c.emit(getPropRefRecv(e.name)) 619 } 620 } 621 622 func (e *compiledSuperDotExpr) deleteExpr() compiledExpr { 623 return e.c.superDeleteError(e.offset) 624 } 625 626 type compiledDotExpr struct { 627 baseCompiledExpr 628 left compiledExpr 629 name unistring.String 630 } 631 632 type compiledPrivateDotExpr struct { 633 baseCompiledExpr 634 left compiledExpr 635 name unistring.String 636 } 637 638 func (c *compiler) checkSuperBase(idx file.Idx) { 639 if s := c.scope.nearestThis(); s != nil { 640 switch s.funcType { 641 case funcMethod, funcClsInit, funcCtor, funcDerivedCtor: 642 return 643 } 644 } 645 c.throwSyntaxError(int(idx)-1, "'super' keyword unexpected here") 646 panic("unreachable") 647 } 648 649 func (c *compiler) compileDotExpression(v *ast.DotExpression) compiledExpr { 650 if sup, ok := v.Left.(*ast.SuperExpression); ok { 651 c.checkSuperBase(sup.Idx) 652 r := &compiledSuperDotExpr{ 653 name: v.Identifier.Name, 654 } 655 r.init(c, v.Identifier.Idx) 656 return r 657 } 658 659 r := &compiledDotExpr{ 660 left: c.compileExpression(v.Left), 661 name: v.Identifier.Name, 662 } 663 r.init(c, v.Identifier.Idx) 664 return r 665 } 666 667 func (c *compiler) compilePrivateDotExpression(v *ast.PrivateDotExpression) compiledExpr { 668 r := &compiledPrivateDotExpr{ 669 left: c.compileExpression(v.Left), 670 name: v.Identifier.Name, 671 } 672 r.init(c, v.Identifier.Idx) 673 return r 674 } 675 676 func (e *compiledPrivateDotExpr) _emitGetter(rn *resolvedPrivateName, id *privateId) { 677 if rn != nil { 678 e.c.emit((*getPrivatePropRes)(rn)) 679 } else { 680 e.c.emit((*getPrivatePropId)(id)) 681 } 682 } 683 684 func (e *compiledPrivateDotExpr) _emitSetter(rn *resolvedPrivateName, id *privateId) { 685 if rn != nil { 686 e.c.emit((*setPrivatePropRes)(rn)) 687 } else { 688 e.c.emit((*setPrivatePropId)(id)) 689 } 690 } 691 692 func (e *compiledPrivateDotExpr) _emitSetterP(rn *resolvedPrivateName, id *privateId) { 693 if rn != nil { 694 e.c.emit((*setPrivatePropResP)(rn)) 695 } else { 696 e.c.emit((*setPrivatePropIdP)(id)) 697 } 698 } 699 700 func (e *compiledPrivateDotExpr) emitGetter(putOnStack bool) { 701 e.left.emitGetter(true) 702 e.addSrcMap() 703 rn, id := e.c.resolvePrivateName(e.name, e.offset) 704 e._emitGetter(rn, id) 705 if !putOnStack { 706 e.c.emit(pop) 707 } 708 } 709 710 func (e *compiledPrivateDotExpr) emitSetter(v compiledExpr, putOnStack bool) { 711 rn, id := e.c.resolvePrivateName(e.name, e.offset) 712 e.left.emitGetter(true) 713 v.emitGetter(true) 714 e.addSrcMap() 715 if putOnStack { 716 e._emitSetter(rn, id) 717 } else { 718 e._emitSetterP(rn, id) 719 } 720 } 721 722 func (e *compiledPrivateDotExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) { 723 rn, id := e.c.resolvePrivateName(e.name, e.offset) 724 if !putOnStack { 725 e.left.emitGetter(true) 726 e.c.emit(dup) 727 e._emitGetter(rn, id) 728 body() 729 e.addSrcMap() 730 e._emitSetterP(rn, id) 731 } else { 732 if !postfix { 733 e.left.emitGetter(true) 734 e.c.emit(dup) 735 e._emitGetter(rn, id) 736 if prepare != nil { 737 prepare() 738 } 739 body() 740 e.addSrcMap() 741 e._emitSetter(rn, id) 742 } else { 743 e.c.emit(loadUndef) 744 e.left.emitGetter(true) 745 e.c.emit(dup) 746 e._emitGetter(rn, id) 747 if prepare != nil { 748 prepare() 749 } 750 e.c.emit(rdupN(2)) 751 body() 752 e.addSrcMap() 753 e._emitSetterP(rn, id) 754 } 755 } 756 } 757 758 func (e *compiledPrivateDotExpr) deleteExpr() compiledExpr { 759 e.c.throwSyntaxError(e.offset, "Private fields can not be deleted") 760 panic("unreachable") 761 } 762 763 func (e *compiledPrivateDotExpr) emitRef() { 764 e.left.emitGetter(true) 765 rn, id := e.c.resolvePrivateName(e.name, e.offset) 766 if rn != nil { 767 e.c.emit((*getPrivateRefRes)(rn)) 768 } else { 769 e.c.emit((*getPrivateRefId)(id)) 770 } 771 } 772 773 type compiledSuperBracketExpr struct { 774 baseCompiledExpr 775 member compiledExpr 776 } 777 778 func (e *compiledSuperBracketExpr) emitGetter(putOnStack bool) { 779 e.c.emitLoadThis() 780 e.member.emitGetter(true) 781 e.c.emit(loadSuper) 782 e.addSrcMap() 783 e.c.emit(getElemRecv) 784 if !putOnStack { 785 e.c.emit(pop) 786 } 787 } 788 789 func (e *compiledSuperBracketExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) { 790 e.c.emitLoadThis() 791 e.member.emitGetter(true) 792 e.c.emit(loadSuper) 793 valueExpr.emitGetter(true) 794 e.addSrcMap() 795 if putOnStack { 796 if e.c.scope.strict { 797 e.c.emit(setElemRecvStrict) 798 } else { 799 e.c.emit(setElemRecv) 800 } 801 } else { 802 if e.c.scope.strict { 803 e.c.emit(setElemRecvStrictP) 804 } else { 805 e.c.emit(setElemRecvP) 806 } 807 } 808 } 809 810 func (e *compiledSuperBracketExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) { 811 if !putOnStack { 812 e.c.emitLoadThis() 813 e.member.emitGetter(true) 814 e.c.emit(loadSuper, dupLast(3), getElemRecv) 815 body() 816 e.addSrcMap() 817 if e.c.scope.strict { 818 e.c.emit(setElemRecvStrictP) 819 } else { 820 e.c.emit(setElemRecvP) 821 } 822 } else { 823 if !postfix { 824 e.c.emitLoadThis() 825 e.member.emitGetter(true) 826 e.c.emit(loadSuper, dupLast(3), getElemRecv) 827 if prepare != nil { 828 prepare() 829 } 830 body() 831 e.addSrcMap() 832 if e.c.scope.strict { 833 e.c.emit(setElemRecvStrict) 834 } else { 835 e.c.emit(setElemRecv) 836 } 837 } else { 838 e.c.emit(loadUndef) 839 e.c.emitLoadThis() 840 e.member.emitGetter(true) 841 e.c.emit(loadSuper, dupLast(3), getElemRecv) 842 if prepare != nil { 843 prepare() 844 } 845 e.c.emit(rdupN(4)) 846 body() 847 e.addSrcMap() 848 if e.c.scope.strict { 849 e.c.emit(setElemRecvStrictP) 850 } else { 851 e.c.emit(setElemRecvP) 852 } 853 } 854 } 855 } 856 857 func (e *compiledSuperBracketExpr) emitRef() { 858 e.c.emitLoadThis() 859 e.member.emitGetter(true) 860 e.c.emit(loadSuper) 861 if e.c.scope.strict { 862 e.c.emit(getElemRefRecvStrict) 863 } else { 864 e.c.emit(getElemRefRecv) 865 } 866 } 867 868 func (c *compiler) superDeleteError(offset int) compiledExpr { 869 return c.compileEmitterExpr(func() { 870 c.emit(throwConst{referenceError("Unsupported reference to 'super'")}) 871 }, file.Idx(offset+1)) 872 } 873 874 func (e *compiledSuperBracketExpr) deleteExpr() compiledExpr { 875 return e.c.superDeleteError(e.offset) 876 } 877 878 func (c *compiler) checkConstantString(expr compiledExpr) (unistring.String, bool) { 879 if expr.constant() { 880 if val, ex := c.evalConst(expr); ex == nil { 881 if s, ok := val.(valueString); ok { 882 return s.string(), true 883 } 884 } 885 } 886 return "", false 887 } 888 889 func (c *compiler) compileBracketExpression(v *ast.BracketExpression) compiledExpr { 890 if sup, ok := v.Left.(*ast.SuperExpression); ok { 891 c.checkSuperBase(sup.Idx) 892 member := c.compileExpression(v.Member) 893 if name, ok := c.checkConstantString(member); ok { 894 r := &compiledSuperDotExpr{ 895 name: name, 896 } 897 r.init(c, v.LeftBracket) 898 return r 899 } 900 901 r := &compiledSuperBracketExpr{ 902 member: member, 903 } 904 r.init(c, v.LeftBracket) 905 return r 906 } 907 908 left := c.compileExpression(v.Left) 909 member := c.compileExpression(v.Member) 910 if name, ok := c.checkConstantString(member); ok { 911 r := &compiledDotExpr{ 912 left: left, 913 name: name, 914 } 915 r.init(c, v.LeftBracket) 916 return r 917 } 918 919 r := &compiledBracketExpr{ 920 left: left, 921 member: member, 922 } 923 r.init(c, v.LeftBracket) 924 return r 925 } 926 927 func (e *compiledDotExpr) emitGetter(putOnStack bool) { 928 e.left.emitGetter(true) 929 e.addSrcMap() 930 e.c.emit(getProp(e.name)) 931 if !putOnStack { 932 e.c.emit(pop) 933 } 934 } 935 936 func (e *compiledDotExpr) emitRef() { 937 e.left.emitGetter(true) 938 if e.c.scope.strict { 939 e.c.emit(getPropRefStrict(e.name)) 940 } else { 941 e.c.emit(getPropRef(e.name)) 942 } 943 } 944 945 func (e *compiledDotExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) { 946 e.left.emitGetter(true) 947 valueExpr.emitGetter(true) 948 if e.c.scope.strict { 949 if putOnStack { 950 e.c.emit(setPropStrict(e.name)) 951 } else { 952 e.c.emit(setPropStrictP(e.name)) 953 } 954 } else { 955 if putOnStack { 956 e.c.emit(setProp(e.name)) 957 } else { 958 e.c.emit(setPropP(e.name)) 959 } 960 } 961 } 962 963 func (e *compiledDotExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) { 964 if !putOnStack { 965 e.left.emitGetter(true) 966 e.c.emit(dup) 967 e.c.emit(getProp(e.name)) 968 body() 969 e.addSrcMap() 970 if e.c.scope.strict { 971 e.c.emit(setPropStrictP(e.name)) 972 } else { 973 e.c.emit(setPropP(e.name)) 974 } 975 } else { 976 if !postfix { 977 e.left.emitGetter(true) 978 e.c.emit(dup) 979 e.c.emit(getProp(e.name)) 980 if prepare != nil { 981 prepare() 982 } 983 body() 984 e.addSrcMap() 985 if e.c.scope.strict { 986 e.c.emit(setPropStrict(e.name)) 987 } else { 988 e.c.emit(setProp(e.name)) 989 } 990 } else { 991 e.c.emit(loadUndef) 992 e.left.emitGetter(true) 993 e.c.emit(dup) 994 e.c.emit(getProp(e.name)) 995 if prepare != nil { 996 prepare() 997 } 998 e.c.emit(rdupN(2)) 999 body() 1000 e.addSrcMap() 1001 if e.c.scope.strict { 1002 e.c.emit(setPropStrictP(e.name)) 1003 } else { 1004 e.c.emit(setPropP(e.name)) 1005 } 1006 } 1007 } 1008 } 1009 1010 func (e *compiledDotExpr) deleteExpr() compiledExpr { 1011 r := &deletePropExpr{ 1012 left: e.left, 1013 name: e.name, 1014 } 1015 r.init(e.c, file.Idx(e.offset)+1) 1016 return r 1017 } 1018 1019 func (e *compiledBracketExpr) emitGetter(putOnStack bool) { 1020 e.left.emitGetter(true) 1021 e.member.emitGetter(true) 1022 e.addSrcMap() 1023 e.c.emit(getElem) 1024 if !putOnStack { 1025 e.c.emit(pop) 1026 } 1027 } 1028 1029 func (e *compiledBracketExpr) emitRef() { 1030 e.left.emitGetter(true) 1031 e.member.emitGetter(true) 1032 if e.c.scope.strict { 1033 e.c.emit(getElemRefStrict) 1034 } else { 1035 e.c.emit(getElemRef) 1036 } 1037 } 1038 1039 func (e *compiledBracketExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) { 1040 e.left.emitGetter(true) 1041 e.member.emitGetter(true) 1042 valueExpr.emitGetter(true) 1043 e.addSrcMap() 1044 if e.c.scope.strict { 1045 if putOnStack { 1046 e.c.emit(setElemStrict) 1047 } else { 1048 e.c.emit(setElemStrictP) 1049 } 1050 } else { 1051 if putOnStack { 1052 e.c.emit(setElem) 1053 } else { 1054 e.c.emit(setElemP) 1055 } 1056 } 1057 } 1058 1059 func (e *compiledBracketExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) { 1060 if !putOnStack { 1061 e.left.emitGetter(true) 1062 e.member.emitGetter(true) 1063 e.c.emit(dupLast(2), getElem) 1064 body() 1065 e.addSrcMap() 1066 if e.c.scope.strict { 1067 e.c.emit(setElemStrict, pop) 1068 } else { 1069 e.c.emit(setElem, pop) 1070 } 1071 } else { 1072 if !postfix { 1073 e.left.emitGetter(true) 1074 e.member.emitGetter(true) 1075 e.c.emit(dupLast(2), getElem) 1076 if prepare != nil { 1077 prepare() 1078 } 1079 body() 1080 e.addSrcMap() 1081 if e.c.scope.strict { 1082 e.c.emit(setElemStrict) 1083 } else { 1084 e.c.emit(setElem) 1085 } 1086 } else { 1087 e.c.emit(loadUndef) 1088 e.left.emitGetter(true) 1089 e.member.emitGetter(true) 1090 e.c.emit(dupLast(2), getElem) 1091 if prepare != nil { 1092 prepare() 1093 } 1094 e.c.emit(rdupN(3)) 1095 body() 1096 e.addSrcMap() 1097 if e.c.scope.strict { 1098 e.c.emit(setElemStrict, pop) 1099 } else { 1100 e.c.emit(setElem, pop) 1101 } 1102 } 1103 } 1104 } 1105 1106 func (e *compiledBracketExpr) deleteExpr() compiledExpr { 1107 r := &deleteElemExpr{ 1108 left: e.left, 1109 member: e.member, 1110 } 1111 r.init(e.c, file.Idx(e.offset)+1) 1112 return r 1113 } 1114 1115 func (e *deleteElemExpr) emitGetter(putOnStack bool) { 1116 e.left.emitGetter(true) 1117 e.member.emitGetter(true) 1118 e.addSrcMap() 1119 if e.c.scope.strict { 1120 e.c.emit(deleteElemStrict) 1121 } else { 1122 e.c.emit(deleteElem) 1123 } 1124 if !putOnStack { 1125 e.c.emit(pop) 1126 } 1127 } 1128 1129 func (e *deletePropExpr) emitGetter(putOnStack bool) { 1130 e.left.emitGetter(true) 1131 e.addSrcMap() 1132 if e.c.scope.strict { 1133 e.c.emit(deletePropStrict(e.name)) 1134 } else { 1135 e.c.emit(deleteProp(e.name)) 1136 } 1137 if !putOnStack { 1138 e.c.emit(pop) 1139 } 1140 } 1141 1142 func (e *deleteVarExpr) emitGetter(putOnStack bool) { 1143 /*if e.c.scope.strict { 1144 e.c.throwSyntaxError(e.offset, "Delete of an unqualified identifier in strict mode") 1145 return 1146 }*/ 1147 e.c.emit(deleteVar(e.name)) 1148 if !putOnStack { 1149 e.c.emit(pop) 1150 } 1151 } 1152 1153 func (e *deleteGlobalExpr) emitGetter(putOnStack bool) { 1154 /*if e.c.scope.strict { 1155 e.c.throwSyntaxError(e.offset, "Delete of an unqualified identifier in strict mode") 1156 return 1157 }*/ 1158 1159 e.c.emit(deleteGlobal(e.name)) 1160 if !putOnStack { 1161 e.c.emit(pop) 1162 } 1163 } 1164 1165 func (e *compiledAssignExpr) emitGetter(putOnStack bool) { 1166 switch e.operator { 1167 case token.ASSIGN: 1168 e.left.emitSetter(e.right, putOnStack) 1169 case token.PLUS: 1170 e.left.emitUnary(nil, func() { 1171 e.right.emitGetter(true) 1172 e.c.emit(add) 1173 }, false, putOnStack) 1174 case token.MINUS: 1175 e.left.emitUnary(nil, func() { 1176 e.right.emitGetter(true) 1177 e.c.emit(sub) 1178 }, false, putOnStack) 1179 case token.MULTIPLY: 1180 e.left.emitUnary(nil, func() { 1181 e.right.emitGetter(true) 1182 e.c.emit(mul) 1183 }, false, putOnStack) 1184 case token.EXPONENT: 1185 e.left.emitUnary(nil, func() { 1186 e.right.emitGetter(true) 1187 e.c.emit(exp) 1188 }, false, putOnStack) 1189 case token.SLASH: 1190 e.left.emitUnary(nil, func() { 1191 e.right.emitGetter(true) 1192 e.c.emit(div) 1193 }, false, putOnStack) 1194 case token.REMAINDER: 1195 e.left.emitUnary(nil, func() { 1196 e.right.emitGetter(true) 1197 e.c.emit(mod) 1198 }, false, putOnStack) 1199 case token.OR: 1200 e.left.emitUnary(nil, func() { 1201 e.right.emitGetter(true) 1202 e.c.emit(or) 1203 }, false, putOnStack) 1204 case token.AND: 1205 e.left.emitUnary(nil, func() { 1206 e.right.emitGetter(true) 1207 e.c.emit(and) 1208 }, false, putOnStack) 1209 case token.EXCLUSIVE_OR: 1210 e.left.emitUnary(nil, func() { 1211 e.right.emitGetter(true) 1212 e.c.emit(xor) 1213 }, false, putOnStack) 1214 case token.SHIFT_LEFT: 1215 e.left.emitUnary(nil, func() { 1216 e.right.emitGetter(true) 1217 e.c.emit(sal) 1218 }, false, putOnStack) 1219 case token.SHIFT_RIGHT: 1220 e.left.emitUnary(nil, func() { 1221 e.right.emitGetter(true) 1222 e.c.emit(sar) 1223 }, false, putOnStack) 1224 case token.UNSIGNED_SHIFT_RIGHT: 1225 e.left.emitUnary(nil, func() { 1226 e.right.emitGetter(true) 1227 e.c.emit(shr) 1228 }, false, putOnStack) 1229 default: 1230 e.c.assert(false, e.offset, "Unknown assign operator: %s", e.operator.String()) 1231 panic("unreachable") 1232 } 1233 } 1234 1235 func (e *compiledLiteral) emitGetter(putOnStack bool) { 1236 if putOnStack { 1237 e.c.emit(loadVal(e.c.p.defineLiteralValue(e.val))) 1238 } 1239 } 1240 1241 func (e *compiledLiteral) constant() bool { 1242 return true 1243 } 1244 1245 func (e *compiledTemplateLiteral) emitGetter(putOnStack bool) { 1246 if e.tag == nil { 1247 if len(e.elements) == 0 { 1248 e.c.emit(loadVal(e.c.p.defineLiteralValue(stringEmpty))) 1249 } else { 1250 tail := e.elements[len(e.elements)-1].Parsed 1251 if len(e.elements) == 1 { 1252 e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(tail)))) 1253 } else { 1254 stringCount := 0 1255 if head := e.elements[0].Parsed; head != "" { 1256 e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(head)))) 1257 stringCount++ 1258 } 1259 e.expressions[0].emitGetter(true) 1260 e.c.emit(_toString{}) 1261 stringCount++ 1262 for i := 1; i < len(e.elements)-1; i++ { 1263 if elt := e.elements[i].Parsed; elt != "" { 1264 e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(elt)))) 1265 stringCount++ 1266 } 1267 e.expressions[i].emitGetter(true) 1268 e.c.emit(_toString{}) 1269 stringCount++ 1270 } 1271 if tail != "" { 1272 e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(tail)))) 1273 stringCount++ 1274 } 1275 e.c.emit(concatStrings(stringCount)) 1276 } 1277 } 1278 } else { 1279 cooked := make([]Value, len(e.elements)) 1280 raw := make([]Value, len(e.elements)) 1281 for i, elt := range e.elements { 1282 raw[i] = &valueProperty{ 1283 enumerable: true, 1284 value: newStringValue(elt.Literal), 1285 } 1286 var cookedVal Value 1287 if elt.Valid { 1288 cookedVal = stringValueFromRaw(elt.Parsed) 1289 } else { 1290 cookedVal = _undefined 1291 } 1292 cooked[i] = &valueProperty{ 1293 enumerable: true, 1294 value: cookedVal, 1295 } 1296 } 1297 e.c.emitCallee(e.tag) 1298 e.c.emit(&getTaggedTmplObject{ 1299 raw: raw, 1300 cooked: cooked, 1301 }) 1302 for _, expr := range e.expressions { 1303 expr.emitGetter(true) 1304 } 1305 e.c.emit(call(len(e.expressions) + 1)) 1306 } 1307 if !putOnStack { 1308 e.c.emit(pop) 1309 } 1310 } 1311 1312 func (c *compiler) compileParameterBindingIdentifier(name unistring.String, offset int) (*binding, bool) { 1313 if c.scope.strict { 1314 c.checkIdentifierName(name, offset) 1315 c.checkIdentifierLName(name, offset) 1316 } 1317 return c.scope.bindNameShadow(name) 1318 } 1319 1320 func (c *compiler) compileParameterPatternIdBinding(name unistring.String, offset int) { 1321 if _, unique := c.compileParameterBindingIdentifier(name, offset); !unique { 1322 c.throwSyntaxError(offset, "Duplicate parameter name not allowed in this context") 1323 } 1324 } 1325 1326 func (c *compiler) compileParameterPatternBinding(item ast.Expression) { 1327 c.createBindings(item, c.compileParameterPatternIdBinding) 1328 } 1329 1330 func (c *compiler) newCode(length, minCap int) (buf []instruction) { 1331 if c.codeScratchpad != nil { 1332 buf = c.codeScratchpad 1333 c.codeScratchpad = nil 1334 } 1335 if cap(buf) < minCap { 1336 buf = make([]instruction, length, minCap) 1337 } else { 1338 buf = buf[:length] 1339 } 1340 return 1341 } 1342 1343 func (e *compiledFunctionLiteral) compile() (prg *Program, name unistring.String, length int, strict bool) { 1344 e.c.assert(e.typ != funcNone, e.offset, "compiledFunctionLiteral.typ is not set") 1345 1346 savedPrg := e.c.p 1347 preambleLen := 8 // enter, boxThis, loadStack(0), initThis, createArgs, set, loadCallee, init 1348 e.c.p = &Program{ 1349 src: e.c.p.src, 1350 code: e.c.newCode(preambleLen, 16), 1351 } 1352 e.c.newScope() 1353 s := e.c.scope 1354 s.funcType = e.typ 1355 1356 if e.name != nil { 1357 name = e.name.Name 1358 } else { 1359 name = e.lhsName 1360 } 1361 1362 if name != "" { 1363 e.c.p.funcName = name 1364 } 1365 savedBlock := e.c.block 1366 defer func() { 1367 e.c.block = savedBlock 1368 }() 1369 1370 e.c.block = &block{ 1371 typ: blockScope, 1372 } 1373 1374 if !s.strict { 1375 s.strict = e.strict != nil 1376 } 1377 1378 hasPatterns := false 1379 hasInits := false 1380 firstDupIdx := -1 1381 1382 if e.parameterList.Rest != nil { 1383 hasPatterns = true // strictly speaking not, but we need to activate all the checks 1384 } 1385 1386 // First, make sure that the first bindings correspond to the formal parameters 1387 for _, item := range e.parameterList.List { 1388 switch tgt := item.Target.(type) { 1389 case *ast.Identifier: 1390 offset := int(tgt.Idx) - 1 1391 b, unique := e.c.compileParameterBindingIdentifier(tgt.Name, offset) 1392 if !unique { 1393 firstDupIdx = offset 1394 } 1395 b.isArg = true 1396 case ast.Pattern: 1397 b := s.addBinding(int(item.Idx0()) - 1) 1398 b.isArg = true 1399 hasPatterns = true 1400 default: 1401 e.c.throwSyntaxError(int(item.Idx0())-1, "Unsupported BindingElement type: %T", item) 1402 return 1403 } 1404 if item.Initializer != nil { 1405 hasInits = true 1406 } 1407 1408 if firstDupIdx >= 0 && (hasPatterns || hasInits || s.strict || e.typ == funcArrow || e.typ == funcMethod) { 1409 e.c.throwSyntaxError(firstDupIdx, "Duplicate parameter name not allowed in this context") 1410 return 1411 } 1412 1413 if (hasPatterns || hasInits) && e.strict != nil { 1414 e.c.throwSyntaxError(int(e.strict.Idx)-1, "Illegal 'use strict' directive in function with non-simple parameter list") 1415 return 1416 } 1417 1418 if !hasInits { 1419 length++ 1420 } 1421 } 1422 1423 var thisBinding *binding 1424 if e.typ != funcArrow { 1425 thisBinding = s.createThisBinding() 1426 } 1427 1428 // create pattern bindings 1429 if hasPatterns { 1430 for _, item := range e.parameterList.List { 1431 switch tgt := item.Target.(type) { 1432 case *ast.Identifier: 1433 // we already created those in the previous loop, skipping 1434 default: 1435 e.c.compileParameterPatternBinding(tgt) 1436 } 1437 } 1438 if rest := e.parameterList.Rest; rest != nil { 1439 e.c.compileParameterPatternBinding(rest) 1440 } 1441 } 1442 1443 paramsCount := len(e.parameterList.List) 1444 1445 s.numArgs = paramsCount 1446 body := e.body 1447 funcs := e.c.extractFunctions(body) 1448 var calleeBinding *binding 1449 1450 emitArgsRestMark := -1 1451 firstForwardRef := -1 1452 enterFunc2Mark := -1 1453 1454 if hasPatterns || hasInits { 1455 if e.isExpr && e.name != nil { 1456 if b, created := s.bindNameLexical(e.name.Name, false, 0); created { 1457 b.isConst = true 1458 calleeBinding = b 1459 } 1460 } 1461 for i, item := range e.parameterList.List { 1462 if pattern, ok := item.Target.(ast.Pattern); ok { 1463 i := i 1464 e.c.compilePatternInitExpr(func() { 1465 if firstForwardRef == -1 { 1466 s.bindings[i].emitGet() 1467 } else { 1468 e.c.emit(loadStackLex(-i - 1)) 1469 } 1470 }, item.Initializer, item.Target.Idx0()).emitGetter(true) 1471 e.c.emitPattern(pattern, func(target, init compiledExpr) { 1472 e.c.emitPatternLexicalAssign(target, init) 1473 }, false) 1474 } else if item.Initializer != nil { 1475 markGet := len(e.c.p.code) 1476 e.c.emit(nil) 1477 mark := len(e.c.p.code) 1478 e.c.emit(nil) 1479 e.c.emitExpr(e.c.compileExpression(item.Initializer), true) 1480 if firstForwardRef == -1 && (s.isDynamic() || s.bindings[i].useCount() > 0) { 1481 firstForwardRef = i 1482 } 1483 if firstForwardRef == -1 { 1484 s.bindings[i].emitGetAt(markGet) 1485 } else { 1486 e.c.p.code[markGet] = loadStackLex(-i - 1) 1487 } 1488 s.bindings[i].emitInitP() 1489 e.c.p.code[mark] = jdefP(len(e.c.p.code) - mark) 1490 } else { 1491 if firstForwardRef == -1 && s.bindings[i].useCount() > 0 { 1492 firstForwardRef = i 1493 } 1494 if firstForwardRef != -1 { 1495 e.c.emit(loadStackLex(-i - 1)) 1496 s.bindings[i].emitInitP() 1497 } 1498 } 1499 } 1500 if rest := e.parameterList.Rest; rest != nil { 1501 e.c.emitAssign(rest, e.c.compileEmitterExpr( 1502 func() { 1503 emitArgsRestMark = len(e.c.p.code) 1504 e.c.emit(createArgsRestStack(paramsCount)) 1505 }, rest.Idx0()), 1506 func(target, init compiledExpr) { 1507 e.c.emitPatternLexicalAssign(target, init) 1508 }) 1509 } 1510 if firstForwardRef != -1 { 1511 for _, b := range s.bindings { 1512 b.inStash = true 1513 } 1514 s.argsInStash = true 1515 s.needStash = true 1516 } 1517 1518 e.c.newBlockScope() 1519 varScope := e.c.scope 1520 varScope.variable = true 1521 enterFunc2Mark = len(e.c.p.code) 1522 e.c.emit(nil) 1523 e.c.compileDeclList(e.declarationList, false) 1524 e.c.createFunctionBindings(funcs) 1525 e.c.compileLexicalDeclarationsFuncBody(body, calleeBinding) 1526 for _, b := range varScope.bindings { 1527 if b.isVar { 1528 if parentBinding := s.boundNames[b.name]; parentBinding != nil && parentBinding != calleeBinding { 1529 parentBinding.emitGet() 1530 b.emitSetP() 1531 } 1532 } 1533 } 1534 } else { 1535 // To avoid triggering variable conflict when binding from non-strict direct eval(). 1536 // Parameters are supposed to be in a parent scope, hence no conflict. 1537 for _, b := range s.bindings[:paramsCount] { 1538 b.isVar = true 1539 } 1540 e.c.compileDeclList(e.declarationList, true) 1541 e.c.createFunctionBindings(funcs) 1542 e.c.compileLexicalDeclarations(body, true) 1543 if e.isExpr && e.name != nil { 1544 if b, created := s.bindNameLexical(e.name.Name, false, 0); created { 1545 b.isConst = true 1546 calleeBinding = b 1547 } 1548 } 1549 if calleeBinding != nil { 1550 e.c.emit(loadCallee) 1551 calleeBinding.emitInitP() 1552 } 1553 } 1554 1555 e.c.compileFunctions(funcs) 1556 e.c.compileStatements(body, false) 1557 1558 var last ast.Statement 1559 if l := len(body); l > 0 { 1560 last = body[l-1] 1561 } 1562 if _, ok := last.(*ast.ReturnStatement); !ok { 1563 if e.typ == funcDerivedCtor { 1564 e.c.emit(loadUndef) 1565 thisBinding.markAccessPoint() 1566 e.c.emit(ret) 1567 } else { 1568 e.c.emit(loadUndef, ret) 1569 } 1570 } 1571 1572 delta := 0 1573 code := e.c.p.code 1574 1575 if s.isDynamic() && !s.argsInStash { 1576 s.moveArgsToStash() 1577 } 1578 1579 if s.argsNeeded || s.isDynamic() && e.typ != funcArrow && e.typ != funcClsInit { 1580 if e.typ == funcClsInit { 1581 e.c.throwSyntaxError(e.offset, "'arguments' is not allowed in class field initializer or static initialization block") 1582 } 1583 b, created := s.bindNameLexical("arguments", false, 0) 1584 if created || b.isVar { 1585 if !s.argsInStash { 1586 s.moveArgsToStash() 1587 } 1588 if s.strict { 1589 b.isConst = true 1590 } else { 1591 b.isVar = e.c.scope.isFunction() 1592 } 1593 pos := preambleLen - 2 1594 delta += 2 1595 if s.strict || hasPatterns || hasInits { 1596 code[pos] = createArgsUnmapped(paramsCount) 1597 } else { 1598 code[pos] = createArgsMapped(paramsCount) 1599 } 1600 pos++ 1601 b.emitInitPAtScope(s, pos) 1602 } 1603 } 1604 1605 if calleeBinding != nil { 1606 if !s.isDynamic() && calleeBinding.useCount() == 0 { 1607 s.deleteBinding(calleeBinding) 1608 calleeBinding = nil 1609 } else { 1610 delta++ 1611 calleeBinding.emitInitPAtScope(s, preambleLen-delta) 1612 delta++ 1613 code[preambleLen-delta] = loadCallee 1614 } 1615 } 1616 1617 if thisBinding != nil { 1618 if !s.isDynamic() && thisBinding.useCount() == 0 { 1619 s.deleteBinding(thisBinding) 1620 thisBinding = nil 1621 } else { 1622 if thisBinding.inStash || s.isDynamic() { 1623 delta++ 1624 thisBinding.emitInitAtScope(s, preambleLen-delta) 1625 } 1626 } 1627 } 1628 1629 stashSize, stackSize := s.finaliseVarAlloc(0) 1630 1631 if thisBinding != nil && thisBinding.inStash && (!s.argsInStash || stackSize > 0) { 1632 delta++ 1633 code[preambleLen-delta] = loadStack(0) 1634 } // otherwise, 'this' will be at stack[sp-1], no need to load 1635 1636 if !s.strict && thisBinding != nil { 1637 delta++ 1638 code[preambleLen-delta] = boxThis 1639 } 1640 delta++ 1641 delta = preambleLen - delta 1642 var enter instruction 1643 if stashSize > 0 || s.argsInStash { 1644 if firstForwardRef == -1 { 1645 enter1 := enterFunc{ 1646 numArgs: uint32(paramsCount), 1647 argsToStash: s.argsInStash, 1648 stashSize: uint32(stashSize), 1649 stackSize: uint32(stackSize), 1650 extensible: s.dynamic, 1651 funcType: e.typ, 1652 } 1653 if s.isDynamic() { 1654 enter1.names = s.makeNamesMap() 1655 } 1656 enter = &enter1 1657 if enterFunc2Mark != -1 { 1658 ef2 := &enterFuncBody{ 1659 extensible: e.c.scope.dynamic, 1660 funcType: e.typ, 1661 } 1662 e.c.updateEnterBlock(&ef2.enterBlock) 1663 e.c.p.code[enterFunc2Mark] = ef2 1664 } 1665 } else { 1666 enter1 := enterFunc1{ 1667 stashSize: uint32(stashSize), 1668 numArgs: uint32(paramsCount), 1669 argsToCopy: uint32(firstForwardRef), 1670 extensible: s.dynamic, 1671 funcType: e.typ, 1672 } 1673 if s.isDynamic() { 1674 enter1.names = s.makeNamesMap() 1675 } 1676 enter = &enter1 1677 if enterFunc2Mark != -1 { 1678 ef2 := &enterFuncBody{ 1679 adjustStack: true, 1680 extensible: e.c.scope.dynamic, 1681 funcType: e.typ, 1682 } 1683 e.c.updateEnterBlock(&ef2.enterBlock) 1684 e.c.p.code[enterFunc2Mark] = ef2 1685 } 1686 } 1687 if emitArgsRestMark != -1 && s.argsInStash { 1688 e.c.p.code[emitArgsRestMark] = createArgsRestStash 1689 } 1690 } else { 1691 enter = &enterFuncStashless{ 1692 stackSize: uint32(stackSize), 1693 args: uint32(paramsCount), 1694 } 1695 if enterFunc2Mark != -1 { 1696 ef2 := &enterFuncBody{ 1697 extensible: e.c.scope.dynamic, 1698 funcType: e.typ, 1699 } 1700 e.c.updateEnterBlock(&ef2.enterBlock) 1701 e.c.p.code[enterFunc2Mark] = ef2 1702 } 1703 } 1704 code[delta] = enter 1705 s.trimCode(delta) 1706 1707 strict = s.strict 1708 prg = e.c.p 1709 // e.c.p.dumpCode() 1710 if enterFunc2Mark != -1 { 1711 e.c.popScope() 1712 } 1713 e.c.popScope() 1714 e.c.p = savedPrg 1715 1716 return 1717 } 1718 1719 func (e *compiledFunctionLiteral) emitGetter(putOnStack bool) { 1720 p, name, length, strict := e.compile() 1721 switch e.typ { 1722 case funcArrow: 1723 e.c.emit(&newArrowFunc{newFunc: newFunc{prg: p, length: length, name: name, source: e.source, strict: strict}}) 1724 case funcMethod, funcClsInit: 1725 e.c.emit(&newMethod{newFunc: newFunc{prg: p, length: length, name: name, source: e.source, strict: strict}, homeObjOffset: e.homeObjOffset}) 1726 case funcRegular: 1727 e.c.emit(&newFunc{prg: p, length: length, name: name, source: e.source, strict: strict}) 1728 default: 1729 e.c.throwSyntaxError(e.offset, "Unsupported func type: %v", e.typ) 1730 } 1731 if !putOnStack { 1732 e.c.emit(pop) 1733 } 1734 } 1735 1736 func (c *compiler) compileFunctionLiteral(v *ast.FunctionLiteral, isExpr bool) *compiledFunctionLiteral { 1737 strictBody := c.isStrictStatement(v.Body) 1738 if v.Name != nil && (c.scope.strict || strictBody != nil) { 1739 c.checkIdentifierLName(v.Name.Name, int(v.Name.Idx)-1) 1740 } 1741 r := &compiledFunctionLiteral{ 1742 name: v.Name, 1743 parameterList: v.ParameterList, 1744 body: v.Body.List, 1745 source: v.Source, 1746 declarationList: v.DeclarationList, 1747 isExpr: isExpr, 1748 typ: funcRegular, 1749 strict: strictBody, 1750 } 1751 r.init(c, v.Idx0()) 1752 return r 1753 } 1754 1755 type compiledClassLiteral struct { 1756 baseCompiledExpr 1757 name *ast.Identifier 1758 superClass compiledExpr 1759 body []ast.ClassElement 1760 lhsName unistring.String 1761 source string 1762 isExpr bool 1763 } 1764 1765 func (c *compiler) processKey(expr ast.Expression) (val unistring.String, computed bool) { 1766 keyExpr := c.compileExpression(expr) 1767 if keyExpr.constant() { 1768 v, ex := c.evalConst(keyExpr) 1769 if ex == nil { 1770 return v.string(), false 1771 } 1772 } 1773 keyExpr.emitGetter(true) 1774 computed = true 1775 return 1776 } 1777 1778 func (e *compiledClassLiteral) processClassKey(expr ast.Expression) (privateName *privateName, key unistring.String, computed bool) { 1779 if p, ok := expr.(*ast.PrivateIdentifier); ok { 1780 privateName = e.c.classScope.getDeclaredPrivateId(p.Name) 1781 key = privateIdString(p.Name) 1782 return 1783 } 1784 key, computed = e.c.processKey(expr) 1785 return 1786 } 1787 1788 type clsElement struct { 1789 key unistring.String 1790 privateName *privateName 1791 initializer compiledExpr 1792 body *compiledFunctionLiteral 1793 computed bool 1794 } 1795 1796 func (e *compiledClassLiteral) emitGetter(putOnStack bool) { 1797 e.c.newBlockScope() 1798 s := e.c.scope 1799 s.strict = true 1800 1801 enter := &enterBlock{} 1802 mark0 := len(e.c.p.code) 1803 e.c.emit(enter) 1804 e.c.block = &block{ 1805 typ: blockScope, 1806 outer: e.c.block, 1807 } 1808 var clsBinding *binding 1809 var clsName unistring.String 1810 if name := e.name; name != nil { 1811 clsName = name.Name 1812 clsBinding = e.c.createLexicalIdBinding(clsName, true, int(name.Idx)-1) 1813 } else { 1814 clsName = e.lhsName 1815 } 1816 1817 var ctorMethod *ast.MethodDefinition 1818 ctorMethodIdx := -1 1819 staticsCount := 0 1820 instanceFieldsCount := 0 1821 hasStaticPrivateMethods := false 1822 cs := &classScope{ 1823 c: e.c, 1824 outer: e.c.classScope, 1825 } 1826 1827 for idx, elt := range e.body { 1828 switch elt := elt.(type) { 1829 case *ast.ClassStaticBlock: 1830 if len(elt.Block.List) > 0 { 1831 staticsCount++ 1832 } 1833 case *ast.FieldDefinition: 1834 if id, ok := elt.Key.(*ast.PrivateIdentifier); ok { 1835 cs.declarePrivateId(id.Name, ast.PropertyKindValue, elt.Static, int(elt.Idx)-1) 1836 } 1837 if elt.Static { 1838 staticsCount++ 1839 } else { 1840 instanceFieldsCount++ 1841 } 1842 case *ast.MethodDefinition: 1843 if !elt.Static { 1844 if id, ok := elt.Key.(*ast.StringLiteral); ok { 1845 if !elt.Computed && id.Value == "constructor" { 1846 if ctorMethod != nil { 1847 e.c.throwSyntaxError(int(id.Idx)-1, "A class may only have one constructor") 1848 } 1849 ctorMethod = elt 1850 ctorMethodIdx = idx 1851 continue 1852 } 1853 } 1854 } 1855 if id, ok := elt.Key.(*ast.PrivateIdentifier); ok { 1856 cs.declarePrivateId(id.Name, elt.Kind, elt.Static, int(elt.Idx)-1) 1857 if elt.Static { 1858 hasStaticPrivateMethods = true 1859 } 1860 } 1861 default: 1862 e.c.assert(false, int(elt.Idx0())-1, "Unsupported static element: %T", elt) 1863 } 1864 } 1865 1866 var staticInit *newStaticFieldInit 1867 if staticsCount > 0 || hasStaticPrivateMethods { 1868 staticInit = &newStaticFieldInit{} 1869 e.c.emit(staticInit) 1870 } 1871 1872 var derived bool 1873 var newClassIns *newClass 1874 if superClass := e.superClass; superClass != nil { 1875 derived = true 1876 superClass.emitGetter(true) 1877 ndc := &newDerivedClass{ 1878 newClass: newClass{ 1879 name: clsName, 1880 source: e.source, 1881 }, 1882 } 1883 e.addSrcMap() 1884 e.c.emit(ndc) 1885 newClassIns = &ndc.newClass 1886 } else { 1887 newClassIns = &newClass{ 1888 name: clsName, 1889 source: e.source, 1890 } 1891 e.addSrcMap() 1892 e.c.emit(newClassIns) 1893 } 1894 1895 e.c.classScope = cs 1896 1897 if ctorMethod != nil { 1898 newClassIns.ctor, newClassIns.length = e.c.compileCtor(ctorMethod.Body, derived) 1899 } 1900 1901 curIsPrototype := false 1902 1903 instanceFields := make([]clsElement, 0, instanceFieldsCount) 1904 staticElements := make([]clsElement, 0, staticsCount) 1905 1906 // stack at this point: 1907 // 1908 // staticFieldInit (if staticsCount > 0 || hasStaticPrivateMethods) 1909 // prototype 1910 // class function 1911 // <- sp 1912 1913 for idx, elt := range e.body { 1914 if idx == ctorMethodIdx { 1915 continue 1916 } 1917 switch elt := elt.(type) { 1918 case *ast.ClassStaticBlock: 1919 if len(elt.Block.List) > 0 { 1920 f := e.c.compileFunctionLiteral(&ast.FunctionLiteral{ 1921 Function: elt.Idx0(), 1922 ParameterList: &ast.ParameterList{}, 1923 Body: elt.Block, 1924 Source: elt.Source, 1925 DeclarationList: elt.DeclarationList, 1926 }, true) 1927 f.typ = funcClsInit 1928 //f.lhsName = "<static_initializer>" 1929 f.homeObjOffset = 1 1930 staticElements = append(staticElements, clsElement{ 1931 body: f, 1932 }) 1933 } 1934 case *ast.FieldDefinition: 1935 privateName, key, computed := e.processClassKey(elt.Key) 1936 var el clsElement 1937 if elt.Initializer != nil { 1938 el.initializer = e.c.compileExpression(elt.Initializer) 1939 } 1940 el.computed = computed 1941 if computed { 1942 if elt.Static { 1943 if curIsPrototype { 1944 e.c.emit(defineComputedKey(5)) 1945 } else { 1946 e.c.emit(defineComputedKey(4)) 1947 } 1948 } else { 1949 if curIsPrototype { 1950 e.c.emit(defineComputedKey(3)) 1951 } else { 1952 e.c.emit(defineComputedKey(2)) 1953 } 1954 } 1955 } else { 1956 el.privateName = privateName 1957 el.key = key 1958 } 1959 if elt.Static { 1960 staticElements = append(staticElements, el) 1961 } else { 1962 instanceFields = append(instanceFields, el) 1963 } 1964 case *ast.MethodDefinition: 1965 if elt.Static { 1966 if curIsPrototype { 1967 e.c.emit(pop) 1968 curIsPrototype = false 1969 } 1970 } else { 1971 if !curIsPrototype { 1972 e.c.emit(dupN(1)) 1973 curIsPrototype = true 1974 } 1975 } 1976 privateName, key, computed := e.processClassKey(elt.Key) 1977 lit := e.c.compileFunctionLiteral(elt.Body, true) 1978 lit.typ = funcMethod 1979 if computed { 1980 e.c.emit(_toPropertyKey{}) 1981 lit.homeObjOffset = 2 1982 } else { 1983 lit.homeObjOffset = 1 1984 lit.lhsName = key 1985 } 1986 lit.emitGetter(true) 1987 if privateName != nil { 1988 var offset int 1989 if elt.Static { 1990 if curIsPrototype { 1991 /* 1992 staticInit 1993 proto 1994 cls 1995 proto 1996 method 1997 <- sp 1998 */ 1999 offset = 5 2000 } else { 2001 /* 2002 staticInit 2003 proto 2004 cls 2005 method 2006 <- sp 2007 */ 2008 offset = 4 2009 } 2010 } else { 2011 if curIsPrototype { 2012 offset = 3 2013 } else { 2014 offset = 2 2015 } 2016 } 2017 switch elt.Kind { 2018 case ast.PropertyKindGet: 2019 e.c.emit(&definePrivateGetter{ 2020 definePrivateMethod: definePrivateMethod{ 2021 idx: privateName.idx, 2022 targetOffset: offset, 2023 }, 2024 }) 2025 case ast.PropertyKindSet: 2026 e.c.emit(&definePrivateSetter{ 2027 definePrivateMethod: definePrivateMethod{ 2028 idx: privateName.idx, 2029 targetOffset: offset, 2030 }, 2031 }) 2032 default: 2033 e.c.emit(&definePrivateMethod{ 2034 idx: privateName.idx, 2035 targetOffset: offset, 2036 }) 2037 } 2038 } else if computed { 2039 switch elt.Kind { 2040 case ast.PropertyKindGet: 2041 e.c.emit(&defineGetter{}) 2042 case ast.PropertyKindSet: 2043 e.c.emit(&defineSetter{}) 2044 default: 2045 e.c.emit(&defineMethod{}) 2046 } 2047 } else { 2048 switch elt.Kind { 2049 case ast.PropertyKindGet: 2050 e.c.emit(&defineGetterKeyed{key: key}) 2051 case ast.PropertyKindSet: 2052 e.c.emit(&defineSetterKeyed{key: key}) 2053 default: 2054 e.c.emit(&defineMethodKeyed{key: key}) 2055 } 2056 } 2057 } 2058 } 2059 if curIsPrototype { 2060 e.c.emit(pop) 2061 } 2062 2063 if len(instanceFields) > 0 { 2064 newClassIns.initFields = e.compileFieldsAndStaticBlocks(instanceFields, "<instance_members_initializer>") 2065 } 2066 if staticInit != nil { 2067 if len(staticElements) > 0 { 2068 staticInit.initFields = e.compileFieldsAndStaticBlocks(staticElements, "<static_initializer>") 2069 } 2070 } 2071 2072 env := e.c.classScope.instanceEnv 2073 if s.dynLookup { 2074 newClassIns.privateMethods, newClassIns.privateFields = env.methods, env.fields 2075 } 2076 newClassIns.numPrivateMethods = uint32(len(env.methods)) 2077 newClassIns.numPrivateFields = uint32(len(env.fields)) 2078 newClassIns.hasPrivateEnv = len(e.c.classScope.privateNames) > 0 2079 2080 if (clsBinding != nil && clsBinding.useCount() > 0) || s.dynLookup { 2081 if clsBinding != nil { 2082 // Because this block may be in the middle of an expression, it's initial stack position 2083 // cannot be known, and therefore it may not have any stack variables. 2084 // Note, because clsBinding would be accessed through a function, it should already be in stash, 2085 // this is just to make sure. 2086 clsBinding.moveToStash() 2087 clsBinding.emitInit() 2088 } 2089 } else { 2090 if clsBinding != nil { 2091 s.deleteBinding(clsBinding) 2092 clsBinding = nil 2093 } 2094 e.c.p.code[mark0] = jump(1) 2095 } 2096 2097 if staticsCount > 0 || hasStaticPrivateMethods { 2098 ise := &initStaticElements{} 2099 e.c.emit(ise) 2100 env := e.c.classScope.staticEnv 2101 staticInit.numPrivateFields = uint32(len(env.fields)) 2102 staticInit.numPrivateMethods = uint32(len(env.methods)) 2103 if s.dynLookup { 2104 // These cannot be set on staticInit, because it is executed before ClassHeritage, and therefore 2105 // the VM's PrivateEnvironment is still not set. 2106 ise.privateFields = env.fields 2107 ise.privateMethods = env.methods 2108 } 2109 } else { 2110 e.c.emit(endVariadic) // re-using as semantics match 2111 } 2112 2113 if !putOnStack { 2114 e.c.emit(pop) 2115 } 2116 2117 if clsBinding != nil || s.dynLookup { 2118 e.c.leaveScopeBlock(enter) 2119 e.c.assert(enter.stackSize == 0, e.offset, "enter.StackSize != 0 in compiledClassLiteral") 2120 } else { 2121 e.c.block = e.c.block.outer 2122 } 2123 if len(e.c.classScope.privateNames) > 0 { 2124 e.c.emit(popPrivateEnv{}) 2125 } 2126 e.c.classScope = e.c.classScope.outer 2127 e.c.popScope() 2128 } 2129 2130 func (e *compiledClassLiteral) compileFieldsAndStaticBlocks(elements []clsElement, funcName unistring.String) *Program { 2131 savedPrg := e.c.p 2132 savedBlock := e.c.block 2133 defer func() { 2134 e.c.p = savedPrg 2135 e.c.block = savedBlock 2136 }() 2137 2138 e.c.block = &block{ 2139 typ: blockScope, 2140 } 2141 2142 e.c.p = &Program{ 2143 src: savedPrg.src, 2144 funcName: funcName, 2145 code: e.c.newCode(2, 16), 2146 } 2147 2148 e.c.newScope() 2149 s := e.c.scope 2150 s.funcType = funcClsInit 2151 thisBinding := s.createThisBinding() 2152 2153 valIdx := 0 2154 for _, elt := range elements { 2155 if elt.body != nil { 2156 e.c.emit(dup) // this 2157 elt.body.emitGetter(true) 2158 elt.body.addSrcMap() 2159 e.c.emit(call(0), pop) 2160 } else { 2161 if elt.computed { 2162 e.c.emit(loadComputedKey(valIdx)) 2163 valIdx++ 2164 } 2165 if init := elt.initializer; init != nil { 2166 if !elt.computed { 2167 e.c.emitNamedOrConst(init, elt.key) 2168 } else { 2169 e.c.emitExpr(init, true) 2170 } 2171 } else { 2172 e.c.emit(loadUndef) 2173 } 2174 if elt.privateName != nil { 2175 e.c.emit(&definePrivateProp{ 2176 idx: elt.privateName.idx, 2177 }) 2178 } else if elt.computed { 2179 e.c.emit(defineProp{}) 2180 } else { 2181 e.c.emit(definePropKeyed(elt.key)) 2182 } 2183 } 2184 } 2185 e.c.emit(halt) 2186 if s.isDynamic() || thisBinding.useCount() > 0 { 2187 if s.isDynamic() || thisBinding.inStash { 2188 thisBinding.emitInitAt(1) 2189 } 2190 } else { 2191 s.deleteBinding(thisBinding) 2192 } 2193 stashSize, stackSize := s.finaliseVarAlloc(0) 2194 e.c.assert(stackSize == 0, e.offset, "stackSize != 0 in initFields") 2195 if stashSize > 0 { 2196 e.c.assert(stashSize == 1, e.offset, "stashSize != 1 in initFields") 2197 enter := &enterFunc{ 2198 stashSize: 1, 2199 funcType: funcClsInit, 2200 } 2201 if s.dynLookup { 2202 enter.names = s.makeNamesMap() 2203 } 2204 e.c.p.code[0] = enter 2205 s.trimCode(0) 2206 } else { 2207 s.trimCode(2) 2208 } 2209 res := e.c.p 2210 e.c.popScope() 2211 return res 2212 } 2213 2214 func (c *compiler) compileClassLiteral(v *ast.ClassLiteral, isExpr bool) *compiledClassLiteral { 2215 if v.Name != nil { 2216 c.checkIdentifierLName(v.Name.Name, int(v.Name.Idx)-1) 2217 } 2218 r := &compiledClassLiteral{ 2219 name: v.Name, 2220 superClass: c.compileExpression(v.SuperClass), 2221 body: v.Body, 2222 source: v.Source, 2223 isExpr: isExpr, 2224 } 2225 r.init(c, v.Idx0()) 2226 return r 2227 } 2228 2229 func (c *compiler) compileCtor(ctor *ast.FunctionLiteral, derived bool) (p *Program, length int) { 2230 f := c.compileFunctionLiteral(ctor, true) 2231 if derived { 2232 f.typ = funcDerivedCtor 2233 } else { 2234 f.typ = funcCtor 2235 } 2236 p, _, length, _ = f.compile() 2237 return 2238 } 2239 2240 func (c *compiler) compileArrowFunctionLiteral(v *ast.ArrowFunctionLiteral) *compiledFunctionLiteral { 2241 var strictBody *ast.StringLiteral 2242 var body []ast.Statement 2243 switch b := v.Body.(type) { 2244 case *ast.BlockStatement: 2245 strictBody = c.isStrictStatement(b) 2246 body = b.List 2247 case *ast.ExpressionBody: 2248 body = []ast.Statement{ 2249 &ast.ReturnStatement{ 2250 Argument: b.Expression, 2251 }, 2252 } 2253 default: 2254 c.throwSyntaxError(int(b.Idx0())-1, "Unsupported ConciseBody type: %T", b) 2255 } 2256 r := &compiledFunctionLiteral{ 2257 parameterList: v.ParameterList, 2258 body: body, 2259 source: v.Source, 2260 declarationList: v.DeclarationList, 2261 isExpr: true, 2262 typ: funcArrow, 2263 strict: strictBody, 2264 } 2265 r.init(c, v.Idx0()) 2266 return r 2267 } 2268 2269 func (c *compiler) emitLoadThis() { 2270 b, eval := c.scope.lookupThis() 2271 if b != nil { 2272 b.emitGet() 2273 } else { 2274 if eval { 2275 c.emit(getThisDynamic{}) 2276 } else { 2277 c.emit(loadGlobalObject) 2278 } 2279 } 2280 } 2281 2282 func (e *compiledThisExpr) emitGetter(putOnStack bool) { 2283 e.addSrcMap() 2284 e.c.emitLoadThis() 2285 if !putOnStack { 2286 e.c.emit(pop) 2287 } 2288 } 2289 2290 func (e *compiledSuperExpr) emitGetter(putOnStack bool) { 2291 if putOnStack { 2292 e.c.emit(loadSuper) 2293 } 2294 } 2295 2296 func (e *compiledNewExpr) emitGetter(putOnStack bool) { 2297 if e.isVariadic { 2298 e.c.emit(startVariadic) 2299 } 2300 e.callee.emitGetter(true) 2301 for _, expr := range e.args { 2302 expr.emitGetter(true) 2303 } 2304 e.addSrcMap() 2305 if e.isVariadic { 2306 e.c.emit(newVariadic, endVariadic) 2307 } else { 2308 e.c.emit(_new(len(e.args))) 2309 } 2310 if !putOnStack { 2311 e.c.emit(pop) 2312 } 2313 } 2314 2315 func (c *compiler) compileCallArgs(list []ast.Expression) (args []compiledExpr, isVariadic bool) { 2316 args = make([]compiledExpr, len(list)) 2317 for i, argExpr := range list { 2318 if spread, ok := argExpr.(*ast.SpreadElement); ok { 2319 args[i] = c.compileSpreadCallArgument(spread) 2320 isVariadic = true 2321 } else { 2322 args[i] = c.compileExpression(argExpr) 2323 } 2324 } 2325 return 2326 } 2327 2328 func (c *compiler) compileNewExpression(v *ast.NewExpression) compiledExpr { 2329 args, isVariadic := c.compileCallArgs(v.ArgumentList) 2330 r := &compiledNewExpr{ 2331 compiledCallExpr: compiledCallExpr{ 2332 callee: c.compileExpression(v.Callee), 2333 args: args, 2334 isVariadic: isVariadic, 2335 }, 2336 } 2337 r.init(c, v.Idx0()) 2338 return r 2339 } 2340 2341 func (e *compiledNewTarget) emitGetter(putOnStack bool) { 2342 if s := e.c.scope.nearestThis(); s == nil || s.funcType == funcNone { 2343 e.c.throwSyntaxError(e.offset, "new.target expression is not allowed here") 2344 } 2345 if putOnStack { 2346 e.addSrcMap() 2347 e.c.emit(loadNewTarget) 2348 } 2349 } 2350 2351 func (c *compiler) compileMetaProperty(v *ast.MetaProperty) compiledExpr { 2352 if v.Meta.Name == "new" || v.Property.Name != "target" { 2353 r := &compiledNewTarget{} 2354 r.init(c, v.Idx0()) 2355 return r 2356 } 2357 c.throwSyntaxError(int(v.Idx)-1, "Unsupported meta property: %s.%s", v.Meta.Name, v.Property.Name) 2358 return nil 2359 } 2360 2361 func (e *compiledSequenceExpr) emitGetter(putOnStack bool) { 2362 if len(e.sequence) > 0 { 2363 for i := 0; i < len(e.sequence)-1; i++ { 2364 e.sequence[i].emitGetter(false) 2365 } 2366 e.sequence[len(e.sequence)-1].emitGetter(putOnStack) 2367 } 2368 } 2369 2370 func (c *compiler) compileSequenceExpression(v *ast.SequenceExpression) compiledExpr { 2371 s := make([]compiledExpr, len(v.Sequence)) 2372 for i, expr := range v.Sequence { 2373 s[i] = c.compileExpression(expr) 2374 } 2375 r := &compiledSequenceExpr{ 2376 sequence: s, 2377 } 2378 var idx file.Idx 2379 if len(v.Sequence) > 0 { 2380 idx = v.Idx0() 2381 } 2382 r.init(c, idx) 2383 return r 2384 } 2385 2386 func (c *compiler) emitThrow(v Value) { 2387 if o, ok := v.(*Object); ok { 2388 t := nilSafe(o.self.getStr("name", nil)).toString().String() 2389 switch t { 2390 case "TypeError": 2391 c.emit(loadDynamic(t)) 2392 msg := o.self.getStr("message", nil) 2393 if msg != nil { 2394 c.emit(loadVal(c.p.defineLiteralValue(msg))) 2395 c.emit(_new(1)) 2396 } else { 2397 c.emit(_new(0)) 2398 } 2399 c.emit(throw) 2400 return 2401 } 2402 } 2403 c.assert(false, 0, "unknown exception type thrown while evaluating constant expression: %s", v.String()) 2404 panic("unreachable") 2405 } 2406 2407 func (c *compiler) emitConst(expr compiledExpr, putOnStack bool) { 2408 v, ex := c.evalConst(expr) 2409 if ex == nil { 2410 if putOnStack { 2411 c.emit(loadVal(c.p.defineLiteralValue(v))) 2412 } 2413 } else { 2414 c.emitThrow(ex.val) 2415 } 2416 } 2417 2418 func (c *compiler) evalConst(expr compiledExpr) (Value, *Exception) { 2419 if expr, ok := expr.(*compiledLiteral); ok { 2420 return expr.val, nil 2421 } 2422 if c.evalVM == nil { 2423 c.evalVM = New().vm 2424 } 2425 var savedPrg *Program 2426 createdPrg := false 2427 if c.evalVM.prg == nil { 2428 c.evalVM.prg = &Program{} 2429 savedPrg = c.p 2430 c.p = c.evalVM.prg 2431 createdPrg = true 2432 } 2433 savedPc := len(c.p.code) 2434 expr.emitGetter(true) 2435 c.emit(halt) 2436 c.evalVM.pc = savedPc 2437 ex := c.evalVM.runTry() 2438 if createdPrg { 2439 c.evalVM.prg = nil 2440 c.evalVM.pc = 0 2441 c.p = savedPrg 2442 } else { 2443 c.evalVM.prg.code = c.evalVM.prg.code[:savedPc] 2444 c.p.code = c.evalVM.prg.code 2445 } 2446 if ex == nil { 2447 return c.evalVM.pop(), nil 2448 } 2449 return nil, ex 2450 } 2451 2452 func (e *compiledUnaryExpr) constant() bool { 2453 return e.operand.constant() 2454 } 2455 2456 func (e *compiledUnaryExpr) emitGetter(putOnStack bool) { 2457 var prepare, body func() 2458 2459 toNumber := func() { 2460 e.addSrcMap() 2461 e.c.emit(toNumber) 2462 } 2463 2464 switch e.operator { 2465 case token.NOT: 2466 e.operand.emitGetter(true) 2467 e.c.emit(not) 2468 goto end 2469 case token.BITWISE_NOT: 2470 e.operand.emitGetter(true) 2471 e.c.emit(bnot) 2472 goto end 2473 case token.TYPEOF: 2474 if o, ok := e.operand.(compiledExprOrRef); ok { 2475 o.emitGetterOrRef() 2476 } else { 2477 e.operand.emitGetter(true) 2478 } 2479 e.c.emit(typeof) 2480 goto end 2481 case token.DELETE: 2482 e.operand.deleteExpr().emitGetter(putOnStack) 2483 return 2484 case token.MINUS: 2485 e.c.emitExpr(e.operand, true) 2486 e.c.emit(neg) 2487 goto end 2488 case token.PLUS: 2489 e.c.emitExpr(e.operand, true) 2490 e.c.emit(plus) 2491 goto end 2492 case token.INCREMENT: 2493 prepare = toNumber 2494 body = func() { 2495 e.c.emit(inc) 2496 } 2497 case token.DECREMENT: 2498 prepare = toNumber 2499 body = func() { 2500 e.c.emit(dec) 2501 } 2502 case token.VOID: 2503 e.c.emitExpr(e.operand, false) 2504 if putOnStack { 2505 e.c.emit(loadUndef) 2506 } 2507 return 2508 default: 2509 e.c.assert(false, e.offset, "Unknown unary operator: %s", e.operator.String()) 2510 panic("unreachable") 2511 } 2512 2513 e.operand.emitUnary(prepare, body, e.postfix, putOnStack) 2514 return 2515 2516 end: 2517 if !putOnStack { 2518 e.c.emit(pop) 2519 } 2520 } 2521 2522 func (c *compiler) compileUnaryExpression(v *ast.UnaryExpression) compiledExpr { 2523 r := &compiledUnaryExpr{ 2524 operand: c.compileExpression(v.Operand), 2525 operator: v.Operator, 2526 postfix: v.Postfix, 2527 } 2528 r.init(c, v.Idx0()) 2529 return r 2530 } 2531 2532 func (e *compiledConditionalExpr) emitGetter(putOnStack bool) { 2533 e.test.emitGetter(true) 2534 j := len(e.c.p.code) 2535 e.c.emit(nil) 2536 e.consequent.emitGetter(putOnStack) 2537 j1 := len(e.c.p.code) 2538 e.c.emit(nil) 2539 e.c.p.code[j] = jne(len(e.c.p.code) - j) 2540 e.alternate.emitGetter(putOnStack) 2541 e.c.p.code[j1] = jump(len(e.c.p.code) - j1) 2542 } 2543 2544 func (c *compiler) compileConditionalExpression(v *ast.ConditionalExpression) compiledExpr { 2545 r := &compiledConditionalExpr{ 2546 test: c.compileExpression(v.Test), 2547 consequent: c.compileExpression(v.Consequent), 2548 alternate: c.compileExpression(v.Alternate), 2549 } 2550 r.init(c, v.Idx0()) 2551 return r 2552 } 2553 2554 func (e *compiledLogicalOr) constant() bool { 2555 if e.left.constant() { 2556 if v, ex := e.c.evalConst(e.left); ex == nil { 2557 if v.ToBoolean() { 2558 return true 2559 } 2560 return e.right.constant() 2561 } else { 2562 return true 2563 } 2564 } 2565 2566 return false 2567 } 2568 2569 func (e *compiledLogicalOr) emitGetter(putOnStack bool) { 2570 if e.left.constant() { 2571 if v, ex := e.c.evalConst(e.left); ex == nil { 2572 if !v.ToBoolean() { 2573 e.c.emitExpr(e.right, putOnStack) 2574 } else { 2575 if putOnStack { 2576 e.c.emit(loadVal(e.c.p.defineLiteralValue(v))) 2577 } 2578 } 2579 } else { 2580 e.c.emitThrow(ex.val) 2581 } 2582 return 2583 } 2584 e.c.emitExpr(e.left, true) 2585 j := len(e.c.p.code) 2586 e.addSrcMap() 2587 e.c.emit(nil) 2588 e.c.emitExpr(e.right, true) 2589 e.c.p.code[j] = jeq1(len(e.c.p.code) - j) 2590 if !putOnStack { 2591 e.c.emit(pop) 2592 } 2593 } 2594 2595 func (e *compiledCoalesce) constant() bool { 2596 if e.left.constant() { 2597 if v, ex := e.c.evalConst(e.left); ex == nil { 2598 if v != _null && v != _undefined { 2599 return true 2600 } 2601 return e.right.constant() 2602 } else { 2603 return true 2604 } 2605 } 2606 2607 return false 2608 } 2609 2610 func (e *compiledCoalesce) emitGetter(putOnStack bool) { 2611 if e.left.constant() { 2612 if v, ex := e.c.evalConst(e.left); ex == nil { 2613 if v == _undefined || v == _null { 2614 e.c.emitExpr(e.right, putOnStack) 2615 } else { 2616 if putOnStack { 2617 e.c.emit(loadVal(e.c.p.defineLiteralValue(v))) 2618 } 2619 } 2620 } else { 2621 e.c.emitThrow(ex.val) 2622 } 2623 return 2624 } 2625 e.c.emitExpr(e.left, true) 2626 j := len(e.c.p.code) 2627 e.addSrcMap() 2628 e.c.emit(nil) 2629 e.c.emitExpr(e.right, true) 2630 e.c.p.code[j] = jcoalesc(len(e.c.p.code) - j) 2631 if !putOnStack { 2632 e.c.emit(pop) 2633 } 2634 } 2635 2636 func (e *compiledLogicalAnd) constant() bool { 2637 if e.left.constant() { 2638 if v, ex := e.c.evalConst(e.left); ex == nil { 2639 if !v.ToBoolean() { 2640 return true 2641 } else { 2642 return e.right.constant() 2643 } 2644 } else { 2645 return true 2646 } 2647 } 2648 2649 return false 2650 } 2651 2652 func (e *compiledLogicalAnd) emitGetter(putOnStack bool) { 2653 var j int 2654 if e.left.constant() { 2655 if v, ex := e.c.evalConst(e.left); ex == nil { 2656 if !v.ToBoolean() { 2657 e.c.emit(loadVal(e.c.p.defineLiteralValue(v))) 2658 } else { 2659 e.c.emitExpr(e.right, putOnStack) 2660 } 2661 } else { 2662 e.c.emitThrow(ex.val) 2663 } 2664 return 2665 } 2666 e.left.emitGetter(true) 2667 j = len(e.c.p.code) 2668 e.addSrcMap() 2669 e.c.emit(nil) 2670 e.c.emitExpr(e.right, true) 2671 e.c.p.code[j] = jneq1(len(e.c.p.code) - j) 2672 if !putOnStack { 2673 e.c.emit(pop) 2674 } 2675 } 2676 2677 func (e *compiledBinaryExpr) constant() bool { 2678 return e.left.constant() && e.right.constant() 2679 } 2680 2681 func (e *compiledBinaryExpr) emitGetter(putOnStack bool) { 2682 e.c.emitExpr(e.left, true) 2683 e.c.emitExpr(e.right, true) 2684 e.addSrcMap() 2685 2686 switch e.operator { 2687 case token.LESS: 2688 e.c.emit(op_lt) 2689 case token.GREATER: 2690 e.c.emit(op_gt) 2691 case token.LESS_OR_EQUAL: 2692 e.c.emit(op_lte) 2693 case token.GREATER_OR_EQUAL: 2694 e.c.emit(op_gte) 2695 case token.EQUAL: 2696 e.c.emit(op_eq) 2697 case token.NOT_EQUAL: 2698 e.c.emit(op_neq) 2699 case token.STRICT_EQUAL: 2700 e.c.emit(op_strict_eq) 2701 case token.STRICT_NOT_EQUAL: 2702 e.c.emit(op_strict_neq) 2703 case token.PLUS: 2704 e.c.emit(add) 2705 case token.MINUS: 2706 e.c.emit(sub) 2707 case token.MULTIPLY: 2708 e.c.emit(mul) 2709 case token.EXPONENT: 2710 e.c.emit(exp) 2711 case token.SLASH: 2712 e.c.emit(div) 2713 case token.REMAINDER: 2714 e.c.emit(mod) 2715 case token.AND: 2716 e.c.emit(and) 2717 case token.OR: 2718 e.c.emit(or) 2719 case token.EXCLUSIVE_OR: 2720 e.c.emit(xor) 2721 case token.INSTANCEOF: 2722 e.c.emit(op_instanceof) 2723 case token.IN: 2724 e.c.emit(op_in) 2725 case token.SHIFT_LEFT: 2726 e.c.emit(sal) 2727 case token.SHIFT_RIGHT: 2728 e.c.emit(sar) 2729 case token.UNSIGNED_SHIFT_RIGHT: 2730 e.c.emit(shr) 2731 default: 2732 e.c.assert(false, e.offset, "Unknown operator: %s", e.operator.String()) 2733 panic("unreachable") 2734 } 2735 2736 if !putOnStack { 2737 e.c.emit(pop) 2738 } 2739 } 2740 2741 func (c *compiler) compileBinaryExpression(v *ast.BinaryExpression) compiledExpr { 2742 2743 switch v.Operator { 2744 case token.LOGICAL_OR: 2745 return c.compileLogicalOr(v.Left, v.Right, v.Idx0()) 2746 case token.COALESCE: 2747 return c.compileCoalesce(v.Left, v.Right, v.Idx0()) 2748 case token.LOGICAL_AND: 2749 return c.compileLogicalAnd(v.Left, v.Right, v.Idx0()) 2750 } 2751 2752 if id, ok := v.Left.(*ast.PrivateIdentifier); ok { 2753 return c.compilePrivateIn(id, v.Right, id.Idx) 2754 } 2755 2756 r := &compiledBinaryExpr{ 2757 left: c.compileExpression(v.Left), 2758 right: c.compileExpression(v.Right), 2759 operator: v.Operator, 2760 } 2761 r.init(c, v.Idx0()) 2762 return r 2763 } 2764 2765 type compiledPrivateIn struct { 2766 baseCompiledExpr 2767 id unistring.String 2768 right compiledExpr 2769 } 2770 2771 func (e *compiledPrivateIn) emitGetter(putOnStack bool) { 2772 e.right.emitGetter(true) 2773 rn, id := e.c.resolvePrivateName(e.id, e.offset) 2774 if rn != nil { 2775 e.c.emit((*privateInRes)(rn)) 2776 } else { 2777 e.c.emit((*privateInId)(id)) 2778 } 2779 if !putOnStack { 2780 e.c.emit(pop) 2781 } 2782 } 2783 2784 func (c *compiler) compilePrivateIn(id *ast.PrivateIdentifier, right ast.Expression, idx file.Idx) compiledExpr { 2785 r := &compiledPrivateIn{ 2786 id: id.Name, 2787 right: c.compileExpression(right), 2788 } 2789 r.init(c, idx) 2790 return r 2791 } 2792 2793 func (c *compiler) compileLogicalOr(left, right ast.Expression, idx file.Idx) compiledExpr { 2794 r := &compiledLogicalOr{ 2795 left: c.compileExpression(left), 2796 right: c.compileExpression(right), 2797 } 2798 r.init(c, idx) 2799 return r 2800 } 2801 2802 func (c *compiler) compileCoalesce(left, right ast.Expression, idx file.Idx) compiledExpr { 2803 r := &compiledCoalesce{ 2804 left: c.compileExpression(left), 2805 right: c.compileExpression(right), 2806 } 2807 r.init(c, idx) 2808 return r 2809 } 2810 2811 func (c *compiler) compileLogicalAnd(left, right ast.Expression, idx file.Idx) compiledExpr { 2812 r := &compiledLogicalAnd{ 2813 left: c.compileExpression(left), 2814 right: c.compileExpression(right), 2815 } 2816 r.init(c, idx) 2817 return r 2818 } 2819 2820 func (e *compiledObjectLiteral) emitGetter(putOnStack bool) { 2821 e.addSrcMap() 2822 e.c.emit(newObject) 2823 hasProto := false 2824 for _, prop := range e.expr.Value { 2825 switch prop := prop.(type) { 2826 case *ast.PropertyKeyed: 2827 key, computed := e.c.processKey(prop.Key) 2828 valueExpr := e.c.compileExpression(prop.Value) 2829 var ne namedEmitter 2830 if fn, ok := valueExpr.(*compiledFunctionLiteral); ok { 2831 if fn.name == nil { 2832 ne = fn 2833 } 2834 switch prop.Kind { 2835 case ast.PropertyKindMethod, ast.PropertyKindGet, ast.PropertyKindSet: 2836 fn.typ = funcMethod 2837 if computed { 2838 fn.homeObjOffset = 2 2839 } else { 2840 fn.homeObjOffset = 1 2841 } 2842 } 2843 } else if v, ok := valueExpr.(namedEmitter); ok { 2844 ne = v 2845 } 2846 if computed { 2847 e.c.emit(_toPropertyKey{}) 2848 e.c.emitExpr(valueExpr, true) 2849 switch prop.Kind { 2850 case ast.PropertyKindValue: 2851 if ne != nil { 2852 e.c.emit(setElem1Named) 2853 } else { 2854 e.c.emit(setElem1) 2855 } 2856 case ast.PropertyKindMethod: 2857 e.c.emit(&defineMethod{enumerable: true}) 2858 case ast.PropertyKindGet: 2859 e.c.emit(&defineGetter{enumerable: true}) 2860 case ast.PropertyKindSet: 2861 e.c.emit(&defineSetter{enumerable: true}) 2862 default: 2863 e.c.assert(false, e.offset, "unknown property kind: %s", prop.Kind) 2864 panic("unreachable") 2865 } 2866 } else { 2867 isProto := key == __proto__ && !prop.Computed 2868 if isProto { 2869 if hasProto { 2870 e.c.throwSyntaxError(int(prop.Idx0())-1, "Duplicate __proto__ fields are not allowed in object literals") 2871 } else { 2872 hasProto = true 2873 } 2874 } 2875 if ne != nil && !isProto { 2876 ne.emitNamed(key) 2877 } else { 2878 e.c.emitExpr(valueExpr, true) 2879 } 2880 switch prop.Kind { 2881 case ast.PropertyKindValue: 2882 if isProto { 2883 e.c.emit(setProto) 2884 } else { 2885 e.c.emit(putProp(key)) 2886 } 2887 case ast.PropertyKindMethod: 2888 e.c.emit(&defineMethodKeyed{key: key, enumerable: true}) 2889 case ast.PropertyKindGet: 2890 e.c.emit(&defineGetterKeyed{key: key, enumerable: true}) 2891 case ast.PropertyKindSet: 2892 e.c.emit(&defineSetterKeyed{key: key, enumerable: true}) 2893 default: 2894 e.c.assert(false, e.offset, "unknown property kind: %s", prop.Kind) 2895 panic("unreachable") 2896 } 2897 } 2898 case *ast.PropertyShort: 2899 key := prop.Name.Name 2900 if prop.Initializer != nil { 2901 e.c.throwSyntaxError(int(prop.Initializer.Idx0())-1, "Invalid shorthand property initializer") 2902 } 2903 if e.c.scope.strict && key == "let" { 2904 e.c.throwSyntaxError(e.offset, "'let' cannot be used as a shorthand property in strict mode") 2905 } 2906 e.c.compileIdentifierExpression(&prop.Name).emitGetter(true) 2907 e.c.emit(putProp(key)) 2908 case *ast.SpreadElement: 2909 e.c.compileExpression(prop.Expression).emitGetter(true) 2910 e.c.emit(copySpread) 2911 default: 2912 e.c.assert(false, e.offset, "unknown Property type: %T", prop) 2913 panic("unreachable") 2914 } 2915 } 2916 if !putOnStack { 2917 e.c.emit(pop) 2918 } 2919 } 2920 2921 func (c *compiler) compileObjectLiteral(v *ast.ObjectLiteral) compiledExpr { 2922 r := &compiledObjectLiteral{ 2923 expr: v, 2924 } 2925 r.init(c, v.Idx0()) 2926 return r 2927 } 2928 2929 func (e *compiledArrayLiteral) emitGetter(putOnStack bool) { 2930 e.addSrcMap() 2931 hasSpread := false 2932 mark := len(e.c.p.code) 2933 e.c.emit(nil) 2934 for _, v := range e.expr.Value { 2935 if spread, ok := v.(*ast.SpreadElement); ok { 2936 hasSpread = true 2937 e.c.compileExpression(spread.Expression).emitGetter(true) 2938 e.c.emit(pushArraySpread) 2939 } else { 2940 if v != nil { 2941 e.c.emitExpr(e.c.compileExpression(v), true) 2942 } else { 2943 e.c.emit(loadNil) 2944 } 2945 e.c.emit(pushArrayItem) 2946 } 2947 } 2948 var objCount uint32 2949 if !hasSpread { 2950 objCount = uint32(len(e.expr.Value)) 2951 } 2952 e.c.p.code[mark] = newArray(objCount) 2953 if !putOnStack { 2954 e.c.emit(pop) 2955 } 2956 } 2957 2958 func (c *compiler) compileArrayLiteral(v *ast.ArrayLiteral) compiledExpr { 2959 r := &compiledArrayLiteral{ 2960 expr: v, 2961 } 2962 r.init(c, v.Idx0()) 2963 return r 2964 } 2965 2966 func (e *compiledRegexpLiteral) emitGetter(putOnStack bool) { 2967 if putOnStack { 2968 pattern, err := compileRegexp(e.expr.Pattern, e.expr.Flags) 2969 if err != nil { 2970 e.c.throwSyntaxError(e.offset, err.Error()) 2971 } 2972 2973 e.c.emit(&newRegexp{pattern: pattern, src: newStringValue(e.expr.Pattern)}) 2974 } 2975 } 2976 2977 func (c *compiler) compileRegexpLiteral(v *ast.RegExpLiteral) compiledExpr { 2978 r := &compiledRegexpLiteral{ 2979 expr: v, 2980 } 2981 r.init(c, v.Idx0()) 2982 return r 2983 } 2984 2985 func (c *compiler) emitCallee(callee compiledExpr) (calleeName unistring.String) { 2986 switch callee := callee.(type) { 2987 case *compiledDotExpr: 2988 callee.left.emitGetter(true) 2989 c.emit(getPropCallee(callee.name)) 2990 case *compiledPrivateDotExpr: 2991 callee.left.emitGetter(true) 2992 rn, id := c.resolvePrivateName(callee.name, callee.offset) 2993 if rn != nil { 2994 c.emit((*getPrivatePropResCallee)(rn)) 2995 } else { 2996 c.emit((*getPrivatePropIdCallee)(id)) 2997 } 2998 case *compiledSuperDotExpr: 2999 c.emitLoadThis() 3000 c.emit(loadSuper) 3001 c.emit(getPropRecvCallee(callee.name)) 3002 case *compiledBracketExpr: 3003 callee.left.emitGetter(true) 3004 callee.member.emitGetter(true) 3005 c.emit(getElemCallee) 3006 case *compiledSuperBracketExpr: 3007 c.emitLoadThis() 3008 c.emit(loadSuper) 3009 callee.member.emitGetter(true) 3010 c.emit(getElemRecvCallee) 3011 case *compiledIdentifierExpr: 3012 calleeName = callee.name 3013 callee.emitGetterAndCallee() 3014 case *compiledOptionalChain: 3015 c.startOptChain() 3016 c.emitCallee(callee.expr) 3017 c.endOptChain() 3018 case *compiledOptional: 3019 c.emitCallee(callee.expr) 3020 c.block.conts = append(c.block.conts, len(c.p.code)) 3021 c.emit(nil) 3022 case *compiledSuperExpr: 3023 // no-op 3024 default: 3025 c.emit(loadUndef) 3026 callee.emitGetter(true) 3027 } 3028 return 3029 } 3030 3031 func (e *compiledCallExpr) emitGetter(putOnStack bool) { 3032 if e.isVariadic { 3033 e.c.emit(startVariadic) 3034 } 3035 calleeName := e.c.emitCallee(e.callee) 3036 3037 for _, expr := range e.args { 3038 expr.emitGetter(true) 3039 } 3040 3041 e.addSrcMap() 3042 if _, ok := e.callee.(*compiledSuperExpr); ok { 3043 b, eval := e.c.scope.lookupThis() 3044 e.c.assert(eval || b != nil, e.offset, "super call, but no 'this' binding") 3045 if eval { 3046 e.c.emit(resolveThisDynamic{}) 3047 } else { 3048 b.markAccessPoint() 3049 e.c.emit(resolveThisStack{}) 3050 } 3051 if e.isVariadic { 3052 e.c.emit(superCallVariadic) 3053 } else { 3054 e.c.emit(superCall(len(e.args))) 3055 } 3056 } else if calleeName == "eval" { 3057 foundVar := false 3058 for sc := e.c.scope; sc != nil; sc = sc.outer { 3059 if !foundVar && (sc.variable || sc.isFunction()) { 3060 foundVar = true 3061 if !sc.strict { 3062 sc.dynamic = true 3063 } 3064 } 3065 sc.dynLookup = true 3066 } 3067 3068 if e.c.scope.strict { 3069 if e.isVariadic { 3070 e.c.emit(callEvalVariadicStrict) 3071 } else { 3072 e.c.emit(callEvalStrict(len(e.args))) 3073 } 3074 } else { 3075 if e.isVariadic { 3076 e.c.emit(callEvalVariadic) 3077 } else { 3078 e.c.emit(callEval(len(e.args))) 3079 } 3080 } 3081 } else { 3082 if e.isVariadic { 3083 e.c.emit(callVariadic) 3084 } else { 3085 e.c.emit(call(len(e.args))) 3086 } 3087 } 3088 if e.isVariadic { 3089 e.c.emit(endVariadic) 3090 } 3091 if !putOnStack { 3092 e.c.emit(pop) 3093 } 3094 } 3095 3096 func (e *compiledCallExpr) deleteExpr() compiledExpr { 3097 r := &defaultDeleteExpr{ 3098 expr: e, 3099 } 3100 r.init(e.c, file.Idx(e.offset+1)) 3101 return r 3102 } 3103 3104 func (c *compiler) compileSpreadCallArgument(spread *ast.SpreadElement) compiledExpr { 3105 r := &compiledSpreadCallArgument{ 3106 expr: c.compileExpression(spread.Expression), 3107 } 3108 r.init(c, spread.Idx0()) 3109 return r 3110 } 3111 3112 func (c *compiler) compileCallee(v ast.Expression) compiledExpr { 3113 if sup, ok := v.(*ast.SuperExpression); ok { 3114 if s := c.scope.nearestThis(); s != nil && s.funcType == funcDerivedCtor { 3115 e := &compiledSuperExpr{} 3116 e.init(c, sup.Idx) 3117 return e 3118 } 3119 c.throwSyntaxError(int(v.Idx0())-1, "'super' keyword unexpected here") 3120 panic("unreachable") 3121 } 3122 return c.compileExpression(v) 3123 } 3124 3125 func (c *compiler) compileCallExpression(v *ast.CallExpression) compiledExpr { 3126 3127 args := make([]compiledExpr, len(v.ArgumentList)) 3128 isVariadic := false 3129 for i, argExpr := range v.ArgumentList { 3130 if spread, ok := argExpr.(*ast.SpreadElement); ok { 3131 args[i] = c.compileSpreadCallArgument(spread) 3132 isVariadic = true 3133 } else { 3134 args[i] = c.compileExpression(argExpr) 3135 } 3136 } 3137 3138 r := &compiledCallExpr{ 3139 args: args, 3140 callee: c.compileCallee(v.Callee), 3141 isVariadic: isVariadic, 3142 } 3143 r.init(c, v.LeftParenthesis) 3144 return r 3145 } 3146 3147 func (c *compiler) compileIdentifierExpression(v *ast.Identifier) compiledExpr { 3148 if c.scope.strict { 3149 c.checkIdentifierName(v.Name, int(v.Idx)-1) 3150 } 3151 3152 r := &compiledIdentifierExpr{ 3153 name: v.Name, 3154 } 3155 r.offset = int(v.Idx) - 1 3156 r.init(c, v.Idx0()) 3157 return r 3158 } 3159 3160 func (c *compiler) compileNumberLiteral(v *ast.NumberLiteral) compiledExpr { 3161 if c.scope.strict && len(v.Literal) > 1 && v.Literal[0] == '0' && v.Literal[1] <= '7' && v.Literal[1] >= '0' { 3162 c.throwSyntaxError(int(v.Idx)-1, "Octal literals are not allowed in strict mode") 3163 panic("Unreachable") 3164 } 3165 var val Value 3166 switch num := v.Value.(type) { 3167 case int64: 3168 val = intToValue(num) 3169 case float64: 3170 val = floatToValue(num) 3171 default: 3172 c.assert(false, int(v.Idx)-1, "Unsupported number literal type: %T", v.Value) 3173 panic("unreachable") 3174 } 3175 r := &compiledLiteral{ 3176 val: val, 3177 } 3178 r.init(c, v.Idx0()) 3179 return r 3180 } 3181 3182 func (c *compiler) compileStringLiteral(v *ast.StringLiteral) compiledExpr { 3183 r := &compiledLiteral{ 3184 val: stringValueFromRaw(v.Value), 3185 } 3186 r.init(c, v.Idx0()) 3187 return r 3188 } 3189 3190 func (c *compiler) compileTemplateLiteral(v *ast.TemplateLiteral) compiledExpr { 3191 r := &compiledTemplateLiteral{} 3192 if v.Tag != nil { 3193 r.tag = c.compileExpression(v.Tag) 3194 } 3195 ce := make([]compiledExpr, len(v.Expressions)) 3196 for i, expr := range v.Expressions { 3197 ce[i] = c.compileExpression(expr) 3198 } 3199 r.expressions = ce 3200 r.elements = v.Elements 3201 r.init(c, v.Idx0()) 3202 return r 3203 } 3204 3205 func (c *compiler) compileBooleanLiteral(v *ast.BooleanLiteral) compiledExpr { 3206 var val Value 3207 if v.Value { 3208 val = valueTrue 3209 } else { 3210 val = valueFalse 3211 } 3212 3213 r := &compiledLiteral{ 3214 val: val, 3215 } 3216 r.init(c, v.Idx0()) 3217 return r 3218 } 3219 3220 func (c *compiler) compileAssignExpression(v *ast.AssignExpression) compiledExpr { 3221 // log.Printf("compileAssignExpression(): %+v", v) 3222 3223 r := &compiledAssignExpr{ 3224 left: c.compileExpression(v.Left), 3225 right: c.compileExpression(v.Right), 3226 operator: v.Operator, 3227 } 3228 r.init(c, v.Idx0()) 3229 return r 3230 } 3231 3232 func (e *compiledEnumGetExpr) emitGetter(putOnStack bool) { 3233 e.c.emit(enumGet) 3234 if !putOnStack { 3235 e.c.emit(pop) 3236 } 3237 } 3238 3239 func (c *compiler) compileObjectAssignmentPattern(v *ast.ObjectPattern) compiledExpr { 3240 r := &compiledObjectAssignmentPattern{ 3241 expr: v, 3242 } 3243 r.init(c, v.Idx0()) 3244 return r 3245 } 3246 3247 func (e *compiledObjectAssignmentPattern) emitGetter(putOnStack bool) { 3248 if putOnStack { 3249 e.c.emit(loadUndef) 3250 } 3251 } 3252 3253 func (c *compiler) compileArrayAssignmentPattern(v *ast.ArrayPattern) compiledExpr { 3254 r := &compiledArrayAssignmentPattern{ 3255 expr: v, 3256 } 3257 r.init(c, v.Idx0()) 3258 return r 3259 } 3260 3261 func (e *compiledArrayAssignmentPattern) emitGetter(putOnStack bool) { 3262 if putOnStack { 3263 e.c.emit(loadUndef) 3264 } 3265 } 3266 3267 func (c *compiler) emitExpr(expr compiledExpr, putOnStack bool) { 3268 if expr.constant() { 3269 c.emitConst(expr, putOnStack) 3270 } else { 3271 expr.emitGetter(putOnStack) 3272 } 3273 } 3274 3275 type namedEmitter interface { 3276 emitNamed(name unistring.String) 3277 } 3278 3279 func (c *compiler) emitNamed(expr compiledExpr, name unistring.String) { 3280 if en, ok := expr.(namedEmitter); ok { 3281 en.emitNamed(name) 3282 } else { 3283 expr.emitGetter(true) 3284 } 3285 } 3286 3287 func (c *compiler) emitNamedOrConst(expr compiledExpr, name unistring.String) { 3288 if expr.constant() { 3289 c.emitConst(expr, true) 3290 } else { 3291 c.emitNamed(expr, name) 3292 } 3293 } 3294 3295 func (e *compiledFunctionLiteral) emitNamed(name unistring.String) { 3296 e.lhsName = name 3297 e.emitGetter(true) 3298 } 3299 3300 func (e *compiledClassLiteral) emitNamed(name unistring.String) { 3301 e.lhsName = name 3302 e.emitGetter(true) 3303 } 3304 3305 func (c *compiler) emitPattern(pattern ast.Pattern, emitter func(target, init compiledExpr), putOnStack bool) { 3306 switch pattern := pattern.(type) { 3307 case *ast.ObjectPattern: 3308 c.emitObjectPattern(pattern, emitter, putOnStack) 3309 case *ast.ArrayPattern: 3310 c.emitArrayPattern(pattern, emitter, putOnStack) 3311 default: 3312 c.assert(false, int(pattern.Idx0())-1, "unsupported Pattern: %T", pattern) 3313 panic("unreachable") 3314 } 3315 } 3316 3317 func (c *compiler) emitAssign(target ast.Expression, init compiledExpr, emitAssignSimple func(target, init compiledExpr)) { 3318 pattern, isPattern := target.(ast.Pattern) 3319 if isPattern { 3320 init.emitGetter(true) 3321 c.emitPattern(pattern, emitAssignSimple, false) 3322 } else { 3323 emitAssignSimple(c.compileExpression(target), init) 3324 } 3325 } 3326 3327 func (c *compiler) emitObjectPattern(pattern *ast.ObjectPattern, emitAssign func(target, init compiledExpr), putOnStack bool) { 3328 if pattern.Rest != nil { 3329 c.emit(createDestructSrc) 3330 } else { 3331 c.emit(checkObjectCoercible) 3332 } 3333 for _, prop := range pattern.Properties { 3334 switch prop := prop.(type) { 3335 case *ast.PropertyShort: 3336 c.emit(dup) 3337 emitAssign(c.compileIdentifierExpression(&prop.Name), c.compilePatternInitExpr(func() { 3338 c.emit(getProp(prop.Name.Name)) 3339 }, prop.Initializer, prop.Idx0())) 3340 case *ast.PropertyKeyed: 3341 c.emit(dup) 3342 c.compileExpression(prop.Key).emitGetter(true) 3343 c.emit(_toPropertyKey{}) 3344 var target ast.Expression 3345 var initializer ast.Expression 3346 if e, ok := prop.Value.(*ast.AssignExpression); ok { 3347 target = e.Left 3348 initializer = e.Right 3349 } else { 3350 target = prop.Value 3351 } 3352 c.emitAssign(target, c.compilePatternInitExpr(func() { 3353 c.emit(getKey) 3354 }, initializer, prop.Idx0()), emitAssign) 3355 default: 3356 c.throwSyntaxError(int(prop.Idx0()-1), "Unsupported AssignmentProperty type: %T", prop) 3357 } 3358 } 3359 if pattern.Rest != nil { 3360 emitAssign(c.compileExpression(pattern.Rest), c.compileEmitterExpr(func() { 3361 c.emit(copyRest) 3362 }, pattern.Rest.Idx0())) 3363 c.emit(pop) 3364 } 3365 if !putOnStack { 3366 c.emit(pop) 3367 } 3368 } 3369 3370 func (c *compiler) emitArrayPattern(pattern *ast.ArrayPattern, emitAssign func(target, init compiledExpr), putOnStack bool) { 3371 c.emit(iterate) 3372 for _, elt := range pattern.Elements { 3373 switch elt := elt.(type) { 3374 case nil: 3375 c.emit(iterGetNextOrUndef{}, pop) 3376 case *ast.AssignExpression: 3377 c.emitAssign(elt.Left, c.compilePatternInitExpr(func() { 3378 c.emit(iterGetNextOrUndef{}) 3379 }, elt.Right, elt.Idx0()), emitAssign) 3380 default: 3381 c.emitAssign(elt, c.compileEmitterExpr(func() { 3382 c.emit(iterGetNextOrUndef{}) 3383 }, elt.Idx0()), emitAssign) 3384 } 3385 } 3386 if pattern.Rest != nil { 3387 c.emitAssign(pattern.Rest, c.compileEmitterExpr(func() { 3388 c.emit(newArrayFromIter) 3389 }, pattern.Rest.Idx0()), emitAssign) 3390 } else { 3391 c.emit(enumPopClose) 3392 } 3393 3394 if !putOnStack { 3395 c.emit(pop) 3396 } 3397 } 3398 3399 func (e *compiledObjectAssignmentPattern) emitSetter(valueExpr compiledExpr, putOnStack bool) { 3400 valueExpr.emitGetter(true) 3401 e.c.emitObjectPattern(e.expr, e.c.emitPatternAssign, putOnStack) 3402 } 3403 3404 func (e *compiledArrayAssignmentPattern) emitSetter(valueExpr compiledExpr, putOnStack bool) { 3405 valueExpr.emitGetter(true) 3406 e.c.emitArrayPattern(e.expr, e.c.emitPatternAssign, putOnStack) 3407 } 3408 3409 type compiledPatternInitExpr struct { 3410 baseCompiledExpr 3411 emitSrc func() 3412 def compiledExpr 3413 } 3414 3415 func (e *compiledPatternInitExpr) emitGetter(putOnStack bool) { 3416 if !putOnStack { 3417 return 3418 } 3419 e.emitSrc() 3420 if e.def != nil { 3421 mark := len(e.c.p.code) 3422 e.c.emit(nil) 3423 e.c.emitExpr(e.def, true) 3424 e.c.p.code[mark] = jdef(len(e.c.p.code) - mark) 3425 } 3426 } 3427 3428 func (e *compiledPatternInitExpr) emitNamed(name unistring.String) { 3429 e.emitSrc() 3430 if e.def != nil { 3431 mark := len(e.c.p.code) 3432 e.c.emit(nil) 3433 e.c.emitNamedOrConst(e.def, name) 3434 e.c.p.code[mark] = jdef(len(e.c.p.code) - mark) 3435 } 3436 } 3437 3438 func (c *compiler) compilePatternInitExpr(emitSrc func(), def ast.Expression, idx file.Idx) compiledExpr { 3439 r := &compiledPatternInitExpr{ 3440 emitSrc: emitSrc, 3441 def: c.compileExpression(def), 3442 } 3443 r.init(c, idx) 3444 return r 3445 } 3446 3447 type compiledEmitterExpr struct { 3448 baseCompiledExpr 3449 emitter func() 3450 namedEmitter func(name unistring.String) 3451 } 3452 3453 func (e *compiledEmitterExpr) emitGetter(putOnStack bool) { 3454 if e.emitter != nil { 3455 e.emitter() 3456 } else { 3457 e.namedEmitter("") 3458 } 3459 if !putOnStack { 3460 e.c.emit(pop) 3461 } 3462 } 3463 3464 func (e *compiledEmitterExpr) emitNamed(name unistring.String) { 3465 if e.namedEmitter != nil { 3466 e.namedEmitter(name) 3467 } else { 3468 e.emitter() 3469 } 3470 } 3471 3472 func (c *compiler) compileEmitterExpr(emitter func(), idx file.Idx) *compiledEmitterExpr { 3473 r := &compiledEmitterExpr{ 3474 emitter: emitter, 3475 } 3476 r.init(c, idx) 3477 return r 3478 } 3479 3480 func (e *compiledSpreadCallArgument) emitGetter(putOnStack bool) { 3481 e.expr.emitGetter(putOnStack) 3482 if putOnStack { 3483 e.c.emit(pushSpread) 3484 } 3485 } 3486 3487 func (c *compiler) startOptChain() { 3488 c.block = &block{ 3489 typ: blockOptChain, 3490 outer: c.block, 3491 } 3492 } 3493 3494 func (c *compiler) endOptChain() { 3495 lbl := len(c.p.code) 3496 for _, item := range c.block.breaks { 3497 c.p.code[item] = jopt(lbl - item) 3498 } 3499 for _, item := range c.block.conts { 3500 c.p.code[item] = joptc(lbl - item) 3501 } 3502 c.block = c.block.outer 3503 } 3504 3505 func (e *compiledOptionalChain) emitGetter(putOnStack bool) { 3506 e.c.startOptChain() 3507 e.expr.emitGetter(true) 3508 e.c.endOptChain() 3509 if !putOnStack { 3510 e.c.emit(pop) 3511 } 3512 } 3513 3514 func (e *compiledOptional) emitGetter(putOnStack bool) { 3515 e.expr.emitGetter(putOnStack) 3516 if putOnStack { 3517 e.c.block.breaks = append(e.c.block.breaks, len(e.c.p.code)) 3518 e.c.emit(nil) 3519 } 3520 }