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