1 // Copyright 2016 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/builtins/builtins.h" 6 #include "src/builtins/builtins-utils.h" 7 8 #include "src/counters.h" 9 #include "src/keys.h" 10 #include "src/lookup.h" 11 #include "src/objects-inl.h" 12 #include "src/property-descriptor.h" 13 14 namespace v8 { 15 namespace internal { 16 17 // ----------------------------------------------------------------------------- 18 // ES6 section 26.1 The Reflect Object 19 20 // ES6 section 26.1.3 Reflect.defineProperty 21 BUILTIN(ReflectDefineProperty) { 22 HandleScope scope(isolate); 23 DCHECK_EQ(4, args.length()); 24 Handle<Object> target = args.at(1); 25 Handle<Object> key = args.at(2); 26 Handle<Object> attributes = args.at(3); 27 28 if (!target->IsJSReceiver()) { 29 THROW_NEW_ERROR_RETURN_FAILURE( 30 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 31 isolate->factory()->NewStringFromAsciiChecked( 32 "Reflect.defineProperty"))); 33 } 34 35 Handle<Name> name; 36 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, 37 Object::ToName(isolate, key)); 38 39 PropertyDescriptor desc; 40 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) { 41 return isolate->heap()->exception(); 42 } 43 44 Maybe<bool> result = 45 JSReceiver::DefineOwnProperty(isolate, Handle<JSReceiver>::cast(target), 46 name, &desc, Object::DONT_THROW); 47 MAYBE_RETURN(result, isolate->heap()->exception()); 48 return *isolate->factory()->ToBoolean(result.FromJust()); 49 } 50 51 // ES6 section 26.1.4 Reflect.deleteProperty 52 BUILTIN(ReflectDeleteProperty) { 53 HandleScope scope(isolate); 54 DCHECK_EQ(3, args.length()); 55 Handle<Object> target = args.at(1); 56 Handle<Object> key = args.at(2); 57 58 if (!target->IsJSReceiver()) { 59 THROW_NEW_ERROR_RETURN_FAILURE( 60 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 61 isolate->factory()->NewStringFromAsciiChecked( 62 "Reflect.deleteProperty"))); 63 } 64 65 Handle<Name> name; 66 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, 67 Object::ToName(isolate, key)); 68 69 Maybe<bool> result = JSReceiver::DeletePropertyOrElement( 70 Handle<JSReceiver>::cast(target), name, SLOPPY); 71 MAYBE_RETURN(result, isolate->heap()->exception()); 72 return *isolate->factory()->ToBoolean(result.FromJust()); 73 } 74 75 // ES6 section 26.1.6 Reflect.get 76 BUILTIN(ReflectGet) { 77 HandleScope scope(isolate); 78 Handle<Object> target = args.atOrUndefined(isolate, 1); 79 Handle<Object> key = args.atOrUndefined(isolate, 2); 80 Handle<Object> receiver = args.length() > 3 ? args.at(3) : target; 81 82 if (!target->IsJSReceiver()) { 83 THROW_NEW_ERROR_RETURN_FAILURE( 84 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 85 isolate->factory()->NewStringFromAsciiChecked( 86 "Reflect.get"))); 87 } 88 89 Handle<Name> name; 90 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, 91 Object::ToName(isolate, key)); 92 93 RETURN_RESULT_OR_FAILURE( 94 isolate, Object::GetPropertyOrElement(receiver, name, 95 Handle<JSReceiver>::cast(target))); 96 } 97 98 // ES6 section 26.1.7 Reflect.getOwnPropertyDescriptor 99 BUILTIN(ReflectGetOwnPropertyDescriptor) { 100 HandleScope scope(isolate); 101 DCHECK_EQ(3, args.length()); 102 Handle<Object> target = args.at(1); 103 Handle<Object> key = args.at(2); 104 105 if (!target->IsJSReceiver()) { 106 THROW_NEW_ERROR_RETURN_FAILURE( 107 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 108 isolate->factory()->NewStringFromAsciiChecked( 109 "Reflect.getOwnPropertyDescriptor"))); 110 } 111 112 Handle<Name> name; 113 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, 114 Object::ToName(isolate, key)); 115 116 PropertyDescriptor desc; 117 Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor( 118 isolate, Handle<JSReceiver>::cast(target), name, &desc); 119 MAYBE_RETURN(found, isolate->heap()->exception()); 120 if (!found.FromJust()) return isolate->heap()->undefined_value(); 121 return *desc.ToObject(isolate); 122 } 123 124 // ES6 section 26.1.8 Reflect.getPrototypeOf 125 BUILTIN(ReflectGetPrototypeOf) { 126 HandleScope scope(isolate); 127 DCHECK_EQ(2, args.length()); 128 Handle<Object> target = args.at(1); 129 130 if (!target->IsJSReceiver()) { 131 THROW_NEW_ERROR_RETURN_FAILURE( 132 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 133 isolate->factory()->NewStringFromAsciiChecked( 134 "Reflect.getPrototypeOf"))); 135 } 136 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(target); 137 RETURN_RESULT_OR_FAILURE(isolate, 138 JSReceiver::GetPrototype(isolate, receiver)); 139 } 140 141 // ES6 section 26.1.9 Reflect.has 142 BUILTIN(ReflectHas) { 143 HandleScope scope(isolate); 144 DCHECK_EQ(3, args.length()); 145 Handle<Object> target = args.at(1); 146 Handle<Object> key = args.at(2); 147 148 if (!target->IsJSReceiver()) { 149 THROW_NEW_ERROR_RETURN_FAILURE( 150 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 151 isolate->factory()->NewStringFromAsciiChecked( 152 "Reflect.has"))); 153 } 154 155 Handle<Name> name; 156 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, 157 Object::ToName(isolate, key)); 158 159 Maybe<bool> result = 160 JSReceiver::HasProperty(Handle<JSReceiver>::cast(target), name); 161 return result.IsJust() ? *isolate->factory()->ToBoolean(result.FromJust()) 162 : isolate->heap()->exception(); 163 } 164 165 // ES6 section 26.1.10 Reflect.isExtensible 166 BUILTIN(ReflectIsExtensible) { 167 HandleScope scope(isolate); 168 DCHECK_EQ(2, args.length()); 169 Handle<Object> target = args.at(1); 170 171 if (!target->IsJSReceiver()) { 172 THROW_NEW_ERROR_RETURN_FAILURE( 173 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 174 isolate->factory()->NewStringFromAsciiChecked( 175 "Reflect.isExtensible"))); 176 } 177 178 Maybe<bool> result = 179 JSReceiver::IsExtensible(Handle<JSReceiver>::cast(target)); 180 MAYBE_RETURN(result, isolate->heap()->exception()); 181 return *isolate->factory()->ToBoolean(result.FromJust()); 182 } 183 184 // ES6 section 26.1.11 Reflect.ownKeys 185 BUILTIN(ReflectOwnKeys) { 186 HandleScope scope(isolate); 187 DCHECK_EQ(2, args.length()); 188 Handle<Object> target = args.at(1); 189 190 if (!target->IsJSReceiver()) { 191 THROW_NEW_ERROR_RETURN_FAILURE( 192 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 193 isolate->factory()->NewStringFromAsciiChecked( 194 "Reflect.ownKeys"))); 195 } 196 197 Handle<FixedArray> keys; 198 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 199 isolate, keys, 200 KeyAccumulator::GetKeys(Handle<JSReceiver>::cast(target), 201 KeyCollectionMode::kOwnOnly, ALL_PROPERTIES, 202 GetKeysConversion::kConvertToString)); 203 return *isolate->factory()->NewJSArrayWithElements(keys); 204 } 205 206 // ES6 section 26.1.12 Reflect.preventExtensions 207 BUILTIN(ReflectPreventExtensions) { 208 HandleScope scope(isolate); 209 DCHECK_EQ(2, args.length()); 210 Handle<Object> target = args.at(1); 211 212 if (!target->IsJSReceiver()) { 213 THROW_NEW_ERROR_RETURN_FAILURE( 214 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 215 isolate->factory()->NewStringFromAsciiChecked( 216 "Reflect.preventExtensions"))); 217 } 218 219 Maybe<bool> result = JSReceiver::PreventExtensions( 220 Handle<JSReceiver>::cast(target), Object::DONT_THROW); 221 MAYBE_RETURN(result, isolate->heap()->exception()); 222 return *isolate->factory()->ToBoolean(result.FromJust()); 223 } 224 225 // ES6 section 26.1.13 Reflect.set 226 BUILTIN(ReflectSet) { 227 HandleScope scope(isolate); 228 Handle<Object> target = args.atOrUndefined(isolate, 1); 229 Handle<Object> key = args.atOrUndefined(isolate, 2); 230 Handle<Object> value = args.atOrUndefined(isolate, 3); 231 Handle<Object> receiver = args.length() > 4 ? args.at(4) : target; 232 233 if (!target->IsJSReceiver()) { 234 THROW_NEW_ERROR_RETURN_FAILURE( 235 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 236 isolate->factory()->NewStringFromAsciiChecked( 237 "Reflect.set"))); 238 } 239 240 Handle<Name> name; 241 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, 242 Object::ToName(isolate, key)); 243 244 LookupIterator it = LookupIterator::PropertyOrElement( 245 isolate, receiver, name, Handle<JSReceiver>::cast(target)); 246 Maybe<bool> result = Object::SetSuperProperty( 247 &it, value, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED); 248 MAYBE_RETURN(result, isolate->heap()->exception()); 249 return *isolate->factory()->ToBoolean(result.FromJust()); 250 } 251 252 // ES6 section 26.1.14 Reflect.setPrototypeOf 253 BUILTIN(ReflectSetPrototypeOf) { 254 HandleScope scope(isolate); 255 DCHECK_EQ(3, args.length()); 256 Handle<Object> target = args.at(1); 257 Handle<Object> proto = args.at(2); 258 259 if (!target->IsJSReceiver()) { 260 THROW_NEW_ERROR_RETURN_FAILURE( 261 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, 262 isolate->factory()->NewStringFromAsciiChecked( 263 "Reflect.setPrototypeOf"))); 264 } 265 266 if (!proto->IsJSReceiver() && !proto->IsNull(isolate)) { 267 THROW_NEW_ERROR_RETURN_FAILURE( 268 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto)); 269 } 270 271 Maybe<bool> result = JSReceiver::SetPrototype( 272 Handle<JSReceiver>::cast(target), proto, true, Object::DONT_THROW); 273 MAYBE_RETURN(result, isolate->heap()->exception()); 274 return *isolate->factory()->ToBoolean(result.FromJust()); 275 } 276 277 } // namespace internal 278 } // namespace v8 279