tor-browser

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

nsJSUtils.cpp (6125B)


      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 * This is not a generated file. It contains common utility functions
      9 * invoked from the JavaScript code generated from IDL interfaces.
     10 * The goal of the utility functions is to cut down on the size of
     11 * the generated code itself.
     12 */
     13 
     14 #include "nsJSUtils.h"
     15 
     16 #include <utility>
     17 
     18 #include "MainThreadUtils.h"
     19 #include "js/ArrayBuffer.h"
     20 #include "js/ComparisonOperators.h"
     21 #include "js/CompilationAndEvaluation.h"
     22 #include "js/CompileOptions.h"
     23 #include "js/Date.h"
     24 #include "js/EnvironmentChain.h"
     25 #include "js/GCVector.h"
     26 #include "js/HeapAPI.h"
     27 #include "js/Modules.h"
     28 #include "js/RootingAPI.h"
     29 #include "js/SourceText.h"
     30 #include "js/TypeDecls.h"
     31 #include "js/experimental/TypedData.h"
     32 #include "jsfriendapi.h"
     33 #include "mozilla/CycleCollectedJSContext.h"
     34 #include "mozilla/ProfilerLabels.h"
     35 #include "mozilla/dom/BindingUtils.h"
     36 #include "mozilla/dom/Element.h"
     37 #include "mozilla/dom/ScriptSettings.h"
     38 #include "nsContentUtils.h"
     39 #include "nsDebug.h"
     40 #include "nsGlobalWindowInner.h"
     41 #include "nsINode.h"
     42 #include "nsString.h"
     43 #include "nsTPromiseFlatString.h"
     44 #include "nscore.h"
     45 #include "prenv.h"
     46 
     47 #if !defined(DEBUG) && !defined(MOZ_ENABLE_JS_DUMP)
     48 #  include "mozilla/StaticPrefs_browser.h"
     49 #endif
     50 
     51 using namespace mozilla;
     52 using namespace mozilla::dom;
     53 
     54 uint64_t nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(JSContext* aContext) {
     55  if (!aContext) return 0;
     56 
     57  nsGlobalWindowInner* win = xpc::CurrentWindowOrNull(aContext);
     58  return win ? win->WindowID() : 0;
     59 }
     60 
     61 nsresult nsJSUtils::UpdateFunctionDebugMetadata(
     62    AutoJSAPI& jsapi, JS::Handle<JSObject*> aFun, JS::CompileOptions& aOptions,
     63    JS::Handle<JSString*> aElementAttributeName,
     64    JS::Handle<JS::Value> aPrivateValue) {
     65  JSContext* cx = jsapi.cx();
     66 
     67  JS::Rooted<JSFunction*> fun(cx, JS_GetObjectFunction(aFun));
     68  if (!fun) {
     69    return NS_ERROR_FAILURE;
     70  }
     71 
     72  JS::Rooted<JSScript*> script(cx, JS_GetFunctionScript(cx, fun));
     73  if (!script) {
     74    return NS_OK;
     75  }
     76 
     77  JS::InstantiateOptions instantiateOptions(aOptions);
     78  if (!JS::UpdateDebugMetadata(cx, script, instantiateOptions, aPrivateValue,
     79                               aElementAttributeName, nullptr, nullptr)) {
     80    return NS_ERROR_FAILURE;
     81  }
     82  return NS_OK;
     83 }
     84 
     85 nsresult nsJSUtils::CompileFunction(AutoJSAPI& jsapi,
     86                                    const JS::EnvironmentChain& aEnvChain,
     87                                    JS::CompileOptions& aOptions,
     88                                    const nsACString& aName, uint32_t aArgCount,
     89                                    const char** aArgArray,
     90                                    const nsAString& aBody,
     91                                    JSObject** aFunctionObject) {
     92  JSContext* cx = jsapi.cx();
     93  MOZ_ASSERT(js::GetContextRealm(cx));
     94  MOZ_ASSERT_IF(aEnvChain.length() != 0,
     95                js::IsObjectInContextCompartment(aEnvChain.chain()[0], cx));
     96 
     97  // Do the junk Gecko is supposed to do before calling into JSAPI.
     98  for (size_t i = 0; i < aEnvChain.length(); ++i) {
     99    JS::ExposeObjectToActiveJS(aEnvChain.chain()[i]);
    100  }
    101 
    102  // Compile.
    103  const nsPromiseFlatString& flatBody = PromiseFlatString(aBody);
    104 
    105  JS::SourceText<char16_t> source;
    106  if (!source.init(cx, flatBody.get(), flatBody.Length(),
    107                   JS::SourceOwnership::Borrowed)) {
    108    return NS_ERROR_FAILURE;
    109  }
    110 
    111  JS::Rooted<JSFunction*> fun(
    112      cx, JS::CompileFunction(cx, aEnvChain, aOptions,
    113                              PromiseFlatCString(aName).get(), aArgCount,
    114                              aArgArray, source));
    115  if (!fun) {
    116    return NS_ERROR_FAILURE;
    117  }
    118 
    119  *aFunctionObject = JS_GetFunctionObject(fun);
    120  return NS_OK;
    121 }
    122 
    123 /* static */
    124 bool nsJSUtils::IsScriptable(JS::Handle<JSObject*> aEvaluationGlobal) {
    125  return xpc::Scriptability::AllowedIfExists(aEvaluationGlobal);
    126 }
    127 
    128 static bool AddEnvChainItem(JSContext* aCx, nsINode* aNode,
    129                            JS::EnvironmentChain& aEnvChain) {
    130  JS::Rooted<JS::Value> val(aCx);
    131  if (!GetOrCreateDOMReflector(aCx, aNode, &val)) {
    132    return false;
    133  }
    134 
    135  if (!aEnvChain.append(&val.toObject())) {
    136    return false;
    137  }
    138 
    139  return true;
    140 }
    141 
    142 /* static */
    143 bool nsJSUtils::GetEnvironmentChainForElement(JSContext* aCx, Element* aElement,
    144                                              JS::EnvironmentChain& aEnvChain) {
    145  for (nsINode* cur = aElement; cur; cur = cur->GetScopeChainParent()) {
    146    if (!AddEnvChainItem(aCx, cur, aEnvChain)) {
    147      return false;
    148    }
    149  }
    150 
    151  return true;
    152 }
    153 
    154 /* static */
    155 void nsJSUtils::ResetTimeZone() { JS::ResetTimeZone(); }
    156 
    157 /* static */
    158 bool nsJSUtils::DumpEnabled() {
    159 #ifdef FUZZING
    160  static bool mozFuzzDebug = !!PR_GetEnv("MOZ_FUZZ_DEBUG");
    161  return mozFuzzDebug;
    162 #endif
    163 
    164 #if defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP)
    165  return true;
    166 #else
    167  return StaticPrefs::browser_dom_window_dump_enabled();
    168 #endif
    169 }
    170 
    171 JSObject* nsJSUtils::MoveBufferAsUint8Array(
    172    JSContext* aCx, size_t aSize,
    173    UniquePtr<uint8_t[], JS::FreePolicy> aBuffer) {
    174  JS::Rooted<JSObject*> arrayBuffer(
    175      aCx, JS::NewArrayBufferWithContents(aCx, aSize, std::move(aBuffer)));
    176  if (!arrayBuffer) {
    177    return nullptr;
    178  }
    179 
    180  return JS_NewUint8ArrayWithBuffer(aCx, arrayBuffer, 0,
    181                                    static_cast<int64_t>(aSize));
    182 }
    183 
    184 //
    185 // nsDOMJSUtils.h
    186 //
    187 
    188 template <typename T>
    189 bool nsTAutoJSString<T>::init(const JS::Value& v) {
    190  // Note: it's okay to use danger::GetJSContext here instead of AutoJSAPI,
    191  // because the init() call below is careful not to run script (for instance,
    192  // it only calls JS::ToString for non-object values).
    193  JSContext* cx = danger::GetJSContext();
    194  if (!init(cx, v)) {
    195    JS_ClearPendingException(cx);
    196    return false;
    197  }
    198  return true;
    199 }
    200 
    201 template bool nsTAutoJSString<char16_t>::init(const JS::Value&);
    202 template bool nsTAutoJSString<char>::init(const JS::Value&);