tor-browser

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

CallAndConstruct.cpp (5855B)


      1 /* -*- Mode.h: 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 "js/CallAndConstruct.h"
      8 
      9 #include "mozilla/Assertions.h"  // MOZ_ASSERT
     10 
     11 #include "jstypes.h"                  // JS_PUBLIC_API
     12 #include "gc/Zone.h"                  // js::Zone
     13 #include "js/Context.h"               // AssertHeapIsIdle
     14 #include "js/friend/ErrorMessages.h"  // JSMSG_*
     15 #include "js/RootingAPI.h"    // JS::Rooted, JS::Handle, JS::MutableHandle
     16 #include "js/Value.h"         // JS::Value, JS::*Value
     17 #include "js/ValueArray.h"    // JS::HandleValueArray
     18 #include "vm/BytecodeUtil.h"  // JSDVG_IGNORE_STACK
     19 #include "vm/Interpreter.h"   // js::Call, js::Construct
     20 #include "vm/JSAtomUtils.h"   // js::Atomize
     21 #include "vm/JSContext.h"     // JSContext, CHECK_THREAD, ReportValueError
     22 #include "vm/JSObject.h"      // JSObject
     23 #include "vm/Stack.h"  // js::InvokeArgs, js::FillArgumentsFromArraylike, js::ConstructArgs
     24 #include "vm/StringType.h"  // JSAtom
     25 
     26 #include "vm/JSAtomUtils-inl.h"       // js::AtomToId
     27 #include "vm/JSContext-inl.h"         // JSContext::check
     28 #include "vm/JSObject-inl.h"          // js::IsConstructor
     29 #include "vm/ObjectOperations-inl.h"  // js::GetProperty
     30 
     31 using namespace js;
     32 
     33 JS_PUBLIC_API bool JS::IsCallable(JSObject* obj) { return obj->isCallable(); }
     34 
     35 JS_PUBLIC_API bool JS::IsConstructor(JSObject* obj) {
     36  return obj->isConstructor();
     37 }
     38 
     39 JS_PUBLIC_API bool JS_CallFunctionValue(JSContext* cx,
     40                                        JS::Handle<JSObject*> obj,
     41                                        JS::Handle<JS::Value> fval,
     42                                        const JS::HandleValueArray& args,
     43                                        JS::MutableHandle<JS::Value> rval) {
     44  MOZ_ASSERT(!cx->zone()->isAtomsZone());
     45  AssertHeapIsIdle();
     46  CHECK_THREAD(cx);
     47  cx->check(obj, fval, args);
     48 
     49  js::InvokeArgs iargs(cx);
     50  if (!FillArgumentsFromArraylike(cx, iargs, args)) {
     51    return false;
     52  }
     53 
     54  JS::Rooted<JS::Value> thisv(cx, JS::ObjectOrNullValue(obj));
     55  return js::Call(cx, fval, thisv, iargs, rval);
     56 }
     57 
     58 JS_PUBLIC_API bool JS_CallFunction(JSContext* cx, JS::Handle<JSObject*> obj,
     59                                   JS::Handle<JSFunction*> fun,
     60                                   const JS::HandleValueArray& args,
     61                                   JS::MutableHandle<JS::Value> rval) {
     62  MOZ_ASSERT(!cx->zone()->isAtomsZone());
     63  AssertHeapIsIdle();
     64  CHECK_THREAD(cx);
     65  cx->check(obj, fun, args);
     66 
     67  js::InvokeArgs iargs(cx);
     68  if (!FillArgumentsFromArraylike(cx, iargs, args)) {
     69    return false;
     70  }
     71 
     72  JS::Rooted<JS::Value> fval(cx, JS::ObjectValue(*fun));
     73  JS::Rooted<JS::Value> thisv(cx, JS::ObjectOrNullValue(obj));
     74  return js::Call(cx, fval, thisv, iargs, rval);
     75 }
     76 
     77 JS_PUBLIC_API bool JS_CallFunctionName(JSContext* cx, JS::Handle<JSObject*> obj,
     78                                       const char* name,
     79                                       const JS::HandleValueArray& args,
     80                                       JS::MutableHandle<JS::Value> rval) {
     81  MOZ_ASSERT(!cx->zone()->isAtomsZone());
     82  AssertHeapIsIdle();
     83  CHECK_THREAD(cx);
     84  cx->check(obj, args);
     85 
     86  JSAtom* atom = Atomize(cx, name, strlen(name));
     87  if (!atom) {
     88    return false;
     89  }
     90 
     91  JS::Rooted<JS::Value> fval(cx);
     92  JS::Rooted<jsid> id(cx, AtomToId(atom));
     93  if (!GetProperty(cx, obj, obj, id, &fval)) {
     94    return false;
     95  }
     96 
     97  js::InvokeArgs iargs(cx);
     98  if (!FillArgumentsFromArraylike(cx, iargs, args)) {
     99    return false;
    100  }
    101 
    102  JS::Rooted<JS::Value> thisv(cx, JS::ObjectOrNullValue(obj));
    103  return js::Call(cx, fval, thisv, iargs, rval);
    104 }
    105 
    106 JS_PUBLIC_API bool JS::Call(JSContext* cx, JS::Handle<JS::Value> thisv,
    107                            JS::Handle<JS::Value> fval,
    108                            const JS::HandleValueArray& args,
    109                            JS::MutableHandle<JS::Value> rval) {
    110  AssertHeapIsIdle();
    111  CHECK_THREAD(cx);
    112  cx->check(thisv, fval, args);
    113 
    114  js::InvokeArgs iargs(cx);
    115  if (!FillArgumentsFromArraylike(cx, iargs, args)) {
    116    return false;
    117  }
    118 
    119  return js::Call(cx, fval, thisv, iargs, rval);
    120 }
    121 
    122 JS_PUBLIC_API bool JS::Construct(JSContext* cx, JS::Handle<JS::Value> fval,
    123                                 JS::Handle<JSObject*> newTarget,
    124                                 const JS::HandleValueArray& args,
    125                                 JS::MutableHandle<JSObject*> objp) {
    126  AssertHeapIsIdle();
    127  CHECK_THREAD(cx);
    128  cx->check(fval, newTarget, args);
    129 
    130  if (!js::IsConstructor(fval)) {
    131    ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, fval,
    132                     nullptr);
    133    return false;
    134  }
    135 
    136  JS::Rooted<JS::Value> newTargetVal(cx, JS::ObjectValue(*newTarget));
    137  if (!js::IsConstructor(newTargetVal)) {
    138    ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK,
    139                     newTargetVal, nullptr);
    140    return false;
    141  }
    142 
    143  js::ConstructArgs cargs(cx);
    144  if (!FillArgumentsFromArraylike(cx, cargs, args)) {
    145    return false;
    146  }
    147 
    148  return js::Construct(cx, fval, cargs, newTargetVal, objp);
    149 }
    150 
    151 JS_PUBLIC_API bool JS::Construct(JSContext* cx, JS::Handle<JS::Value> fval,
    152                                 const JS::HandleValueArray& args,
    153                                 JS::MutableHandle<JSObject*> objp) {
    154  AssertHeapIsIdle();
    155  CHECK_THREAD(cx);
    156  cx->check(fval, args);
    157 
    158  if (!js::IsConstructor(fval)) {
    159    ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, fval,
    160                     nullptr);
    161    return false;
    162  }
    163 
    164  js::ConstructArgs cargs(cx);
    165  if (!FillArgumentsFromArraylike(cx, cargs, args)) {
    166    return false;
    167  }
    168 
    169  return js::Construct(cx, fval, cargs, fval, objp);
    170 }