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