1from __future__ import unicode_literals 2from ..conversions import * 3from ..func_utils import * 4from ..base import is_data_descriptor 5import six 6 7 8def Object(this, args): 9 val = get_arg(args, 0) 10 if is_null(val) or is_undefined(val): 11 return args.space.NewObject() 12 return to_object(val, args.space) 13 14 15def ObjectCreate(args, space): 16 if len(args): 17 val = get_arg(args, 0) 18 if is_object(val): 19 # Implementation dependent, but my will simply return :) 20 return val 21 elif type(val) in (NUMBER_TYPE, STRING_TYPE, BOOLEAN_TYPE): 22 return to_object(val, space) 23 return space.NewObject() 24 25 26class ObjectMethods: 27 def getPrototypeOf(this, args): 28 obj = get_arg(args, 0) 29 if not is_object(obj): 30 raise MakeError('TypeError', 31 'Object.getPrototypeOf called on non-object') 32 return null if obj.prototype is None else obj.prototype 33 34 def getOwnPropertyDescriptor(this, args): 35 obj = get_arg(args, 0) 36 prop = get_arg(args, 1) 37 if not is_object(obj): 38 raise MakeError( 39 'TypeError', 40 'Object.getOwnPropertyDescriptor called on non-object') 41 desc = obj.own.get(to_string(prop)) 42 return convert_to_js_type(desc, args.space) 43 44 def getOwnPropertyNames(this, args): 45 obj = get_arg(args, 0) 46 if not is_object(obj): 47 raise MakeError( 48 'TypeError', 49 'Object.getOwnPropertyDescriptor called on non-object') 50 return args.space.ConstructArray(obj.own.keys()) 51 52 def create(this, args): 53 obj = get_arg(args, 0) 54 if not (is_object(obj) or is_null(obj)): 55 raise MakeError('TypeError', 56 'Object prototype may only be an Object or null') 57 temp = args.space.NewObject() 58 temp.prototype = None if is_null(obj) else obj 59 if len(args) > 1 and not is_undefined(args[1]): 60 if six.PY2: 61 args.tup = (args[1], ) 62 ObjectMethods.defineProperties.__func__(temp, args) 63 else: 64 args.tup = (args[1], ) 65 ObjectMethods.defineProperties(temp, args) 66 return temp 67 68 def defineProperty(this, args): 69 obj = get_arg(args, 0) 70 prop = get_arg(args, 1) 71 attrs = get_arg(args, 2) 72 if not is_object(obj): 73 raise MakeError('TypeError', 74 'Object.defineProperty called on non-object') 75 name = to_string(prop) 76 if not obj.define_own_property(name, ToPropertyDescriptor(attrs), 77 False): 78 raise MakeError('TypeError', 'Cannot redefine property: %s' % name) 79 return obj 80 81 def defineProperties(this, args): 82 obj = get_arg(args, 0) 83 properties = get_arg(args, 1) 84 if not is_object(obj): 85 raise MakeError('TypeError', 86 'Object.defineProperties called on non-object') 87 props = to_object(properties, args.space) 88 for k, v in props.own.items(): 89 if not v.get('enumerable'): 90 continue 91 desc = ToPropertyDescriptor(props.get(unicode(k))) 92 if not obj.define_own_property(unicode(k), desc, False): 93 raise MakeError('TypeError', 94 'Failed to define own property: %s' % k) 95 return obj 96 97 def seal(this, args): 98 obj = get_arg(args, 0) 99 if not is_object(obj): 100 raise MakeError('TypeError', 'Object.seal called on non-object') 101 for desc in obj.own.values(): 102 desc['configurable'] = False 103 obj.extensible = False 104 return obj 105 106 def freeze(this, args): 107 obj = get_arg(args, 0) 108 if not is_object(obj): 109 raise MakeError('TypeError', 'Object.freeze called on non-object') 110 for desc in obj.own.values(): 111 desc['configurable'] = False 112 if is_data_descriptor(desc): 113 desc['writable'] = False 114 obj.extensible = False 115 return obj 116 117 def preventExtensions(this, args): 118 obj = get_arg(args, 0) 119 if not is_object(obj): 120 raise MakeError('TypeError', 121 'Object.preventExtensions on non-object') 122 obj.extensible = False 123 return obj 124 125 def isSealed(this, args): 126 obj = get_arg(args, 0) 127 if not is_object(obj): 128 raise MakeError('TypeError', 129 'Object.isSealed called on non-object') 130 if obj.extensible: 131 return False 132 for desc in obj.own.values(): 133 if desc.get('configurable'): 134 return False 135 return True 136 137 def isFrozen(this, args): 138 obj = get_arg(args, 0) 139 if not is_object(obj): 140 raise MakeError('TypeError', 141 'Object.isFrozen called on non-object') 142 if obj.extensible: 143 return False 144 for desc in obj.own.values(): 145 if desc.get('configurable'): 146 return False 147 if is_data_descriptor(desc) and desc.get('writable'): 148 return False 149 return True 150 151 def isExtensible(this, args): 152 obj = get_arg(args, 0) 153 if not is_object(obj): 154 raise MakeError('TypeError', 155 'Object.isExtensible called on non-object') 156 return obj.extensible 157 158 def keys(this, args): 159 obj = get_arg(args, 0) 160 if not is_object(obj): 161 raise MakeError('TypeError', 'Object.keys called on non-object') 162 return args.space.ConstructArray([ 163 unicode(e) for e, d in six.iteritems(obj.own) 164 if d.get('enumerable') 165 ]) 166 167 168# some utility functions: 169 170 171def ToPropertyDescriptor(obj): # page 38 (50 absolute) 172 if not is_object(obj): 173 raise MakeError('TypeError', 174 'Can\'t convert non-object to property descriptor') 175 desc = {} 176 if obj.has_property('enumerable'): 177 desc['enumerable'] = to_boolean(obj.get('enumerable')) 178 if obj.has_property('configurable'): 179 desc['configurable'] = to_boolean(obj.get('configurable')) 180 if obj.has_property('value'): 181 desc['value'] = obj.get('value') 182 if obj.has_property('writable'): 183 desc['writable'] = to_boolean(obj.get('writable')) 184 if obj.has_property('get'): 185 cand = obj.get('get') 186 if not (is_undefined(cand) or is_callable(cand)): 187 raise MakeError( 188 'TypeError', 189 'Invalid getter (it has to be a function or undefined)') 190 desc['get'] = cand 191 if obj.has_property('set'): 192 cand = obj.get('set') 193 if not (is_undefined(cand) or is_callable(cand)): 194 raise MakeError( 195 'TypeError', 196 'Invalid setter (it has to be a function or undefined)') 197 desc['set'] = cand 198 if ('get' in desc or 'set' in desc) and ('value' in desc 199 or 'writable' in desc): 200 raise MakeError( 201 'TypeError', 202 'Invalid property. A property cannot both have accessors and be writable or have a value.' 203 ) 204 return desc 205