summaryrefslogtreecommitdiffstats
path: root/dom/base/nsJSUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/base/nsJSUtils.cpp252
1 files changed, 252 insertions, 0 deletions
diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp
new file mode 100644
index 0000000000..46db78b384
--- /dev/null
+++ b/dom/base/nsJSUtils.cpp
@@ -0,0 +1,252 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * This is not a generated file. It contains common utility functions
+ * invoked from the JavaScript code generated from IDL interfaces.
+ * The goal of the utility functions is to cut down on the size of
+ * the generated code itself.
+ */
+
+#include "nsJSUtils.h"
+
+#include <utility>
+#include "GeckoProfiler.h"
+#include "MainThreadUtils.h"
+#include "js/ComparisonOperators.h"
+#include "js/CompilationAndEvaluation.h"
+#include "js/CompileOptions.h"
+#include "js/Date.h"
+#include "js/GCVector.h"
+#include "js/HeapAPI.h"
+#include "js/Modules.h"
+#include "js/RootingAPI.h"
+#include "js/SourceText.h"
+#include "js/TypeDecls.h"
+#include "jsfriendapi.h"
+#include "mozilla/CycleCollectedJSContext.h"
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/fallible.h"
+#include "nsContentUtils.h"
+#include "nsDebug.h"
+#include "nsGlobalWindowInner.h"
+#include "nsINode.h"
+#include "nsString.h"
+#include "nsTPromiseFlatString.h"
+#include "nscore.h"
+
+#if !defined(DEBUG) && !defined(MOZ_ENABLE_JS_DUMP)
+# include "mozilla/StaticPrefs_browser.h"
+#endif
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+bool nsJSUtils::GetCallingLocation(JSContext* aContext, nsACString& aFilename,
+ uint32_t* aLineno, uint32_t* aColumn) {
+ JS::AutoFilename filename;
+ if (!JS::DescribeScriptedCaller(aContext, &filename, aLineno, aColumn)) {
+ return false;
+ }
+
+ return aFilename.Assign(filename.get(), fallible);
+}
+
+bool nsJSUtils::GetCallingLocation(JSContext* aContext, nsAString& aFilename,
+ uint32_t* aLineno, uint32_t* aColumn) {
+ JS::AutoFilename filename;
+ if (!JS::DescribeScriptedCaller(aContext, &filename, aLineno, aColumn)) {
+ return false;
+ }
+
+ return aFilename.Assign(NS_ConvertUTF8toUTF16(filename.get()), fallible);
+}
+
+uint64_t nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(JSContext* aContext) {
+ if (!aContext) return 0;
+
+ nsGlobalWindowInner* win = xpc::CurrentWindowOrNull(aContext);
+ return win ? win->WindowID() : 0;
+}
+
+nsresult nsJSUtils::CompileFunction(AutoJSAPI& jsapi,
+ JS::HandleVector<JSObject*> aScopeChain,
+ JS::CompileOptions& aOptions,
+ const nsACString& aName, uint32_t aArgCount,
+ const char** aArgArray,
+ const nsAString& aBody,
+ JSObject** aFunctionObject) {
+ JSContext* cx = jsapi.cx();
+ MOZ_ASSERT(js::GetContextRealm(cx));
+ MOZ_ASSERT_IF(aScopeChain.length() != 0,
+ js::IsObjectInContextCompartment(aScopeChain[0], cx));
+
+ // Do the junk Gecko is supposed to do before calling into JSAPI.
+ for (size_t i = 0; i < aScopeChain.length(); ++i) {
+ JS::ExposeObjectToActiveJS(aScopeChain[i]);
+ }
+
+ // Compile.
+ const nsPromiseFlatString& flatBody = PromiseFlatString(aBody);
+
+ JS::SourceText<char16_t> source;
+ if (!source.init(cx, flatBody.get(), flatBody.Length(),
+ JS::SourceOwnership::Borrowed)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ JS::Rooted<JSFunction*> fun(
+ cx, JS::CompileFunction(cx, aScopeChain, aOptions,
+ PromiseFlatCString(aName).get(), aArgCount,
+ aArgArray, source));
+ if (!fun) {
+ return NS_ERROR_FAILURE;
+ }
+
+ *aFunctionObject = JS_GetFunctionObject(fun);
+ return NS_OK;
+}
+
+template <typename Unit>
+static nsresult CompileJSModule(JSContext* aCx, JS::SourceText<Unit>& aSrcBuf,
+ JS::Handle<JSObject*> aEvaluationGlobal,
+ JS::CompileOptions& aCompileOptions,
+ JS::MutableHandle<JSObject*> aModule) {
+ AUTO_PROFILER_LABEL("nsJSUtils::CompileModule", JS);
+ MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
+ MOZ_ASSERT(aSrcBuf.get());
+ MOZ_ASSERT(JS_IsGlobalObject(aEvaluationGlobal));
+ MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx) == aEvaluationGlobal);
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(CycleCollectedJSContext::Get() &&
+ CycleCollectedJSContext::Get()->MicroTaskLevel());
+
+ NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal).Allowed(), NS_OK);
+
+ JSObject* module = JS::CompileModule(aCx, aCompileOptions, aSrcBuf);
+ if (!module) {
+ return NS_ERROR_FAILURE;
+ }
+
+ aModule.set(module);
+ return NS_OK;
+}
+
+nsresult nsJSUtils::CompileModule(JSContext* aCx,
+ JS::SourceText<char16_t>& aSrcBuf,
+ JS::Handle<JSObject*> aEvaluationGlobal,
+ JS::CompileOptions& aCompileOptions,
+ JS::MutableHandle<JSObject*> aModule) {
+ return CompileJSModule(aCx, aSrcBuf, aEvaluationGlobal, aCompileOptions,
+ aModule);
+}
+
+nsresult nsJSUtils::CompileModule(JSContext* aCx,
+ JS::SourceText<Utf8Unit>& aSrcBuf,
+ JS::Handle<JSObject*> aEvaluationGlobal,
+ JS::CompileOptions& aCompileOptions,
+ JS::MutableHandle<JSObject*> aModule) {
+ return CompileJSModule(aCx, aSrcBuf, aEvaluationGlobal, aCompileOptions,
+ aModule);
+}
+
+nsresult nsJSUtils::ModuleInstantiate(JSContext* aCx,
+ JS::Handle<JSObject*> aModule) {
+ AUTO_PROFILER_LABEL("nsJSUtils::ModuleInstantiate", JS);
+
+ MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(CycleCollectedJSContext::Get() &&
+ CycleCollectedJSContext::Get()->MicroTaskLevel());
+
+ NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
+
+ if (!JS::ModuleInstantiate(aCx, aModule)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+nsresult nsJSUtils::ModuleEvaluate(JSContext* aCx,
+ JS::Handle<JSObject*> aModule,
+ JS::MutableHandle<JS::Value> aResult) {
+ AUTO_PROFILER_LABEL("nsJSUtils::ModuleEvaluate", JS);
+
+ MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(CycleCollectedJSContext::Get() &&
+ CycleCollectedJSContext::Get()->MicroTaskLevel());
+
+ NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
+
+ if (!JS::ModuleEvaluate(aCx, aModule, aResult)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+static bool AddScopeChainItem(JSContext* aCx, nsINode* aNode,
+ JS::MutableHandleVector<JSObject*> aScopeChain) {
+ JS::RootedValue val(aCx);
+ if (!GetOrCreateDOMReflector(aCx, aNode, &val)) {
+ return false;
+ }
+
+ if (!aScopeChain.append(&val.toObject())) {
+ return false;
+ }
+
+ return true;
+}
+
+/* static */
+bool nsJSUtils::GetScopeChainForElement(
+ JSContext* aCx, Element* aElement,
+ JS::MutableHandleVector<JSObject*> aScopeChain) {
+ for (nsINode* cur = aElement; cur; cur = cur->GetScopeChainParent()) {
+ if (!AddScopeChainItem(aCx, cur, aScopeChain)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* static */
+void nsJSUtils::ResetTimeZone() { JS::ResetTimeZone(); }
+
+/* static */
+bool nsJSUtils::DumpEnabled() {
+#if defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP)
+ return true;
+#else
+ return StaticPrefs::browser_dom_window_dump_enabled();
+#endif
+}
+
+//
+// nsDOMJSUtils.h
+//
+
+template <typename T>
+bool nsTAutoJSString<T>::init(const JS::Value& v) {
+ // Note: it's okay to use danger::GetJSContext here instead of AutoJSAPI,
+ // because the init() call below is careful not to run script (for instance,
+ // it only calls JS::ToString for non-object values).
+ JSContext* cx = danger::GetJSContext();
+ if (!init(cx, v)) {
+ JS_ClearPendingException(cx);
+ return false;
+ }
+ return true;
+}
+
+template bool nsTAutoJSString<char16_t>::init(const JS::Value&);
+template bool nsTAutoJSString<char>::init(const JS::Value&);