tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 };