Reflect.cpp (6940B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "builtin/Reflect.h" 8 9 #include "jsapi.h" 10 11 #include "builtin/Object.h" 12 #include "jit/InlinableNatives.h" 13 #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_NOT_EXPECTED_TYPE 14 #include "js/PropertySpec.h" 15 #include "vm/GlobalObject.h" 16 #include "vm/JSContext.h" 17 #include "vm/PlainObject.h" 18 19 #include "vm/GeckoProfiler-inl.h" 20 #include "vm/JSObject-inl.h" 21 #include "vm/ObjectOperations-inl.h" 22 23 using namespace js; 24 25 /*** Reflect methods ********************************************************/ 26 27 /* ES6 26.1.4 Reflect.deleteProperty (target, propertyKey) */ 28 static bool Reflect_deleteProperty(JSContext* cx, unsigned argc, Value* vp) { 29 CallArgs args = CallArgsFromVp(argc, vp); 30 31 // Step 1. 32 RootedObject target( 33 cx, 34 RequireObjectArg(cx, "`target`", "Reflect.deleteProperty", args.get(0))); 35 if (!target) { 36 return false; 37 } 38 39 // Steps 2-3. 40 RootedValue propertyKey(cx, args.get(1)); 41 RootedId key(cx); 42 if (!ToPropertyKey(cx, propertyKey, &key)) { 43 return false; 44 } 45 46 // Step 4. 47 ObjectOpResult result; 48 if (!DeleteProperty(cx, target, key, result)) { 49 return false; 50 } 51 args.rval().setBoolean(result.ok()); 52 return true; 53 } 54 55 /* ES6 26.1.8 Reflect.getPrototypeOf(target) */ 56 bool js::Reflect_getPrototypeOf(JSContext* cx, unsigned argc, Value* vp) { 57 CallArgs args = CallArgsFromVp(argc, vp); 58 59 // Step 1. 60 RootedObject target( 61 cx, 62 RequireObjectArg(cx, "`target`", "Reflect.getPrototypeOf", args.get(0))); 63 if (!target) { 64 return false; 65 } 66 67 // Step 2. 68 RootedObject proto(cx); 69 if (!GetPrototype(cx, target, &proto)) { 70 return false; 71 } 72 args.rval().setObjectOrNull(proto); 73 return true; 74 } 75 76 /* ES6 draft 26.1.10 Reflect.isExtensible(target) */ 77 bool js::Reflect_isExtensible(JSContext* cx, unsigned argc, Value* vp) { 78 CallArgs args = CallArgsFromVp(argc, vp); 79 80 // Step 1. 81 RootedObject target( 82 cx, 83 RequireObjectArg(cx, "`target`", "Reflect.isExtensible", args.get(0))); 84 if (!target) { 85 return false; 86 } 87 88 // Step 2. 89 bool extensible; 90 if (!IsExtensible(cx, target, &extensible)) { 91 return false; 92 } 93 args.rval().setBoolean(extensible); 94 return true; 95 } 96 97 // ES2018 draft rev c164be80f7ea91de5526b33d54e5c9321ed03d3f 98 // 26.1.10 Reflect.ownKeys ( target ) 99 bool js::Reflect_ownKeys(JSContext* cx, unsigned argc, Value* vp) { 100 AutoJSMethodProfilerEntry pseudoFrame(cx, "Reflect", "ownKeys"); 101 CallArgs args = CallArgsFromVp(argc, vp); 102 103 // Step 1. 104 RootedObject target( 105 cx, RequireObjectArg(cx, "`target`", "Reflect.ownKeys", args.get(0))); 106 if (!target) { 107 return false; 108 } 109 110 // Steps 2-3. 111 return GetOwnPropertyKeys( 112 cx, target, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, args.rval()); 113 } 114 115 /* ES6 26.1.12 Reflect.preventExtensions(target) */ 116 static bool Reflect_preventExtensions(JSContext* cx, unsigned argc, Value* vp) { 117 CallArgs args = CallArgsFromVp(argc, vp); 118 119 // Step 1. 120 RootedObject target( 121 cx, RequireObjectArg(cx, "`target`", "Reflect.preventExtensions", 122 args.get(0))); 123 if (!target) { 124 return false; 125 } 126 127 // Step 2. 128 ObjectOpResult result; 129 if (!PreventExtensions(cx, target, result)) { 130 return false; 131 } 132 args.rval().setBoolean(result.ok()); 133 return true; 134 } 135 136 /* ES6 26.1.13 Reflect.set(target, propertyKey, V [, receiver]) */ 137 static bool Reflect_set(JSContext* cx, unsigned argc, Value* vp) { 138 CallArgs args = CallArgsFromVp(argc, vp); 139 140 // Step 1. 141 RootedObject target( 142 cx, RequireObjectArg(cx, "`target`", "Reflect.set", args.get(0))); 143 if (!target) { 144 return false; 145 } 146 147 // Steps 2-3. 148 RootedValue propertyKey(cx, args.get(1)); 149 RootedId key(cx); 150 if (!ToPropertyKey(cx, propertyKey, &key)) { 151 return false; 152 } 153 154 // Step 4. 155 RootedValue receiver(cx, args.length() > 3 ? args[3] : args.get(0)); 156 157 // Step 5. 158 ObjectOpResult result; 159 RootedValue value(cx, args.get(2)); 160 if (!SetProperty(cx, target, key, value, receiver, result)) { 161 return false; 162 } 163 args.rval().setBoolean(result.ok()); 164 return true; 165 } 166 167 /* 168 * ES6 26.1.3 Reflect.setPrototypeOf(target, proto) 169 * 170 * The specification is not quite similar enough to Object.setPrototypeOf to 171 * share code. 172 */ 173 static bool Reflect_setPrototypeOf(JSContext* cx, unsigned argc, Value* vp) { 174 CallArgs args = CallArgsFromVp(argc, vp); 175 176 // Step 1. 177 RootedObject obj(cx, RequireObjectArg(cx, "`target`", 178 "Reflect.setPrototypeOf", args.get(0))); 179 if (!obj) { 180 return false; 181 } 182 183 // Step 2. 184 if (!args.get(1).isObjectOrNull()) { 185 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 186 JSMSG_NOT_EXPECTED_TYPE, "Reflect.setPrototypeOf", 187 "an object or null", 188 InformalValueTypeName(args.get(1))); 189 return false; 190 } 191 RootedObject proto(cx, args.get(1).toObjectOrNull()); 192 193 // Step 4. 194 ObjectOpResult result; 195 if (!SetPrototype(cx, obj, proto, result)) { 196 return false; 197 } 198 args.rval().setBoolean(result.ok()); 199 return true; 200 } 201 202 static const JSFunctionSpec reflect_methods[] = { 203 JS_SELF_HOSTED_FN("apply", "Reflect_apply", 3, 0), 204 JS_SELF_HOSTED_FN("construct", "Reflect_construct", 2, 0), 205 JS_SELF_HOSTED_FN("defineProperty", "Reflect_defineProperty", 3, 0), 206 JS_FN("deleteProperty", Reflect_deleteProperty, 2, 0), 207 JS_SELF_HOSTED_FN("get", "Reflect_get", 2, 0), 208 JS_SELF_HOSTED_FN("getOwnPropertyDescriptor", 209 "Reflect_getOwnPropertyDescriptor", 2, 0), 210 JS_INLINABLE_FN("getPrototypeOf", Reflect_getPrototypeOf, 1, 0, 211 ReflectGetPrototypeOf), 212 JS_SELF_HOSTED_FN("has", "Reflect_has", 2, 0), 213 JS_FN("isExtensible", Reflect_isExtensible, 1, 0), 214 JS_FN("ownKeys", Reflect_ownKeys, 1, 0), 215 JS_FN("preventExtensions", Reflect_preventExtensions, 1, 0), 216 JS_FN("set", Reflect_set, 3, 0), 217 JS_FN("setPrototypeOf", Reflect_setPrototypeOf, 2, 0), 218 JS_FS_END, 219 }; 220 221 static const JSPropertySpec reflect_properties[] = { 222 JS_STRING_SYM_PS(toStringTag, "Reflect", JSPROP_READONLY), 223 JS_PS_END, 224 }; 225 226 /*** Setup ******************************************************************/ 227 228 static JSObject* CreateReflectObject(JSContext* cx, JSProtoKey key) { 229 RootedObject proto(cx, &cx->global()->getObjectPrototype()); 230 return NewPlainObjectWithProto(cx, proto, TenuredObject); 231 } 232 233 static const ClassSpec ReflectClassSpec = { 234 CreateReflectObject, 235 nullptr, 236 reflect_methods, 237 reflect_properties, 238 }; 239 240 const JSClass js::ReflectClass = { 241 "Reflect", 242 0, 243 JS_NULL_CLASS_OPS, 244 &ReflectClassSpec, 245 };