...

Source file src/github.com/dop251/goja/builtin_object.go

Documentation: github.com/dop251/goja

     1  package goja
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  )
     7  
     8  func (r *Runtime) builtin_Object(args []Value, newTarget *Object) *Object {
     9  	if newTarget != nil && newTarget != r.getObject() {
    10  		proto := r.getPrototypeFromCtor(newTarget, nil, r.global.ObjectPrototype)
    11  		return r.newBaseObject(proto, classObject).val
    12  	}
    13  	if len(args) > 0 {
    14  		arg := args[0]
    15  		if arg != _undefined && arg != _null {
    16  			return arg.ToObject(r)
    17  		}
    18  	}
    19  	return r.NewObject()
    20  }
    21  
    22  func (r *Runtime) object_getPrototypeOf(call FunctionCall) Value {
    23  	o := call.Argument(0).ToObject(r)
    24  	p := o.self.proto()
    25  	if p == nil {
    26  		return _null
    27  	}
    28  	return p
    29  }
    30  
    31  func (r *Runtime) valuePropToDescriptorObject(desc Value) Value {
    32  	if desc == nil {
    33  		return _undefined
    34  	}
    35  	var writable, configurable, enumerable, accessor bool
    36  	var get, set *Object
    37  	var value Value
    38  	if v, ok := desc.(*valueProperty); ok {
    39  		writable = v.writable
    40  		configurable = v.configurable
    41  		enumerable = v.enumerable
    42  		accessor = v.accessor
    43  		value = v.value
    44  		get = v.getterFunc
    45  		set = v.setterFunc
    46  	} else {
    47  		writable = true
    48  		configurable = true
    49  		enumerable = true
    50  		value = desc
    51  	}
    52  
    53  	ret := r.NewObject()
    54  	obj := ret.self
    55  	if !accessor {
    56  		obj.setOwnStr("value", value, false)
    57  		obj.setOwnStr("writable", r.toBoolean(writable), false)
    58  	} else {
    59  		if get != nil {
    60  			obj.setOwnStr("get", get, false)
    61  		} else {
    62  			obj.setOwnStr("get", _undefined, false)
    63  		}
    64  		if set != nil {
    65  			obj.setOwnStr("set", set, false)
    66  		} else {
    67  			obj.setOwnStr("set", _undefined, false)
    68  		}
    69  	}
    70  	obj.setOwnStr("enumerable", r.toBoolean(enumerable), false)
    71  	obj.setOwnStr("configurable", r.toBoolean(configurable), false)
    72  
    73  	return ret
    74  }
    75  
    76  func (r *Runtime) object_getOwnPropertyDescriptor(call FunctionCall) Value {
    77  	o := call.Argument(0).ToObject(r)
    78  	propName := toPropertyKey(call.Argument(1))
    79  	return r.valuePropToDescriptorObject(o.getOwnProp(propName))
    80  }
    81  
    82  func (r *Runtime) object_getOwnPropertyDescriptors(call FunctionCall) Value {
    83  	o := call.Argument(0).ToObject(r)
    84  	result := r.newBaseObject(r.global.ObjectPrototype, classObject).val
    85  	for item, next := o.self.iterateKeys()(); next != nil; item, next = next() {
    86  		var prop Value
    87  		if item.value == nil {
    88  			prop = o.getOwnProp(item.name)
    89  			if prop == nil {
    90  				continue
    91  			}
    92  		} else {
    93  			prop = item.value
    94  		}
    95  		descriptor := r.valuePropToDescriptorObject(prop)
    96  		if descriptor != _undefined {
    97  			createDataPropertyOrThrow(result, item.name, descriptor)
    98  		}
    99  	}
   100  	return result
   101  }
   102  
   103  func (r *Runtime) object_getOwnPropertyNames(call FunctionCall) Value {
   104  	obj := call.Argument(0).ToObject(r)
   105  
   106  	return r.newArrayValues(obj.self.stringKeys(true, nil))
   107  }
   108  
   109  func (r *Runtime) object_getOwnPropertySymbols(call FunctionCall) Value {
   110  	obj := call.Argument(0).ToObject(r)
   111  	return r.newArrayValues(obj.self.symbols(true, nil))
   112  }
   113  
   114  func (r *Runtime) toValueProp(v Value) *valueProperty {
   115  	if v == nil || v == _undefined {
   116  		return nil
   117  	}
   118  	obj := r.toObject(v)
   119  	getter := obj.self.getStr("get", nil)
   120  	setter := obj.self.getStr("set", nil)
   121  	writable := obj.self.getStr("writable", nil)
   122  	value := obj.self.getStr("value", nil)
   123  	if (getter != nil || setter != nil) && (value != nil || writable != nil) {
   124  		r.typeErrorResult(true, "Invalid property descriptor. Cannot both specify accessors and a value or writable attribute")
   125  	}
   126  
   127  	ret := &valueProperty{}
   128  	if writable != nil && writable.ToBoolean() {
   129  		ret.writable = true
   130  	}
   131  	if e := obj.self.getStr("enumerable", nil); e != nil && e.ToBoolean() {
   132  		ret.enumerable = true
   133  	}
   134  	if c := obj.self.getStr("configurable", nil); c != nil && c.ToBoolean() {
   135  		ret.configurable = true
   136  	}
   137  	ret.value = value
   138  
   139  	if getter != nil && getter != _undefined {
   140  		o := r.toObject(getter)
   141  		if _, ok := o.self.assertCallable(); !ok {
   142  			r.typeErrorResult(true, "getter must be a function")
   143  		}
   144  		ret.getterFunc = o
   145  	}
   146  
   147  	if setter != nil && setter != _undefined {
   148  		o := r.toObject(setter)
   149  		if _, ok := o.self.assertCallable(); !ok {
   150  			r.typeErrorResult(true, "setter must be a function")
   151  		}
   152  		ret.setterFunc = o
   153  	}
   154  
   155  	if ret.getterFunc != nil || ret.setterFunc != nil {
   156  		ret.accessor = true
   157  	}
   158  
   159  	return ret
   160  }
   161  
   162  func (r *Runtime) toPropertyDescriptor(v Value) (ret PropertyDescriptor) {
   163  	if o, ok := v.(*Object); ok {
   164  		descr := o.self
   165  
   166  		// Save the original descriptor for reference
   167  		ret.jsDescriptor = o
   168  
   169  		ret.Value = descr.getStr("value", nil)
   170  
   171  		if p := descr.getStr("writable", nil); p != nil {
   172  			ret.Writable = ToFlag(p.ToBoolean())
   173  		}
   174  		if p := descr.getStr("enumerable", nil); p != nil {
   175  			ret.Enumerable = ToFlag(p.ToBoolean())
   176  		}
   177  		if p := descr.getStr("configurable", nil); p != nil {
   178  			ret.Configurable = ToFlag(p.ToBoolean())
   179  		}
   180  
   181  		ret.Getter = descr.getStr("get", nil)
   182  		ret.Setter = descr.getStr("set", nil)
   183  
   184  		if ret.Getter != nil && ret.Getter != _undefined {
   185  			if _, ok := r.toObject(ret.Getter).self.assertCallable(); !ok {
   186  				r.typeErrorResult(true, "getter must be a function")
   187  			}
   188  		}
   189  
   190  		if ret.Setter != nil && ret.Setter != _undefined {
   191  			if _, ok := r.toObject(ret.Setter).self.assertCallable(); !ok {
   192  				r.typeErrorResult(true, "setter must be a function")
   193  			}
   194  		}
   195  
   196  		if (ret.Getter != nil || ret.Setter != nil) && (ret.Value != nil || ret.Writable != FLAG_NOT_SET) {
   197  			r.typeErrorResult(true, "Invalid property descriptor. Cannot both specify accessors and a value or writable attribute")
   198  		}
   199  	} else {
   200  		r.typeErrorResult(true, "Property description must be an object: %s", v.String())
   201  	}
   202  
   203  	return
   204  }
   205  
   206  func (r *Runtime) _defineProperties(o *Object, p Value) {
   207  	type propItem struct {
   208  		name Value
   209  		prop PropertyDescriptor
   210  	}
   211  	props := p.ToObject(r)
   212  	var list []propItem
   213  	for item, next := iterateEnumerableProperties(props)(); next != nil; item, next = next() {
   214  		list = append(list, propItem{
   215  			name: item.name,
   216  			prop: r.toPropertyDescriptor(item.value),
   217  		})
   218  	}
   219  	for _, prop := range list {
   220  		o.defineOwnProperty(prop.name, prop.prop, true)
   221  	}
   222  }
   223  
   224  func (r *Runtime) object_create(call FunctionCall) Value {
   225  	var proto *Object
   226  	if arg := call.Argument(0); arg != _null {
   227  		if o, ok := arg.(*Object); ok {
   228  			proto = o
   229  		} else {
   230  			r.typeErrorResult(true, "Object prototype may only be an Object or null: %s", arg.String())
   231  		}
   232  	}
   233  	o := r.newBaseObject(proto, classObject).val
   234  
   235  	if props := call.Argument(1); props != _undefined {
   236  		r._defineProperties(o, props)
   237  	}
   238  
   239  	return o
   240  }
   241  
   242  func (r *Runtime) object_defineProperty(call FunctionCall) (ret Value) {
   243  	if obj, ok := call.Argument(0).(*Object); ok {
   244  		descr := r.toPropertyDescriptor(call.Argument(2))
   245  		obj.defineOwnProperty(toPropertyKey(call.Argument(1)), descr, true)
   246  		ret = call.Argument(0)
   247  	} else {
   248  		r.typeErrorResult(true, "Object.defineProperty called on non-object")
   249  	}
   250  	return
   251  }
   252  
   253  func (r *Runtime) object_defineProperties(call FunctionCall) Value {
   254  	obj := r.toObject(call.Argument(0))
   255  	r._defineProperties(obj, call.Argument(1))
   256  	return obj
   257  }
   258  
   259  func (r *Runtime) object_seal(call FunctionCall) Value {
   260  	// ES6
   261  	arg := call.Argument(0)
   262  	if obj, ok := arg.(*Object); ok {
   263  		obj.self.preventExtensions(true)
   264  		descr := PropertyDescriptor{
   265  			Configurable: FLAG_FALSE,
   266  		}
   267  
   268  		for item, next := obj.self.iterateKeys()(); next != nil; item, next = next() {
   269  			if prop, ok := item.value.(*valueProperty); ok {
   270  				prop.configurable = false
   271  			} else {
   272  				obj.defineOwnProperty(item.name, descr, true)
   273  			}
   274  		}
   275  
   276  		return obj
   277  	}
   278  	return arg
   279  }
   280  
   281  func (r *Runtime) object_freeze(call FunctionCall) Value {
   282  	arg := call.Argument(0)
   283  	if obj, ok := arg.(*Object); ok {
   284  		obj.self.preventExtensions(true)
   285  
   286  		for item, next := obj.self.iterateKeys()(); next != nil; item, next = next() {
   287  			if prop, ok := item.value.(*valueProperty); ok {
   288  				prop.configurable = false
   289  				if !prop.accessor {
   290  					prop.writable = false
   291  				}
   292  			} else {
   293  				prop := obj.getOwnProp(item.name)
   294  				descr := PropertyDescriptor{
   295  					Configurable: FLAG_FALSE,
   296  				}
   297  				if prop, ok := prop.(*valueProperty); ok && prop.accessor {
   298  					// no-op
   299  				} else {
   300  					descr.Writable = FLAG_FALSE
   301  				}
   302  				obj.defineOwnProperty(item.name, descr, true)
   303  			}
   304  		}
   305  		return obj
   306  	} else {
   307  		// ES6 behavior
   308  		return arg
   309  	}
   310  }
   311  
   312  func (r *Runtime) object_preventExtensions(call FunctionCall) (ret Value) {
   313  	arg := call.Argument(0)
   314  	if obj, ok := arg.(*Object); ok {
   315  		obj.self.preventExtensions(true)
   316  	}
   317  	return arg
   318  }
   319  
   320  func (r *Runtime) object_isSealed(call FunctionCall) Value {
   321  	if obj, ok := call.Argument(0).(*Object); ok {
   322  		if obj.self.isExtensible() {
   323  			return valueFalse
   324  		}
   325  		for item, next := obj.self.iterateKeys()(); next != nil; item, next = next() {
   326  			var prop Value
   327  			if item.value == nil {
   328  				prop = obj.getOwnProp(item.name)
   329  				if prop == nil {
   330  					continue
   331  				}
   332  			} else {
   333  				prop = item.value
   334  			}
   335  			if prop, ok := prop.(*valueProperty); ok {
   336  				if prop.configurable {
   337  					return valueFalse
   338  				}
   339  			} else {
   340  				return valueFalse
   341  			}
   342  		}
   343  	}
   344  	return valueTrue
   345  }
   346  
   347  func (r *Runtime) object_isFrozen(call FunctionCall) Value {
   348  	if obj, ok := call.Argument(0).(*Object); ok {
   349  		if obj.self.isExtensible() {
   350  			return valueFalse
   351  		}
   352  		for item, next := obj.self.iterateKeys()(); next != nil; item, next = next() {
   353  			var prop Value
   354  			if item.value == nil {
   355  				prop = obj.getOwnProp(item.name)
   356  				if prop == nil {
   357  					continue
   358  				}
   359  			} else {
   360  				prop = item.value
   361  			}
   362  			if prop, ok := prop.(*valueProperty); ok {
   363  				if prop.configurable || prop.value != nil && prop.writable {
   364  					return valueFalse
   365  				}
   366  			} else {
   367  				return valueFalse
   368  			}
   369  		}
   370  	}
   371  	return valueTrue
   372  }
   373  
   374  func (r *Runtime) object_isExtensible(call FunctionCall) Value {
   375  	if obj, ok := call.Argument(0).(*Object); ok {
   376  		if obj.self.isExtensible() {
   377  			return valueTrue
   378  		}
   379  		return valueFalse
   380  	} else {
   381  		// ES6
   382  		//r.typeErrorResult(true, "Object.isExtensible called on non-object")
   383  		return valueFalse
   384  	}
   385  }
   386  
   387  func (r *Runtime) object_keys(call FunctionCall) Value {
   388  	obj := call.Argument(0).ToObject(r)
   389  
   390  	return r.newArrayValues(obj.self.stringKeys(false, nil))
   391  }
   392  
   393  func (r *Runtime) object_entries(call FunctionCall) Value {
   394  	obj := call.Argument(0).ToObject(r)
   395  
   396  	var values []Value
   397  
   398  	for item, next := iterateEnumerableStringProperties(obj)(); next != nil; item, next = next() {
   399  		values = append(values, r.newArrayValues([]Value{item.name, item.value}))
   400  	}
   401  
   402  	return r.newArrayValues(values)
   403  }
   404  
   405  func (r *Runtime) object_values(call FunctionCall) Value {
   406  	obj := call.Argument(0).ToObject(r)
   407  
   408  	var values []Value
   409  
   410  	for item, next := iterateEnumerableStringProperties(obj)(); next != nil; item, next = next() {
   411  		values = append(values, item.value)
   412  	}
   413  
   414  	return r.newArrayValues(values)
   415  }
   416  
   417  func (r *Runtime) objectproto_hasOwnProperty(call FunctionCall) Value {
   418  	p := toPropertyKey(call.Argument(0))
   419  	o := call.This.ToObject(r)
   420  	if o.hasOwnProperty(p) {
   421  		return valueTrue
   422  	} else {
   423  		return valueFalse
   424  	}
   425  }
   426  
   427  func (r *Runtime) objectproto_isPrototypeOf(call FunctionCall) Value {
   428  	if v, ok := call.Argument(0).(*Object); ok {
   429  		o := call.This.ToObject(r)
   430  		for {
   431  			v = v.self.proto()
   432  			if v == nil {
   433  				break
   434  			}
   435  			if v == o {
   436  				return valueTrue
   437  			}
   438  		}
   439  	}
   440  	return valueFalse
   441  }
   442  
   443  func (r *Runtime) objectproto_propertyIsEnumerable(call FunctionCall) Value {
   444  	p := toPropertyKey(call.Argument(0))
   445  	o := call.This.ToObject(r)
   446  	pv := o.getOwnProp(p)
   447  	if pv == nil {
   448  		return valueFalse
   449  	}
   450  	if prop, ok := pv.(*valueProperty); ok {
   451  		if !prop.enumerable {
   452  			return valueFalse
   453  		}
   454  	}
   455  	return valueTrue
   456  }
   457  
   458  func (r *Runtime) objectproto_toString(call FunctionCall) Value {
   459  	switch o := call.This.(type) {
   460  	case valueNull:
   461  		return stringObjectNull
   462  	case valueUndefined:
   463  		return stringObjectUndefined
   464  	default:
   465  		obj := o.ToObject(r)
   466  		if o, ok := obj.self.(*objectGoReflect); ok {
   467  			if toString := o.toString; toString != nil {
   468  				return toString()
   469  			}
   470  		}
   471  		var clsName string
   472  		if isArray(obj) {
   473  			clsName = classArray
   474  		} else {
   475  			clsName = obj.self.className()
   476  		}
   477  		if tag := obj.self.getSym(SymToStringTag, nil); tag != nil {
   478  			if str, ok := tag.(String); ok {
   479  				clsName = str.String()
   480  			}
   481  		}
   482  		return newStringValue(fmt.Sprintf("[object %s]", clsName))
   483  	}
   484  }
   485  
   486  func (r *Runtime) objectproto_toLocaleString(call FunctionCall) Value {
   487  	toString := toMethod(r.getVStr(call.This, "toString"))
   488  	return toString(FunctionCall{This: call.This})
   489  }
   490  
   491  func (r *Runtime) objectproto_getProto(call FunctionCall) Value {
   492  	proto := call.This.ToObject(r).self.proto()
   493  	if proto != nil {
   494  		return proto
   495  	}
   496  	return _null
   497  }
   498  
   499  func (r *Runtime) setObjectProto(o, arg Value) {
   500  	r.checkObjectCoercible(o)
   501  	var proto *Object
   502  	if arg != _null {
   503  		if obj, ok := arg.(*Object); ok {
   504  			proto = obj
   505  		} else {
   506  			return
   507  		}
   508  	}
   509  	if o, ok := o.(*Object); ok {
   510  		o.self.setProto(proto, true)
   511  	}
   512  }
   513  
   514  func (r *Runtime) objectproto_setProto(call FunctionCall) Value {
   515  	r.setObjectProto(call.This, call.Argument(0))
   516  	return _undefined
   517  }
   518  
   519  func (r *Runtime) objectproto_valueOf(call FunctionCall) Value {
   520  	return call.This.ToObject(r)
   521  }
   522  
   523  func (r *Runtime) object_assign(call FunctionCall) Value {
   524  	to := call.Argument(0).ToObject(r)
   525  	if len(call.Arguments) > 1 {
   526  		for _, arg := range call.Arguments[1:] {
   527  			if arg != _undefined && arg != _null {
   528  				source := arg.ToObject(r)
   529  				for item, next := iterateEnumerableProperties(source)(); next != nil; item, next = next() {
   530  					to.setOwn(item.name, item.value, true)
   531  				}
   532  			}
   533  		}
   534  	}
   535  
   536  	return to
   537  }
   538  
   539  func (r *Runtime) object_is(call FunctionCall) Value {
   540  	return r.toBoolean(call.Argument(0).SameAs(call.Argument(1)))
   541  }
   542  
   543  func (r *Runtime) toProto(proto Value) *Object {
   544  	if proto != _null {
   545  		if obj, ok := proto.(*Object); ok {
   546  			return obj
   547  		} else {
   548  			panic(r.NewTypeError("Object prototype may only be an Object or null: %s", proto))
   549  		}
   550  	}
   551  	return nil
   552  }
   553  
   554  func (r *Runtime) object_setPrototypeOf(call FunctionCall) Value {
   555  	o := call.Argument(0)
   556  	r.checkObjectCoercible(o)
   557  	proto := r.toProto(call.Argument(1))
   558  	if o, ok := o.(*Object); ok {
   559  		o.self.setProto(proto, true)
   560  	}
   561  
   562  	return o
   563  }
   564  
   565  func (r *Runtime) object_fromEntries(call FunctionCall) Value {
   566  	o := call.Argument(0)
   567  	r.checkObjectCoercible(o)
   568  
   569  	result := r.newBaseObject(r.global.ObjectPrototype, classObject).val
   570  
   571  	iter := r.getIterator(o, nil)
   572  	iter.iterate(func(nextValue Value) {
   573  		i0 := valueInt(0)
   574  		i1 := valueInt(1)
   575  
   576  		itemObj := r.toObject(nextValue)
   577  		k := itemObj.self.getIdx(i0, nil)
   578  		v := itemObj.self.getIdx(i1, nil)
   579  		key := toPropertyKey(k)
   580  
   581  		createDataPropertyOrThrow(result, key, v)
   582  	})
   583  
   584  	return result
   585  }
   586  
   587  func (r *Runtime) object_hasOwn(call FunctionCall) Value {
   588  	o := call.Argument(0)
   589  	obj := o.ToObject(r)
   590  	p := toPropertyKey(call.Argument(1))
   591  
   592  	if obj.hasOwnProperty(p) {
   593  		return valueTrue
   594  	} else {
   595  		return valueFalse
   596  	}
   597  }
   598  
   599  func createObjectTemplate() *objectTemplate {
   600  	t := newObjectTemplate()
   601  	t.protoFactory = func(r *Runtime) *Object {
   602  		return r.getFunctionPrototype()
   603  	}
   604  
   605  	t.putStr("length", func(r *Runtime) Value { return valueProp(intToValue(1), false, false, true) })
   606  	t.putStr("name", func(r *Runtime) Value { return valueProp(asciiString("Object"), false, false, true) })
   607  
   608  	t.putStr("prototype", func(r *Runtime) Value { return valueProp(r.global.ObjectPrototype, false, false, false) })
   609  
   610  	t.putStr("assign", func(r *Runtime) Value { return r.methodProp(r.object_assign, "assign", 2) })
   611  	t.putStr("defineProperty", func(r *Runtime) Value { return r.methodProp(r.object_defineProperty, "defineProperty", 3) })
   612  	t.putStr("defineProperties", func(r *Runtime) Value { return r.methodProp(r.object_defineProperties, "defineProperties", 2) })
   613  	t.putStr("entries", func(r *Runtime) Value { return r.methodProp(r.object_entries, "entries", 1) })
   614  	t.putStr("getOwnPropertyDescriptor", func(r *Runtime) Value {
   615  		return r.methodProp(r.object_getOwnPropertyDescriptor, "getOwnPropertyDescriptor", 2)
   616  	})
   617  	t.putStr("getOwnPropertyDescriptors", func(r *Runtime) Value {
   618  		return r.methodProp(r.object_getOwnPropertyDescriptors, "getOwnPropertyDescriptors", 1)
   619  	})
   620  	t.putStr("getPrototypeOf", func(r *Runtime) Value { return r.methodProp(r.object_getPrototypeOf, "getPrototypeOf", 1) })
   621  	t.putStr("is", func(r *Runtime) Value { return r.methodProp(r.object_is, "is", 2) })
   622  	t.putStr("getOwnPropertyNames", func(r *Runtime) Value { return r.methodProp(r.object_getOwnPropertyNames, "getOwnPropertyNames", 1) })
   623  	t.putStr("getOwnPropertySymbols", func(r *Runtime) Value {
   624  		return r.methodProp(r.object_getOwnPropertySymbols, "getOwnPropertySymbols", 1)
   625  	})
   626  	t.putStr("create", func(r *Runtime) Value { return r.methodProp(r.object_create, "create", 2) })
   627  	t.putStr("seal", func(r *Runtime) Value { return r.methodProp(r.object_seal, "seal", 1) })
   628  	t.putStr("freeze", func(r *Runtime) Value { return r.methodProp(r.object_freeze, "freeze", 1) })
   629  	t.putStr("preventExtensions", func(r *Runtime) Value { return r.methodProp(r.object_preventExtensions, "preventExtensions", 1) })
   630  	t.putStr("isSealed", func(r *Runtime) Value { return r.methodProp(r.object_isSealed, "isSealed", 1) })
   631  	t.putStr("isFrozen", func(r *Runtime) Value { return r.methodProp(r.object_isFrozen, "isFrozen", 1) })
   632  	t.putStr("isExtensible", func(r *Runtime) Value { return r.methodProp(r.object_isExtensible, "isExtensible", 1) })
   633  	t.putStr("keys", func(r *Runtime) Value { return r.methodProp(r.object_keys, "keys", 1) })
   634  	t.putStr("setPrototypeOf", func(r *Runtime) Value { return r.methodProp(r.object_setPrototypeOf, "setPrototypeOf", 2) })
   635  	t.putStr("values", func(r *Runtime) Value { return r.methodProp(r.object_values, "values", 1) })
   636  	t.putStr("fromEntries", func(r *Runtime) Value { return r.methodProp(r.object_fromEntries, "fromEntries", 1) })
   637  	t.putStr("hasOwn", func(r *Runtime) Value { return r.methodProp(r.object_hasOwn, "hasOwn", 2) })
   638  
   639  	return t
   640  }
   641  
   642  var _objectTemplate *objectTemplate
   643  var objectTemplateOnce sync.Once
   644  
   645  func getObjectTemplate() *objectTemplate {
   646  	objectTemplateOnce.Do(func() {
   647  		_objectTemplate = createObjectTemplate()
   648  	})
   649  	return _objectTemplate
   650  }
   651  
   652  func (r *Runtime) getObject() *Object {
   653  	ret := r.global.Object
   654  	if ret == nil {
   655  		ret = &Object{runtime: r}
   656  		r.global.Object = ret
   657  		r.newTemplatedFuncObject(getObjectTemplate(), ret, func(call FunctionCall) Value {
   658  			return r.builtin_Object(call.Arguments, nil)
   659  		}, r.builtin_Object)
   660  	}
   661  	return ret
   662  }
   663  
   664  /*
   665  func (r *Runtime) getObjectPrototype() *Object {
   666  	ret := r.global.ObjectPrototype
   667  	if ret == nil {
   668  		ret = &Object{runtime: r}
   669  		r.global.ObjectPrototype = ret
   670  		r.newTemplatedObject(getObjectProtoTemplate(), ret)
   671  	}
   672  	return ret
   673  }
   674  */
   675  
   676  var objectProtoTemplate *objectTemplate
   677  var objectProtoTemplateOnce sync.Once
   678  
   679  func getObjectProtoTemplate() *objectTemplate {
   680  	objectProtoTemplateOnce.Do(func() {
   681  		objectProtoTemplate = createObjectProtoTemplate()
   682  	})
   683  	return objectProtoTemplate
   684  }
   685  
   686  func createObjectProtoTemplate() *objectTemplate {
   687  	t := newObjectTemplate()
   688  
   689  	// null prototype
   690  
   691  	t.putStr("constructor", func(r *Runtime) Value { return valueProp(r.getObject(), true, false, true) })
   692  
   693  	t.putStr("toString", func(r *Runtime) Value { return r.methodProp(r.objectproto_toString, "toString", 0) })
   694  	t.putStr("toLocaleString", func(r *Runtime) Value { return r.methodProp(r.objectproto_toLocaleString, "toLocaleString", 0) })
   695  	t.putStr("valueOf", func(r *Runtime) Value { return r.methodProp(r.objectproto_valueOf, "valueOf", 0) })
   696  	t.putStr("hasOwnProperty", func(r *Runtime) Value { return r.methodProp(r.objectproto_hasOwnProperty, "hasOwnProperty", 1) })
   697  	t.putStr("isPrototypeOf", func(r *Runtime) Value { return r.methodProp(r.objectproto_isPrototypeOf, "isPrototypeOf", 1) })
   698  	t.putStr("propertyIsEnumerable", func(r *Runtime) Value {
   699  		return r.methodProp(r.objectproto_propertyIsEnumerable, "propertyIsEnumerable", 1)
   700  	})
   701  	t.putStr(__proto__, func(r *Runtime) Value {
   702  		return &valueProperty{
   703  			accessor:     true,
   704  			getterFunc:   r.newNativeFunc(r.objectproto_getProto, "get __proto__", 0),
   705  			setterFunc:   r.newNativeFunc(r.objectproto_setProto, "set __proto__", 1),
   706  			configurable: true,
   707  		}
   708  	})
   709  
   710  	return t
   711  }
   712  

View as plain text