1package goja 2 3import ( 4 "fmt" 5 "math" 6 "reflect" 7 "sort" 8 9 "github.com/dop251/goja/unistring" 10) 11 12const ( 13 classObject = "Object" 14 classArray = "Array" 15 classWeakSet = "WeakSet" 16 classWeakMap = "WeakMap" 17 classMap = "Map" 18 classMath = "Math" 19 classSet = "Set" 20 classFunction = "Function" 21 classNumber = "Number" 22 classString = "String" 23 classBoolean = "Boolean" 24 classError = "Error" 25 classRegExp = "RegExp" 26 classDate = "Date" 27 classJSON = "JSON" 28 classGlobal = "global" 29 30 classArrayIterator = "Array Iterator" 31 classMapIterator = "Map Iterator" 32 classSetIterator = "Set Iterator" 33 classStringIterator = "String Iterator" 34 classRegExpStringIterator = "RegExp String Iterator" 35) 36 37var ( 38 hintDefault Value = asciiString("default") 39 hintNumber Value = asciiString("number") 40 hintString Value = asciiString("string") 41) 42 43type Object struct { 44 id uint64 45 runtime *Runtime 46 self objectImpl 47 48 weakRefs map[weakMap]Value 49} 50 51type iterNextFunc func() (propIterItem, iterNextFunc) 52 53type PropertyDescriptor struct { 54 jsDescriptor *Object 55 56 Value Value 57 58 Writable, Configurable, Enumerable Flag 59 60 Getter, Setter Value 61} 62 63func (p *PropertyDescriptor) Empty() bool { 64 var empty PropertyDescriptor 65 return *p == empty 66} 67 68func (p *PropertyDescriptor) IsAccessor() bool { 69 return p.Setter != nil || p.Getter != nil 70} 71 72func (p *PropertyDescriptor) IsData() bool { 73 return p.Value != nil || p.Writable != FLAG_NOT_SET 74} 75 76func (p *PropertyDescriptor) IsGeneric() bool { 77 return !p.IsAccessor() && !p.IsData() 78} 79 80func (p *PropertyDescriptor) toValue(r *Runtime) Value { 81 if p.jsDescriptor != nil { 82 return p.jsDescriptor 83 } 84 if p.Empty() { 85 return _undefined 86 } 87 o := r.NewObject() 88 s := o.self 89 90 if p.Value != nil { 91 s._putProp("value", p.Value, true, true, true) 92 } 93 94 if p.Writable != FLAG_NOT_SET { 95 s._putProp("writable", valueBool(p.Writable.Bool()), true, true, true) 96 } 97 98 if p.Enumerable != FLAG_NOT_SET { 99 s._putProp("enumerable", valueBool(p.Enumerable.Bool()), true, true, true) 100 } 101 102 if p.Configurable != FLAG_NOT_SET { 103 s._putProp("configurable", valueBool(p.Configurable.Bool()), true, true, true) 104 } 105 106 if p.Getter != nil { 107 s._putProp("get", p.Getter, true, true, true) 108 } 109 if p.Setter != nil { 110 s._putProp("set", p.Setter, true, true, true) 111 } 112 113 return o 114} 115 116func (p *PropertyDescriptor) complete() { 117 if p.Getter == nil && p.Setter == nil { 118 if p.Value == nil { 119 p.Value = _undefined 120 } 121 if p.Writable == FLAG_NOT_SET { 122 p.Writable = FLAG_FALSE 123 } 124 } else { 125 if p.Getter == nil { 126 p.Getter = _undefined 127 } 128 if p.Setter == nil { 129 p.Setter = _undefined 130 } 131 } 132 if p.Enumerable == FLAG_NOT_SET { 133 p.Enumerable = FLAG_FALSE 134 } 135 if p.Configurable == FLAG_NOT_SET { 136 p.Configurable = FLAG_FALSE 137 } 138} 139 140type objectExportCacheItem map[reflect.Type]interface{} 141 142type objectExportCtx struct { 143 cache map[objectImpl]interface{} 144} 145 146type objectImpl interface { 147 sortable 148 className() string 149 getStr(p unistring.String, receiver Value) Value 150 getIdx(p valueInt, receiver Value) Value 151 getSym(p *Symbol, receiver Value) Value 152 153 getOwnPropStr(unistring.String) Value 154 getOwnPropIdx(valueInt) Value 155 getOwnPropSym(*Symbol) Value 156 157 setOwnStr(p unistring.String, v Value, throw bool) bool 158 setOwnIdx(p valueInt, v Value, throw bool) bool 159 setOwnSym(p *Symbol, v Value, throw bool) bool 160 161 setForeignStr(p unistring.String, v, receiver Value, throw bool) (res bool, handled bool) 162 setForeignIdx(p valueInt, v, receiver Value, throw bool) (res bool, handled bool) 163 setForeignSym(p *Symbol, v, receiver Value, throw bool) (res bool, handled bool) 164 165 hasPropertyStr(unistring.String) bool 166 hasPropertyIdx(idx valueInt) bool 167 hasPropertySym(s *Symbol) bool 168 169 hasOwnPropertyStr(unistring.String) bool 170 hasOwnPropertyIdx(valueInt) bool 171 hasOwnPropertySym(s *Symbol) bool 172 173 defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool 174 defineOwnPropertyIdx(name valueInt, desc PropertyDescriptor, throw bool) bool 175 defineOwnPropertySym(name *Symbol, desc PropertyDescriptor, throw bool) bool 176 177 deleteStr(name unistring.String, throw bool) bool 178 deleteIdx(idx valueInt, throw bool) bool 179 deleteSym(s *Symbol, throw bool) bool 180 181 toPrimitiveNumber() Value 182 toPrimitiveString() Value 183 toPrimitive() Value 184 assertCallable() (call func(FunctionCall) Value, ok bool) 185 assertConstructor() func(args []Value, newTarget *Object) *Object 186 proto() *Object 187 setProto(proto *Object, throw bool) bool 188 hasInstance(v Value) bool 189 isExtensible() bool 190 preventExtensions(throw bool) bool 191 enumerateOwnKeys() iterNextFunc 192 export(ctx *objectExportCtx) interface{} 193 exportType() reflect.Type 194 equal(objectImpl) bool 195 ownKeys(all bool, accum []Value) []Value 196 ownSymbols(all bool, accum []Value) []Value 197 ownPropertyKeys(all bool, accum []Value) []Value 198 199 _putProp(name unistring.String, value Value, writable, enumerable, configurable bool) Value 200 _putSym(s *Symbol, prop Value) 201} 202 203type baseObject struct { 204 class string 205 val *Object 206 prototype *Object 207 extensible bool 208 209 values map[unistring.String]Value 210 propNames []unistring.String 211 212 lastSortedPropLen, idxPropCount int 213 214 symValues *orderedMap 215} 216 217type guardedObject struct { 218 baseObject 219 guardedProps map[unistring.String]struct{} 220} 221 222type primitiveValueObject struct { 223 baseObject 224 pValue Value 225} 226 227func (o *primitiveValueObject) export(*objectExportCtx) interface{} { 228 return o.pValue.Export() 229} 230 231func (o *primitiveValueObject) exportType() reflect.Type { 232 return o.pValue.ExportType() 233} 234 235type FunctionCall struct { 236 This Value 237 Arguments []Value 238} 239 240type ConstructorCall struct { 241 This *Object 242 Arguments []Value 243 NewTarget *Object 244} 245 246func (f FunctionCall) Argument(idx int) Value { 247 if idx < len(f.Arguments) { 248 return f.Arguments[idx] 249 } 250 return _undefined 251} 252 253func (f ConstructorCall) Argument(idx int) Value { 254 if idx < len(f.Arguments) { 255 return f.Arguments[idx] 256 } 257 return _undefined 258} 259 260func (o *baseObject) init() { 261 o.values = make(map[unistring.String]Value) 262} 263 264func (o *baseObject) className() string { 265 return o.class 266} 267 268func (o *baseObject) hasPropertyStr(name unistring.String) bool { 269 if o.val.self.hasOwnPropertyStr(name) { 270 return true 271 } 272 if o.prototype != nil { 273 return o.prototype.self.hasPropertyStr(name) 274 } 275 return false 276} 277 278func (o *baseObject) hasPropertyIdx(idx valueInt) bool { 279 return o.val.self.hasPropertyStr(idx.string()) 280} 281 282func (o *baseObject) hasPropertySym(s *Symbol) bool { 283 if o.hasOwnPropertySym(s) { 284 return true 285 } 286 if o.prototype != nil { 287 return o.prototype.self.hasPropertySym(s) 288 } 289 return false 290} 291 292func (o *baseObject) getWithOwnProp(prop, p, receiver Value) Value { 293 if prop == nil && o.prototype != nil { 294 if receiver == nil { 295 return o.prototype.get(p, o.val) 296 } 297 return o.prototype.get(p, receiver) 298 } 299 if prop, ok := prop.(*valueProperty); ok { 300 if receiver == nil { 301 return prop.get(o.val) 302 } 303 return prop.get(receiver) 304 } 305 return prop 306} 307 308func (o *baseObject) getStrWithOwnProp(prop Value, name unistring.String, receiver Value) Value { 309 if prop == nil && o.prototype != nil { 310 if receiver == nil { 311 return o.prototype.self.getStr(name, o.val) 312 } 313 return o.prototype.self.getStr(name, receiver) 314 } 315 if prop, ok := prop.(*valueProperty); ok { 316 if receiver == nil { 317 return prop.get(o.val) 318 } 319 return prop.get(receiver) 320 } 321 return prop 322} 323 324func (o *baseObject) getIdx(idx valueInt, receiver Value) Value { 325 return o.val.self.getStr(idx.string(), receiver) 326} 327 328func (o *baseObject) getSym(s *Symbol, receiver Value) Value { 329 return o.getWithOwnProp(o.getOwnPropSym(s), s, receiver) 330} 331 332func (o *baseObject) getStr(name unistring.String, receiver Value) Value { 333 prop := o.values[name] 334 if prop == nil { 335 if o.prototype != nil { 336 if receiver == nil { 337 return o.prototype.self.getStr(name, o.val) 338 } 339 return o.prototype.self.getStr(name, receiver) 340 } 341 } 342 if prop, ok := prop.(*valueProperty); ok { 343 if receiver == nil { 344 return prop.get(o.val) 345 } 346 return prop.get(receiver) 347 } 348 return prop 349} 350 351func (o *baseObject) getOwnPropIdx(idx valueInt) Value { 352 return o.val.self.getOwnPropStr(idx.string()) 353} 354 355func (o *baseObject) getOwnPropSym(s *Symbol) Value { 356 if o.symValues != nil { 357 return o.symValues.get(s) 358 } 359 return nil 360} 361 362func (o *baseObject) getOwnPropStr(name unistring.String) Value { 363 return o.values[name] 364} 365 366func (o *baseObject) checkDeleteProp(name unistring.String, prop *valueProperty, throw bool) bool { 367 if !prop.configurable { 368 o.val.runtime.typeErrorResult(throw, "Cannot delete property '%s' of %s", name, o.val.toString()) 369 return false 370 } 371 return true 372} 373 374func (o *baseObject) checkDelete(name unistring.String, val Value, throw bool) bool { 375 if val, ok := val.(*valueProperty); ok { 376 return o.checkDeleteProp(name, val, throw) 377 } 378 return true 379} 380 381func (o *baseObject) _delete(name unistring.String) { 382 delete(o.values, name) 383 for i, n := range o.propNames { 384 if n == name { 385 names := o.propNames 386 if namesMarkedForCopy(names) { 387 newNames := make([]unistring.String, len(names)-1, shrinkCap(len(names), cap(names))) 388 copy(newNames, names[:i]) 389 copy(newNames[i:], names[i+1:]) 390 o.propNames = newNames 391 } else { 392 copy(names[i:], names[i+1:]) 393 names[len(names)-1] = "" 394 o.propNames = names[:len(names)-1] 395 } 396 if i < o.lastSortedPropLen { 397 o.lastSortedPropLen-- 398 if i < o.idxPropCount { 399 o.idxPropCount-- 400 } 401 } 402 break 403 } 404 } 405} 406 407func (o *baseObject) deleteIdx(idx valueInt, throw bool) bool { 408 return o.val.self.deleteStr(idx.string(), throw) 409} 410 411func (o *baseObject) deleteSym(s *Symbol, throw bool) bool { 412 if o.symValues != nil { 413 if val := o.symValues.get(s); val != nil { 414 if !o.checkDelete(s.descriptiveString().string(), val, throw) { 415 return false 416 } 417 o.symValues.remove(s) 418 } 419 } 420 return true 421} 422 423func (o *baseObject) deleteStr(name unistring.String, throw bool) bool { 424 if val, exists := o.values[name]; exists { 425 if !o.checkDelete(name, val, throw) { 426 return false 427 } 428 o._delete(name) 429 } 430 return true 431} 432 433func (o *baseObject) setProto(proto *Object, throw bool) bool { 434 current := o.prototype 435 if current.SameAs(proto) { 436 return true 437 } 438 if !o.extensible { 439 o.val.runtime.typeErrorResult(throw, "%s is not extensible", o.val) 440 return false 441 } 442 for p := proto; p != nil; p = p.self.proto() { 443 if p.SameAs(o.val) { 444 o.val.runtime.typeErrorResult(throw, "Cyclic __proto__ value") 445 return false 446 } 447 if _, ok := p.self.(*proxyObject); ok { 448 break 449 } 450 } 451 o.prototype = proto 452 return true 453} 454 455func (o *baseObject) setOwnStr(name unistring.String, val Value, throw bool) bool { 456 ownDesc := o.values[name] 457 if ownDesc == nil { 458 if proto := o.prototype; proto != nil { 459 // we know it's foreign because prototype loops are not allowed 460 if res, handled := proto.self.setForeignStr(name, val, o.val, throw); handled { 461 return res 462 } 463 } 464 // new property 465 if !o.extensible { 466 o.val.runtime.typeErrorResult(throw, "Cannot add property %s, object is not extensible", name) 467 return false 468 } else { 469 o.values[name] = val 470 names := copyNamesIfNeeded(o.propNames, 1) 471 o.propNames = append(names, name) 472 } 473 return true 474 } 475 if prop, ok := ownDesc.(*valueProperty); ok { 476 if !prop.isWritable() { 477 o.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name) 478 return false 479 } else { 480 prop.set(o.val, val) 481 } 482 } else { 483 o.values[name] = val 484 } 485 return true 486} 487 488func (o *baseObject) setOwnIdx(idx valueInt, val Value, throw bool) bool { 489 return o.val.self.setOwnStr(idx.string(), val, throw) 490} 491 492func (o *baseObject) setOwnSym(name *Symbol, val Value, throw bool) bool { 493 var ownDesc Value 494 if o.symValues != nil { 495 ownDesc = o.symValues.get(name) 496 } 497 if ownDesc == nil { 498 if proto := o.prototype; proto != nil { 499 // we know it's foreign because prototype loops are not allowed 500 if res, handled := proto.self.setForeignSym(name, val, o.val, throw); handled { 501 return res 502 } 503 } 504 // new property 505 if !o.extensible { 506 o.val.runtime.typeErrorResult(throw, "Cannot add property %s, object is not extensible", name) 507 return false 508 } else { 509 if o.symValues == nil { 510 o.symValues = newOrderedMap(nil) 511 } 512 o.symValues.set(name, val) 513 } 514 return true 515 } 516 if prop, ok := ownDesc.(*valueProperty); ok { 517 if !prop.isWritable() { 518 o.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name) 519 return false 520 } else { 521 prop.set(o.val, val) 522 } 523 } else { 524 o.symValues.set(name, val) 525 } 526 return true 527} 528 529func (o *baseObject) _setForeignStr(name unistring.String, prop, val, receiver Value, throw bool) (bool, bool) { 530 if prop != nil { 531 if prop, ok := prop.(*valueProperty); ok { 532 if !prop.isWritable() { 533 o.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name) 534 return false, true 535 } 536 if prop.setterFunc != nil { 537 prop.set(receiver, val) 538 return true, true 539 } 540 } 541 } else { 542 if proto := o.prototype; proto != nil { 543 if receiver != proto { 544 return proto.self.setForeignStr(name, val, receiver, throw) 545 } 546 return proto.self.setOwnStr(name, val, throw), true 547 } 548 } 549 return false, false 550} 551 552func (o *baseObject) _setForeignIdx(idx valueInt, prop, val, receiver Value, throw bool) (bool, bool) { 553 if prop != nil { 554 if prop, ok := prop.(*valueProperty); ok { 555 if !prop.isWritable() { 556 o.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%d'", idx) 557 return false, true 558 } 559 if prop.setterFunc != nil { 560 prop.set(receiver, val) 561 return true, true 562 } 563 } 564 } else { 565 if proto := o.prototype; proto != nil { 566 if receiver != proto { 567 return proto.self.setForeignIdx(idx, val, receiver, throw) 568 } 569 return proto.self.setOwnIdx(idx, val, throw), true 570 } 571 } 572 return false, false 573} 574 575func (o *baseObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) { 576 return o._setForeignStr(name, o.values[name], val, receiver, throw) 577} 578 579func (o *baseObject) setForeignIdx(name valueInt, val, receiver Value, throw bool) (bool, bool) { 580 if idx := toIdx(name); idx != math.MaxUint32 { 581 if o.lastSortedPropLen != len(o.propNames) { 582 o.fixPropOrder() 583 } 584 if o.idxPropCount == 0 { 585 return o._setForeignIdx(name, name, nil, receiver, throw) 586 } 587 } 588 return o.setForeignStr(name.string(), val, receiver, throw) 589} 590 591func (o *baseObject) setForeignSym(name *Symbol, val, receiver Value, throw bool) (bool, bool) { 592 var prop Value 593 if o.symValues != nil { 594 prop = o.symValues.get(name) 595 } 596 if prop != nil { 597 if prop, ok := prop.(*valueProperty); ok { 598 if !prop.isWritable() { 599 o.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name) 600 return false, true 601 } 602 if prop.setterFunc != nil { 603 prop.set(receiver, val) 604 return true, true 605 } 606 } 607 } else { 608 if proto := o.prototype; proto != nil { 609 if receiver != o.val { 610 return proto.self.setForeignSym(name, val, receiver, throw) 611 } 612 return proto.self.setOwnSym(name, val, throw), true 613 } 614 } 615 return false, false 616} 617 618func (o *baseObject) hasOwnPropertySym(s *Symbol) bool { 619 if o.symValues != nil { 620 return o.symValues.has(s) 621 } 622 return false 623} 624 625func (o *baseObject) hasOwnPropertyStr(name unistring.String) bool { 626 _, exists := o.values[name] 627 return exists 628} 629 630func (o *baseObject) hasOwnPropertyIdx(idx valueInt) bool { 631 return o.val.self.hasOwnPropertyStr(idx.string()) 632} 633 634func (o *baseObject) _defineOwnProperty(name unistring.String, existingValue Value, descr PropertyDescriptor, throw bool) (val Value, ok bool) { 635 636 getterObj, _ := descr.Getter.(*Object) 637 setterObj, _ := descr.Setter.(*Object) 638 639 var existing *valueProperty 640 641 if existingValue == nil { 642 if !o.extensible { 643 o.val.runtime.typeErrorResult(throw, "Cannot define property %s, object is not extensible", name) 644 return nil, false 645 } 646 existing = &valueProperty{} 647 } else { 648 if existing, ok = existingValue.(*valueProperty); !ok { 649 existing = &valueProperty{ 650 writable: true, 651 enumerable: true, 652 configurable: true, 653 value: existingValue, 654 } 655 } 656 657 if !existing.configurable { 658 if descr.Configurable == FLAG_TRUE { 659 goto Reject 660 } 661 if descr.Enumerable != FLAG_NOT_SET && descr.Enumerable.Bool() != existing.enumerable { 662 goto Reject 663 } 664 } 665 if existing.accessor && descr.Value != nil || !existing.accessor && (getterObj != nil || setterObj != nil) { 666 if !existing.configurable { 667 goto Reject 668 } 669 } else if !existing.accessor { 670 if !existing.configurable { 671 if !existing.writable { 672 if descr.Writable == FLAG_TRUE { 673 goto Reject 674 } 675 if descr.Value != nil && !descr.Value.SameAs(existing.value) { 676 goto Reject 677 } 678 } 679 } 680 } else { 681 if !existing.configurable { 682 if descr.Getter != nil && existing.getterFunc != getterObj || descr.Setter != nil && existing.setterFunc != setterObj { 683 goto Reject 684 } 685 } 686 } 687 } 688 689 if descr.Writable == FLAG_TRUE && descr.Enumerable == FLAG_TRUE && descr.Configurable == FLAG_TRUE && descr.Value != nil { 690 return descr.Value, true 691 } 692 693 if descr.Writable != FLAG_NOT_SET { 694 existing.writable = descr.Writable.Bool() 695 } 696 if descr.Enumerable != FLAG_NOT_SET { 697 existing.enumerable = descr.Enumerable.Bool() 698 } 699 if descr.Configurable != FLAG_NOT_SET { 700 existing.configurable = descr.Configurable.Bool() 701 } 702 703 if descr.Value != nil { 704 existing.value = descr.Value 705 existing.getterFunc = nil 706 existing.setterFunc = nil 707 } 708 709 if descr.Value != nil || descr.Writable != FLAG_NOT_SET { 710 existing.accessor = false 711 } 712 713 if descr.Getter != nil { 714 existing.getterFunc = propGetter(o.val, descr.Getter, o.val.runtime) 715 existing.value = nil 716 existing.accessor = true 717 } 718 719 if descr.Setter != nil { 720 existing.setterFunc = propSetter(o.val, descr.Setter, o.val.runtime) 721 existing.value = nil 722 existing.accessor = true 723 } 724 725 if !existing.accessor && existing.value == nil { 726 existing.value = _undefined 727 } 728 729 return existing, true 730 731Reject: 732 o.val.runtime.typeErrorResult(throw, "Cannot redefine property: %s", name) 733 return nil, false 734 735} 736 737func (o *baseObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool { 738 existingVal := o.values[name] 739 if v, ok := o._defineOwnProperty(name, existingVal, descr, throw); ok { 740 o.values[name] = v 741 if existingVal == nil { 742 names := copyNamesIfNeeded(o.propNames, 1) 743 o.propNames = append(names, name) 744 } 745 return true 746 } 747 return false 748} 749 750func (o *baseObject) defineOwnPropertyIdx(idx valueInt, desc PropertyDescriptor, throw bool) bool { 751 return o.val.self.defineOwnPropertyStr(idx.string(), desc, throw) 752} 753 754func (o *baseObject) defineOwnPropertySym(s *Symbol, descr PropertyDescriptor, throw bool) bool { 755 var existingVal Value 756 if o.symValues != nil { 757 existingVal = o.symValues.get(s) 758 } 759 if v, ok := o._defineOwnProperty(s.descriptiveString().string(), existingVal, descr, throw); ok { 760 if o.symValues == nil { 761 o.symValues = newOrderedMap(nil) 762 } 763 o.symValues.set(s, v) 764 return true 765 } 766 return false 767} 768 769func (o *baseObject) _put(name unistring.String, v Value) { 770 if _, exists := o.values[name]; !exists { 771 names := copyNamesIfNeeded(o.propNames, 1) 772 o.propNames = append(names, name) 773 } 774 775 o.values[name] = v 776} 777 778func valueProp(value Value, writable, enumerable, configurable bool) Value { 779 if writable && enumerable && configurable { 780 return value 781 } 782 return &valueProperty{ 783 value: value, 784 writable: writable, 785 enumerable: enumerable, 786 configurable: configurable, 787 } 788} 789 790func (o *baseObject) _putProp(name unistring.String, value Value, writable, enumerable, configurable bool) Value { 791 prop := valueProp(value, writable, enumerable, configurable) 792 o._put(name, prop) 793 return prop 794} 795 796func (o *baseObject) _putSym(s *Symbol, prop Value) { 797 if o.symValues == nil { 798 o.symValues = newOrderedMap(nil) 799 } 800 o.symValues.set(s, prop) 801} 802 803func (o *Object) tryPrimitive(methodName unistring.String) Value { 804 if method, ok := o.self.getStr(methodName, nil).(*Object); ok { 805 if call, ok := method.self.assertCallable(); ok { 806 v := call(FunctionCall{ 807 This: o, 808 }) 809 if _, fail := v.(*Object); !fail { 810 return v 811 } 812 } 813 } 814 return nil 815} 816 817func (o *Object) genericToPrimitiveNumber() Value { 818 if v := o.tryPrimitive("valueOf"); v != nil { 819 return v 820 } 821 822 if v := o.tryPrimitive("toString"); v != nil { 823 return v 824 } 825 826 panic(o.runtime.NewTypeError("Could not convert %v to primitive", o.self)) 827} 828 829func (o *baseObject) toPrimitiveNumber() Value { 830 return o.val.genericToPrimitiveNumber() 831} 832 833func (o *Object) genericToPrimitiveString() Value { 834 if v := o.tryPrimitive("toString"); v != nil { 835 return v 836 } 837 838 if v := o.tryPrimitive("valueOf"); v != nil { 839 return v 840 } 841 842 panic(o.runtime.NewTypeError("Could not convert %v to primitive", o.self)) 843} 844 845func (o *Object) genericToPrimitive() Value { 846 return o.genericToPrimitiveNumber() 847} 848 849func (o *baseObject) toPrimitiveString() Value { 850 return o.val.genericToPrimitiveString() 851} 852 853func (o *baseObject) toPrimitive() Value { 854 return o.val.genericToPrimitiveNumber() 855} 856 857func (o *Object) tryExoticToPrimitive(hint Value) Value { 858 exoticToPrimitive := toMethod(o.self.getSym(SymToPrimitive, nil)) 859 if exoticToPrimitive != nil { 860 ret := exoticToPrimitive(FunctionCall{ 861 This: o, 862 Arguments: []Value{hint}, 863 }) 864 if _, fail := ret.(*Object); !fail { 865 return ret 866 } 867 panic(o.runtime.NewTypeError("Cannot convert object to primitive value")) 868 } 869 return nil 870} 871 872func (o *Object) toPrimitiveNumber() Value { 873 if v := o.tryExoticToPrimitive(hintNumber); v != nil { 874 return v 875 } 876 877 return o.self.toPrimitiveNumber() 878} 879 880func (o *Object) toPrimitiveString() Value { 881 if v := o.tryExoticToPrimitive(hintString); v != nil { 882 return v 883 } 884 885 return o.self.toPrimitiveString() 886} 887 888func (o *Object) toPrimitive() Value { 889 if v := o.tryExoticToPrimitive(hintDefault); v != nil { 890 return v 891 } 892 return o.self.toPrimitive() 893} 894 895func (o *baseObject) assertCallable() (func(FunctionCall) Value, bool) { 896 return nil, false 897} 898 899func (o *baseObject) assertConstructor() func(args []Value, newTarget *Object) *Object { 900 return nil 901} 902 903func (o *baseObject) proto() *Object { 904 return o.prototype 905} 906 907func (o *baseObject) isExtensible() bool { 908 return o.extensible 909} 910 911func (o *baseObject) preventExtensions(bool) bool { 912 o.extensible = false 913 return true 914} 915 916func (o *baseObject) sortLen() int64 { 917 return toLength(o.val.self.getStr("length", nil)) 918} 919 920func (o *baseObject) sortGet(i int64) Value { 921 return o.val.self.getIdx(valueInt(i), nil) 922} 923 924func (o *baseObject) swap(i, j int64) { 925 ii := valueInt(i) 926 jj := valueInt(j) 927 928 x := o.val.self.getIdx(ii, nil) 929 y := o.val.self.getIdx(jj, nil) 930 931 o.val.self.setOwnIdx(ii, y, false) 932 o.val.self.setOwnIdx(jj, x, false) 933} 934 935func (o *baseObject) export(ctx *objectExportCtx) interface{} { 936 if v, exists := ctx.get(o); exists { 937 return v 938 } 939 keys := o.ownKeys(false, nil) 940 m := make(map[string]interface{}, len(keys)) 941 ctx.put(o, m) 942 for _, itemName := range keys { 943 itemNameStr := itemName.String() 944 v := o.val.self.getStr(itemName.string(), nil) 945 if v != nil { 946 m[itemNameStr] = exportValue(v, ctx) 947 } else { 948 m[itemNameStr] = nil 949 } 950 } 951 952 return m 953} 954 955func (o *baseObject) exportType() reflect.Type { 956 return reflectTypeMap 957} 958 959type enumerableFlag int 960 961const ( 962 _ENUM_UNKNOWN enumerableFlag = iota 963 _ENUM_FALSE 964 _ENUM_TRUE 965) 966 967type propIterItem struct { 968 name unistring.String 969 value Value // set only when enumerable == _ENUM_UNKNOWN 970 enumerable enumerableFlag 971} 972 973type objectPropIter struct { 974 o *baseObject 975 propNames []unistring.String 976 idx int 977} 978 979type recursivePropIter struct { 980 o objectImpl 981 cur iterNextFunc 982 seen map[unistring.String]struct{} 983} 984 985type enumerableIter struct { 986 wrapped iterNextFunc 987} 988 989func (i *enumerableIter) next() (propIterItem, iterNextFunc) { 990 for { 991 var item propIterItem 992 item, i.wrapped = i.wrapped() 993 if i.wrapped == nil { 994 return item, nil 995 } 996 if item.enumerable == _ENUM_FALSE { 997 continue 998 } 999 if item.enumerable == _ENUM_UNKNOWN { 1000 if prop, ok := item.value.(*valueProperty); ok { 1001 if !prop.enumerable { 1002 continue 1003 } 1004 } 1005 } 1006 return item, i.next 1007 } 1008} 1009 1010func (i *recursivePropIter) next() (propIterItem, iterNextFunc) { 1011 for { 1012 var item propIterItem 1013 item, i.cur = i.cur() 1014 if i.cur == nil { 1015 if proto := i.o.proto(); proto != nil { 1016 i.cur = proto.self.enumerateOwnKeys() 1017 i.o = proto.self 1018 continue 1019 } 1020 return propIterItem{}, nil 1021 } 1022 if _, exists := i.seen[item.name]; !exists { 1023 i.seen[item.name] = struct{}{} 1024 return item, i.next 1025 } 1026 } 1027} 1028 1029func enumerateRecursive(o *Object) iterNextFunc { 1030 return (&enumerableIter{ 1031 wrapped: (&recursivePropIter{ 1032 o: o.self, 1033 cur: o.self.enumerateOwnKeys(), 1034 seen: make(map[unistring.String]struct{}), 1035 }).next, 1036 }).next 1037} 1038 1039func (i *objectPropIter) next() (propIterItem, iterNextFunc) { 1040 for i.idx < len(i.propNames) { 1041 name := i.propNames[i.idx] 1042 i.idx++ 1043 prop := i.o.values[name] 1044 if prop != nil { 1045 return propIterItem{name: name, value: prop}, i.next 1046 } 1047 } 1048 clearNamesCopyMarker(i.propNames) 1049 return propIterItem{}, nil 1050} 1051 1052var copyMarker = unistring.String(" ") 1053 1054// Set a copy-on-write flag so that any subsequent modifications of anything below the current length 1055// trigger a copy. 1056// The marker is a special value put at the index position of cap-1. Capacity is set so that the marker is 1057// beyond the current length (therefore invisible to normal slice operations). 1058// This function is called before an iteration begins to avoid copying of the names array if 1059// there are no modifications within the iteration. 1060// Note that the copying also occurs in two cases: nested iterations (on the same object) and 1061// iterations after a previously abandoned iteration (because there is currently no mechanism to close an 1062// iterator). It is still better than copying every time. 1063func prepareNamesForCopy(names []unistring.String) []unistring.String { 1064 if len(names) == 0 { 1065 return names 1066 } 1067 if namesMarkedForCopy(names) || cap(names) == len(names) { 1068 var newcap int 1069 if cap(names) == len(names) { 1070 newcap = growCap(len(names)+1, len(names), cap(names)) 1071 } else { 1072 newcap = cap(names) 1073 } 1074 newNames := make([]unistring.String, len(names), newcap) 1075 copy(newNames, names) 1076 names = newNames 1077 } 1078 names[cap(names)-1 : cap(names)][0] = copyMarker 1079 return names 1080} 1081 1082func namesMarkedForCopy(names []unistring.String) bool { 1083 return cap(names) > len(names) && names[cap(names)-1 : cap(names)][0] == copyMarker 1084} 1085 1086func clearNamesCopyMarker(names []unistring.String) { 1087 if cap(names) > len(names) { 1088 names[cap(names)-1 : cap(names)][0] = "" 1089 } 1090} 1091 1092func copyNamesIfNeeded(names []unistring.String, extraCap int) []unistring.String { 1093 if namesMarkedForCopy(names) && len(names)+extraCap >= cap(names) { 1094 var newcap int 1095 newsize := len(names) + extraCap + 1 1096 if newsize > cap(names) { 1097 newcap = growCap(newsize, len(names), cap(names)) 1098 } else { 1099 newcap = cap(names) 1100 } 1101 newNames := make([]unistring.String, len(names), newcap) 1102 copy(newNames, names) 1103 return newNames 1104 } 1105 return names 1106} 1107 1108func (o *baseObject) enumerateOwnKeys() iterNextFunc { 1109 if len(o.propNames) > o.lastSortedPropLen { 1110 o.fixPropOrder() 1111 } 1112 propNames := prepareNamesForCopy(o.propNames) 1113 o.propNames = propNames 1114 return (&objectPropIter{ 1115 o: o, 1116 propNames: propNames, 1117 }).next 1118} 1119 1120func (o *baseObject) equal(objectImpl) bool { 1121 // Rely on parent reference comparison 1122 return false 1123} 1124 1125// Reorder property names so that any integer properties are shifted to the beginning of the list 1126// in ascending order. This is to conform to https://262.ecma-international.org/#sec-ordinaryownpropertykeys. 1127// Personally I think this requirement is strange. I can sort of understand where they are coming from, 1128// this way arrays can be specified just as objects with a 'magic' length property. However, I think 1129// it's safe to assume most devs don't use Objects to store integer properties. Therefore, performing 1130// property type checks when adding (and potentially looking up) properties would be unreasonable. 1131// Instead, we keep insertion order and only change it when (if) the properties get enumerated. 1132func (o *baseObject) fixPropOrder() { 1133 names := o.propNames 1134 for i := o.lastSortedPropLen; i < len(names); i++ { 1135 name := names[i] 1136 if idx := strToArrayIdx(name); idx != math.MaxUint32 { 1137 k := sort.Search(o.idxPropCount, func(j int) bool { 1138 return strToArrayIdx(names[j]) >= idx 1139 }) 1140 if k < i { 1141 if namesMarkedForCopy(names) { 1142 newNames := make([]unistring.String, len(names), cap(names)) 1143 copy(newNames[:k], names) 1144 copy(newNames[k+1:i+1], names[k:i]) 1145 copy(newNames[i+1:], names[i+1:]) 1146 names = newNames 1147 o.propNames = names 1148 } else { 1149 copy(names[k+1:i+1], names[k:i]) 1150 } 1151 names[k] = name 1152 } 1153 o.idxPropCount++ 1154 } 1155 } 1156 o.lastSortedPropLen = len(names) 1157} 1158 1159func (o *baseObject) ownKeys(all bool, keys []Value) []Value { 1160 if len(o.propNames) > o.lastSortedPropLen { 1161 o.fixPropOrder() 1162 } 1163 if all { 1164 for _, k := range o.propNames { 1165 keys = append(keys, stringValueFromRaw(k)) 1166 } 1167 } else { 1168 for _, k := range o.propNames { 1169 prop := o.values[k] 1170 if prop, ok := prop.(*valueProperty); ok && !prop.enumerable { 1171 continue 1172 } 1173 keys = append(keys, stringValueFromRaw(k)) 1174 } 1175 } 1176 return keys 1177} 1178 1179func (o *baseObject) ownSymbols(all bool, accum []Value) []Value { 1180 if o.symValues != nil { 1181 iter := o.symValues.newIter() 1182 if all { 1183 for { 1184 entry := iter.next() 1185 if entry == nil { 1186 break 1187 } 1188 accum = append(accum, entry.key) 1189 } 1190 } else { 1191 for { 1192 entry := iter.next() 1193 if entry == nil { 1194 break 1195 } 1196 if prop, ok := entry.value.(*valueProperty); ok { 1197 if !prop.enumerable { 1198 continue 1199 } 1200 } 1201 accum = append(accum, entry.key) 1202 } 1203 } 1204 } 1205 1206 return accum 1207} 1208 1209func (o *baseObject) ownPropertyKeys(all bool, accum []Value) []Value { 1210 return o.ownSymbols(all, o.val.self.ownKeys(all, accum)) 1211} 1212 1213func (o *baseObject) hasInstance(Value) bool { 1214 panic(o.val.runtime.NewTypeError("Expecting a function in instanceof check, but got %s", o.val.toString())) 1215} 1216 1217func toMethod(v Value) func(FunctionCall) Value { 1218 if v == nil || IsUndefined(v) || IsNull(v) { 1219 return nil 1220 } 1221 if obj, ok := v.(*Object); ok { 1222 if call, ok := obj.self.assertCallable(); ok { 1223 return call 1224 } 1225 } 1226 panic(typeError(fmt.Sprintf("%s is not a method", v.String()))) 1227} 1228 1229func instanceOfOperator(o Value, c *Object) bool { 1230 if instOfHandler := toMethod(c.self.getSym(SymHasInstance, c)); instOfHandler != nil { 1231 return instOfHandler(FunctionCall{ 1232 This: c, 1233 Arguments: []Value{o}, 1234 }).ToBoolean() 1235 } 1236 1237 return c.self.hasInstance(o) 1238} 1239 1240func (o *Object) get(p Value, receiver Value) Value { 1241 switch p := p.(type) { 1242 case valueInt: 1243 return o.self.getIdx(p, receiver) 1244 case *Symbol: 1245 return o.self.getSym(p, receiver) 1246 default: 1247 return o.self.getStr(p.string(), receiver) 1248 } 1249} 1250 1251func (o *Object) getOwnProp(p Value) Value { 1252 switch p := p.(type) { 1253 case valueInt: 1254 return o.self.getOwnPropIdx(p) 1255 case *Symbol: 1256 return o.self.getOwnPropSym(p) 1257 default: 1258 return o.self.getOwnPropStr(p.string()) 1259 } 1260} 1261 1262func (o *Object) hasOwnProperty(p Value) bool { 1263 switch p := p.(type) { 1264 case valueInt: 1265 return o.self.hasOwnPropertyIdx(p) 1266 case *Symbol: 1267 return o.self.hasOwnPropertySym(p) 1268 default: 1269 return o.self.hasOwnPropertyStr(p.string()) 1270 } 1271} 1272 1273func (o *Object) hasProperty(p Value) bool { 1274 switch p := p.(type) { 1275 case valueInt: 1276 return o.self.hasPropertyIdx(p) 1277 case *Symbol: 1278 return o.self.hasPropertySym(p) 1279 default: 1280 return o.self.hasPropertyStr(p.string()) 1281 } 1282} 1283 1284func (o *Object) setStr(name unistring.String, val, receiver Value, throw bool) bool { 1285 if receiver == o { 1286 return o.self.setOwnStr(name, val, throw) 1287 } else { 1288 if res, ok := o.self.setForeignStr(name, val, receiver, throw); !ok { 1289 if robj, ok := receiver.(*Object); ok { 1290 if prop := robj.self.getOwnPropStr(name); prop != nil { 1291 if desc, ok := prop.(*valueProperty); ok { 1292 if desc.accessor { 1293 o.runtime.typeErrorResult(throw, "Receiver property %s is an accessor", name) 1294 return false 1295 } 1296 if !desc.writable { 1297 o.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name) 1298 return false 1299 } 1300 } 1301 robj.self.defineOwnPropertyStr(name, PropertyDescriptor{Value: val}, throw) 1302 } else { 1303 robj.self.defineOwnPropertyStr(name, PropertyDescriptor{ 1304 Value: val, 1305 Writable: FLAG_TRUE, 1306 Configurable: FLAG_TRUE, 1307 Enumerable: FLAG_TRUE, 1308 }, throw) 1309 } 1310 } else { 1311 o.runtime.typeErrorResult(throw, "Receiver is not an object: %v", receiver) 1312 return false 1313 } 1314 } else { 1315 return res 1316 } 1317 } 1318 return true 1319} 1320 1321func (o *Object) set(name Value, val, receiver Value, throw bool) bool { 1322 switch name := name.(type) { 1323 case valueInt: 1324 return o.setIdx(name, val, receiver, throw) 1325 case *Symbol: 1326 return o.setSym(name, val, receiver, throw) 1327 default: 1328 return o.setStr(name.string(), val, receiver, throw) 1329 } 1330} 1331 1332func (o *Object) setOwn(name Value, val Value, throw bool) bool { 1333 switch name := name.(type) { 1334 case valueInt: 1335 return o.self.setOwnIdx(name, val, throw) 1336 case *Symbol: 1337 return o.self.setOwnSym(name, val, throw) 1338 default: 1339 return o.self.setOwnStr(name.string(), val, throw) 1340 } 1341} 1342 1343func (o *Object) setIdx(name valueInt, val, receiver Value, throw bool) bool { 1344 if receiver == o { 1345 return o.self.setOwnIdx(name, val, throw) 1346 } else { 1347 if res, ok := o.self.setForeignIdx(name, val, receiver, throw); !ok { 1348 if robj, ok := receiver.(*Object); ok { 1349 if prop := robj.self.getOwnPropIdx(name); prop != nil { 1350 if desc, ok := prop.(*valueProperty); ok { 1351 if desc.accessor { 1352 o.runtime.typeErrorResult(throw, "Receiver property %s is an accessor", name) 1353 return false 1354 } 1355 if !desc.writable { 1356 o.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name) 1357 return false 1358 } 1359 } 1360 robj.self.defineOwnPropertyIdx(name, PropertyDescriptor{Value: val}, throw) 1361 } else { 1362 robj.self.defineOwnPropertyIdx(name, PropertyDescriptor{ 1363 Value: val, 1364 Writable: FLAG_TRUE, 1365 Configurable: FLAG_TRUE, 1366 Enumerable: FLAG_TRUE, 1367 }, throw) 1368 } 1369 } else { 1370 o.runtime.typeErrorResult(throw, "Receiver is not an object: %v", receiver) 1371 return false 1372 } 1373 } else { 1374 return res 1375 } 1376 } 1377 return true 1378} 1379 1380func (o *Object) setSym(name *Symbol, val, receiver Value, throw bool) bool { 1381 if receiver == o { 1382 return o.self.setOwnSym(name, val, throw) 1383 } else { 1384 if res, ok := o.self.setForeignSym(name, val, receiver, throw); !ok { 1385 if robj, ok := receiver.(*Object); ok { 1386 if prop := robj.self.getOwnPropSym(name); prop != nil { 1387 if desc, ok := prop.(*valueProperty); ok { 1388 if desc.accessor { 1389 o.runtime.typeErrorResult(throw, "Receiver property %s is an accessor", name) 1390 return false 1391 } 1392 if !desc.writable { 1393 o.runtime.typeErrorResult(throw, "Cannot assign to read only property '%s'", name) 1394 return false 1395 } 1396 } 1397 robj.self.defineOwnPropertySym(name, PropertyDescriptor{Value: val}, throw) 1398 } else { 1399 robj.self.defineOwnPropertySym(name, PropertyDescriptor{ 1400 Value: val, 1401 Writable: FLAG_TRUE, 1402 Configurable: FLAG_TRUE, 1403 Enumerable: FLAG_TRUE, 1404 }, throw) 1405 } 1406 } else { 1407 o.runtime.typeErrorResult(throw, "Receiver is not an object: %v", receiver) 1408 return false 1409 } 1410 } else { 1411 return res 1412 } 1413 } 1414 return true 1415} 1416 1417func (o *Object) delete(n Value, throw bool) bool { 1418 switch n := n.(type) { 1419 case valueInt: 1420 return o.self.deleteIdx(n, throw) 1421 case *Symbol: 1422 return o.self.deleteSym(n, throw) 1423 default: 1424 return o.self.deleteStr(n.string(), throw) 1425 } 1426} 1427 1428func (o *Object) defineOwnProperty(n Value, desc PropertyDescriptor, throw bool) bool { 1429 switch n := n.(type) { 1430 case valueInt: 1431 return o.self.defineOwnPropertyIdx(n, desc, throw) 1432 case *Symbol: 1433 return o.self.defineOwnPropertySym(n, desc, throw) 1434 default: 1435 return o.self.defineOwnPropertyStr(n.string(), desc, throw) 1436 } 1437} 1438 1439func (o *Object) getWeakRefs() map[weakMap]Value { 1440 refs := o.weakRefs 1441 if refs == nil { 1442 refs = make(map[weakMap]Value) 1443 o.weakRefs = refs 1444 } 1445 return refs 1446} 1447 1448func (o *Object) getId() uint64 { 1449 id := o.id 1450 if id == 0 { 1451 id = o.runtime.genId() 1452 o.id = id 1453 } 1454 return id 1455} 1456 1457func (o *guardedObject) guard(props ...unistring.String) { 1458 if o.guardedProps == nil { 1459 o.guardedProps = make(map[unistring.String]struct{}) 1460 } 1461 for _, p := range props { 1462 o.guardedProps[p] = struct{}{} 1463 } 1464} 1465 1466func (o *guardedObject) check(p unistring.String) { 1467 if _, exists := o.guardedProps[p]; exists { 1468 o.val.self = &o.baseObject 1469 } 1470} 1471 1472func (o *guardedObject) setOwnStr(p unistring.String, v Value, throw bool) bool { 1473 res := o.baseObject.setOwnStr(p, v, throw) 1474 if res { 1475 o.check(p) 1476 } 1477 return res 1478} 1479 1480func (o *guardedObject) defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool { 1481 res := o.baseObject.defineOwnPropertyStr(name, desc, throw) 1482 if res { 1483 o.check(name) 1484 } 1485 return res 1486} 1487 1488func (o *guardedObject) deleteStr(name unistring.String, throw bool) bool { 1489 res := o.baseObject.deleteStr(name, throw) 1490 if res { 1491 o.check(name) 1492 } 1493 return res 1494} 1495 1496func (ctx *objectExportCtx) get(key objectImpl) (interface{}, bool) { 1497 if v, exists := ctx.cache[key]; exists { 1498 if item, ok := v.(objectExportCacheItem); ok { 1499 r, exists := item[key.exportType()] 1500 return r, exists 1501 } else { 1502 return v, true 1503 } 1504 } 1505 return nil, false 1506} 1507 1508func (ctx *objectExportCtx) getTyped(key objectImpl, typ reflect.Type) (interface{}, bool) { 1509 if v, exists := ctx.cache[key]; exists { 1510 if item, ok := v.(objectExportCacheItem); ok { 1511 r, exists := item[typ] 1512 return r, exists 1513 } else { 1514 if reflect.TypeOf(v) == typ { 1515 return v, true 1516 } 1517 } 1518 } 1519 return nil, false 1520} 1521 1522func (ctx *objectExportCtx) put(key objectImpl, value interface{}) { 1523 if ctx.cache == nil { 1524 ctx.cache = make(map[objectImpl]interface{}) 1525 } 1526 if item, ok := ctx.cache[key].(objectExportCacheItem); ok { 1527 item[key.exportType()] = value 1528 } else { 1529 ctx.cache[key] = value 1530 } 1531} 1532 1533func (ctx *objectExportCtx) putTyped(key objectImpl, typ reflect.Type, value interface{}) { 1534 if ctx.cache == nil { 1535 ctx.cache = make(map[objectImpl]interface{}) 1536 } 1537 v, exists := ctx.cache[key] 1538 if exists { 1539 if item, ok := ctx.cache[key].(objectExportCacheItem); ok { 1540 item[typ] = value 1541 } else { 1542 m := make(objectExportCacheItem, 2) 1543 m[key.exportType()] = v 1544 m[typ] = value 1545 ctx.cache[key] = m 1546 } 1547 } else { 1548 m := make(objectExportCacheItem) 1549 m[typ] = value 1550 ctx.cache[key] = m 1551 } 1552} 1553