tor-browser

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

HandlerFunction-inl.h (3893B)


      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 /*
      8 * Handler for operations that act on a target object, and possibly upon
      9 * an extra value.
     10 */
     11 
     12 #ifndef builtin_HandlerFunction_inl_h
     13 #define builtin_HandlerFunction_inl_h
     14 
     15 #include <stddef.h>  // size_t
     16 
     17 #include "gc/AllocKind.h"   // js::gc::AllocKind
     18 #include "js/CallArgs.h"    // JS::CallArgs
     19 #include "js/RootingAPI.h"  // JS::Handle
     20 #include "js/Value.h"       // JS::ObjectValue
     21 #include "vm/JSContext.h"   // JSContext
     22 #include "vm/JSFunction.h"  // JSFunction, js::Native, js::NewNativeFunction
     23 #include "vm/JSObject.h"    // JSObject, js::GenericObject
     24 #include "vm/StringType.h"  // js::PropertyName
     25 
     26 #include "vm/JSContext-inl.h"  // JSContext::check
     27 
     28 namespace js {
     29 
     30 // Handler functions are extended functions, that close over a target object and
     31 // (optionally) over an extra object, storing those objects in the function's
     32 // extended slots.
     33 constexpr size_t HandlerFunctionSlot_Target = 0;
     34 constexpr size_t HandlerFunctionSlot_Extra = 1;
     35 
     36 static_assert(HandlerFunctionSlot_Extra < FunctionExtended::NUM_EXTENDED_SLOTS,
     37              "handler function slots shouldn't exceed available extended "
     38              "slots");
     39 
     40 [[nodiscard]] inline JSFunction* NewHandler(JSContext* cx, Native handler,
     41                                            JS::Handle<JSObject*> target) {
     42  cx->check(target);
     43 
     44  JS::Handle<PropertyName*> funName = cx->names().empty_;
     45  JSFunction* handlerFun = NewNativeFunction(
     46      cx, handler, 0, funName, gc::AllocKind::FUNCTION_EXTENDED, GenericObject);
     47  if (!handlerFun) {
     48    return nullptr;
     49  }
     50  handlerFun->setExtendedSlot(HandlerFunctionSlot_Target,
     51                              JS::ObjectValue(*target));
     52  return handlerFun;
     53 }
     54 
     55 [[nodiscard]] inline JSFunction* NewHandlerWithExtra(
     56    JSContext* cx, Native handler, JS::Handle<JSObject*> target,
     57    JS::Handle<JSObject*> extra) {
     58  cx->check(extra);
     59  JSFunction* handlerFun = NewHandler(cx, handler, target);
     60  if (handlerFun) {
     61    handlerFun->setExtendedSlot(HandlerFunctionSlot_Extra,
     62                                JS::ObjectValue(*extra));
     63  }
     64  return handlerFun;
     65 }
     66 
     67 [[nodiscard]] inline JSFunction* NewHandlerWithExtraValue(
     68    JSContext* cx, Native handler, JS::Handle<JSObject*> target,
     69    JS::Handle<JS::Value> extra) {
     70  cx->check(extra);
     71  JSFunction* handlerFun = NewHandler(cx, handler, target);
     72  if (handlerFun) {
     73    handlerFun->setExtendedSlot(HandlerFunctionSlot_Extra, extra);
     74  }
     75  return handlerFun;
     76 }
     77 
     78 /**
     79 * Within the call of a handler function that "closes over" a target value that
     80 * is always a |T*| object (and never a wrapper around one), return that |T*|.
     81 */
     82 template <class T>
     83 [[nodiscard]] inline T* TargetFromHandler(const JS::CallArgs& args) {
     84  JSFunction& func = args.callee().as<JSFunction>();
     85  return &func.getExtendedSlot(HandlerFunctionSlot_Target).toObject().as<T>();
     86 }
     87 
     88 /**
     89 * Within the call of a handler function that "closes over" a target value and
     90 * an extra value, return that extra value.
     91 */
     92 [[nodiscard]] inline JS::Value ExtraValueFromHandler(const JS::CallArgs& args) {
     93  JSFunction& func = args.callee().as<JSFunction>();
     94  return func.getExtendedSlot(HandlerFunctionSlot_Extra);
     95 }
     96 
     97 /**
     98 * Within the call of a handler function that "closes over" a target value and
     99 * an extra value, where that extra value is always a |T*| object (and never a
    100 * wrapper around one), return that |T*|.
    101 */
    102 template <class T>
    103 [[nodiscard]] inline T* ExtraFromHandler(const JS::CallArgs& args) {
    104  return &ExtraValueFromHandler(args).toObject().as<T>();
    105 }
    106 
    107 }  // namespace js
    108 
    109 #endif  // builtin_HandlerFunction_inl_h