2015-05-03 22:32:37 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
1998-12-03 03:33:00 +03:00
|
|
|
|
1998-12-23 01:03:20 +03:00
|
|
|
#ifndef nsJSUtils_h__
|
|
|
|
#define nsJSUtils_h__
|
|
|
|
|
1998-12-03 03:33:00 +03:00
|
|
|
/**
|
2017-07-06 15:00:35 +03:00
|
|
|
* This is not a generated file. It contains common utility functions
|
1998-12-03 03:33:00 +03:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2012-06-02 10:39:06 +04:00
|
|
|
#include "mozilla/Assertions.h"
|
|
|
|
|
2017-03-22 16:42:26 +03:00
|
|
|
#include "GeckoProfiler.h"
|
1998-12-03 03:33:00 +03:00
|
|
|
#include "jsapi.h"
|
2014-07-05 19:30:54 +04:00
|
|
|
#include "jsfriendapi.h"
|
2014-12-18 00:50:20 +03:00
|
|
|
#include "js/Conversions.h"
|
2018-08-20 17:44:44 +03:00
|
|
|
#include "js/StableStringChars.h"
|
1998-12-03 03:33:00 +03:00
|
|
|
#include "nsString.h"
|
|
|
|
|
1999-12-18 23:29:29 +03:00
|
|
|
class nsIScriptContext;
|
2018-02-15 16:18:59 +03:00
|
|
|
class nsIScriptElement;
|
1999-12-18 23:29:29 +03:00
|
|
|
class nsIScriptGlobalObject;
|
2018-03-19 01:41:47 +03:00
|
|
|
class nsXBLPrototypeBinding;
|
1999-03-29 02:19:42 +04:00
|
|
|
|
2014-09-29 17:34:21 +04:00
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
class AutoJSAPI;
|
2014-10-31 00:40:09 +03:00
|
|
|
class Element;
|
2015-07-13 18:25:42 +03:00
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|
2014-09-29 17:34:21 +04:00
|
|
|
|
2004-02-10 01:48:53 +03:00
|
|
|
class nsJSUtils
|
|
|
|
{
|
1998-12-23 01:03:20 +03:00
|
|
|
public:
|
2015-01-06 00:53:27 +03:00
|
|
|
static bool GetCallingLocation(JSContext* aContext, nsACString& aFilename,
|
2015-09-02 03:56:03 +03:00
|
|
|
uint32_t* aLineno = nullptr,
|
|
|
|
uint32_t* aColumn = nullptr);
|
2015-01-06 00:53:27 +03:00
|
|
|
static bool GetCallingLocation(JSContext* aContext, nsAString& aFilename,
|
2015-09-02 03:56:03 +03:00
|
|
|
uint32_t* aLineno = nullptr,
|
|
|
|
uint32_t* aColumn = nullptr);
|
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2001-05-08 21:42:36 +04:00
|
|
|
|
2010-12-20 19:21:58 +03:00
|
|
|
/**
|
2011-08-25 00:44:35 +04:00
|
|
|
* Retrieve the inner window ID based on the given JSContext.
|
2010-12-20 19:21:58 +03:00
|
|
|
*
|
|
|
|
* @param JSContext aContext
|
2011-08-25 00:44:35 +04:00
|
|
|
* The JSContext from which you want to find the inner window ID.
|
2010-12-20 19:21:58 +03:00
|
|
|
*
|
2012-08-22 19:56:38 +04:00
|
|
|
* @returns uint64_t the inner window ID.
|
2010-12-20 19:21:58 +03:00
|
|
|
*/
|
2012-08-22 19:56:38 +04:00
|
|
|
static uint64_t GetCurrentlyRunningCodeInnerWindowID(JSContext *aContext);
|
2012-11-09 19:43:57 +04:00
|
|
|
|
2014-09-29 17:34:21 +04:00
|
|
|
static nsresult CompileFunction(mozilla::dom::AutoJSAPI& jsapi,
|
2014-10-25 08:50:29 +04:00
|
|
|
JS::AutoObjectVector& aScopeChain,
|
2013-01-17 06:50:25 +04:00
|
|
|
JS::CompileOptions& aOptions,
|
|
|
|
const nsACString& aName,
|
|
|
|
uint32_t aArgCount,
|
|
|
|
const char** aArgArray,
|
|
|
|
const nsAString& aBody,
|
|
|
|
JSObject** aFunctionObject);
|
|
|
|
|
2017-03-22 16:42:26 +03:00
|
|
|
|
|
|
|
// ExecutionContext is used to switch compartment.
|
|
|
|
class MOZ_STACK_CLASS ExecutionContext {
|
2017-10-04 01:11:18 +03:00
|
|
|
#ifdef MOZ_GECKO_PROFILER
|
2017-03-22 16:42:26 +03:00
|
|
|
// Register stack annotations for the Gecko profiler.
|
2017-06-07 05:33:19 +03:00
|
|
|
mozilla::AutoProfilerLabel mAutoProfilerLabel;
|
2017-10-04 01:11:18 +03:00
|
|
|
#endif
|
2017-03-22 16:42:26 +03:00
|
|
|
|
|
|
|
JSContext* mCx;
|
|
|
|
|
2018-05-16 11:53:16 +03:00
|
|
|
// Handles switching to our global's realm.
|
2018-08-02 09:48:40 +03:00
|
|
|
JSAutoRealm mRealm;
|
2017-03-22 16:42:26 +03:00
|
|
|
|
|
|
|
// Set to a valid handle if a return value is expected.
|
|
|
|
JS::Rooted<JS::Value> mRetValue;
|
|
|
|
|
|
|
|
// Scope chain in which the execution takes place.
|
|
|
|
JS::AutoObjectVector mScopeChain;
|
|
|
|
|
|
|
|
// returned value forwarded when we have to interupt the execution eagerly
|
|
|
|
// with mSkip.
|
|
|
|
nsresult mRv;
|
|
|
|
|
|
|
|
// Used to skip upcoming phases in case of a failure. In such case the
|
|
|
|
// result is carried by mRv.
|
|
|
|
bool mSkip;
|
|
|
|
|
|
|
|
// Should the result be serialized before being returned.
|
|
|
|
bool mCoerceToString;
|
|
|
|
|
2017-05-29 19:01:37 +03:00
|
|
|
// Encode the bytecode before it is being executed.
|
|
|
|
bool mEncodeBytecode;
|
|
|
|
|
2017-03-22 16:42:26 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
// Should we set the return value.
|
|
|
|
bool mWantsReturnValue;
|
|
|
|
|
|
|
|
bool mExpectScopeChain;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
// Enter compartment in which the code would be executed. The JSContext
|
2018-09-25 04:49:18 +03:00
|
|
|
// must come from an AutoEntryScript.
|
2017-03-22 16:42:26 +03:00
|
|
|
ExecutionContext(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
|
|
|
|
|
|
|
|
ExecutionContext(const ExecutionContext&) = delete;
|
|
|
|
ExecutionContext(ExecutionContext&&) = delete;
|
|
|
|
|
|
|
|
~ExecutionContext() {
|
|
|
|
// This flag is resetted, when the returned value is extracted.
|
|
|
|
MOZ_ASSERT(!mWantsReturnValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The returned value would be converted to a string if the
|
|
|
|
// |aCoerceToString| is flag set.
|
|
|
|
ExecutionContext& SetCoerceToString(bool aCoerceToString) {
|
|
|
|
mCoerceToString = aCoerceToString;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2017-05-29 19:01:37 +03:00
|
|
|
// When set, this flag records and encodes the bytecode as soon as it is
|
|
|
|
// being compiled, and before it is being executed. The bytecode can then be
|
|
|
|
// requested by using |JS::FinishIncrementalEncoding| with the mutable
|
|
|
|
// handle |aScript| argument of |CompileAndExec| or |JoinAndExec|.
|
|
|
|
ExecutionContext& SetEncodeBytecode(bool aEncodeBytecode) {
|
|
|
|
mEncodeBytecode = aEncodeBytecode;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2017-03-22 16:42:26 +03:00
|
|
|
// Set the scope chain in which the code should be executed.
|
|
|
|
void SetScopeChain(const JS::AutoObjectVector& aScopeChain);
|
|
|
|
|
|
|
|
// Copy the returned value in the mutable handle argument, in case of a
|
|
|
|
// evaluation failure either during the execution or the conversion of the
|
|
|
|
// result to a string, the nsresult would be set to the corresponding result
|
|
|
|
// code, and the mutable handle argument would remain unchanged.
|
|
|
|
//
|
|
|
|
// The value returned in the mutable handle argument is part of the
|
|
|
|
// compartment given as argument to the ExecutionContext constructor. If the
|
|
|
|
// caller is in a different compartment, then the out-param value should be
|
|
|
|
// wrapped by calling |JS_WrapValue|.
|
|
|
|
MOZ_MUST_USE nsresult
|
|
|
|
ExtractReturnValue(JS::MutableHandle<JS::Value> aRetValue);
|
|
|
|
|
|
|
|
// After getting a notification that an off-thread compilation terminated,
|
2017-04-21 19:57:57 +03:00
|
|
|
// this function will take the result of the parser by moving it to the main
|
|
|
|
// thread before starting the execution of the script.
|
2017-03-22 16:42:26 +03:00
|
|
|
//
|
|
|
|
// The compiled script would be returned in the |aScript| out-param.
|
2018-05-10 16:51:14 +03:00
|
|
|
MOZ_MUST_USE nsresult JoinAndExec(JS::OffThreadToken** aOffThreadToken,
|
2017-03-22 16:42:26 +03:00
|
|
|
JS::MutableHandle<JSScript*> aScript);
|
|
|
|
|
|
|
|
// Compile a script contained in a SourceBuffer, and execute it.
|
|
|
|
nsresult CompileAndExec(JS::CompileOptions& aCompileOptions,
|
2017-05-29 19:01:37 +03:00
|
|
|
JS::SourceBufferHolder& aSrcBuf,
|
|
|
|
JS::MutableHandle<JSScript*> aScript);
|
2017-03-22 16:42:26 +03:00
|
|
|
|
|
|
|
// Compile a script contained in a string, and execute it.
|
|
|
|
nsresult CompileAndExec(JS::CompileOptions& aCompileOptions,
|
|
|
|
const nsAString& aScript);
|
2017-04-21 19:57:57 +03:00
|
|
|
|
|
|
|
// Decode a script contained in a buffer, and execute it.
|
|
|
|
MOZ_MUST_USE nsresult DecodeAndExec(JS::CompileOptions& aCompileOptions,
|
|
|
|
mozilla::Vector<uint8_t>& aBytecodeBuf,
|
|
|
|
size_t aBytecodeIndex);
|
|
|
|
|
|
|
|
// After getting a notification that an off-thread decoding terminated, this
|
|
|
|
// function will get the result of the decoder by moving it to the main
|
|
|
|
// thread before starting the execution of the script.
|
2018-05-10 16:51:14 +03:00
|
|
|
MOZ_MUST_USE nsresult DecodeJoinAndExec(JS::OffThreadToken** aOffThreadToken);
|
2018-05-16 17:58:13 +03:00
|
|
|
|
|
|
|
MOZ_MUST_USE nsresult DecodeBinASTJoinAndExec(JS::OffThreadToken** aOffThreadToken,
|
|
|
|
JS::MutableHandle<JSScript*> aScript);
|
|
|
|
|
|
|
|
// Decode a BinAST encoded script contained in a buffer, and execute it.
|
|
|
|
nsresult DecodeBinASTAndExec(JS::CompileOptions& aCompileOptions,
|
|
|
|
const uint8_t* aBuf, size_t aLength,
|
|
|
|
JS::MutableHandle<JSScript*> aScript);
|
2017-03-22 16:42:26 +03:00
|
|
|
};
|
|
|
|
|
2016-05-07 14:46:38 +03:00
|
|
|
static nsresult CompileModule(JSContext* aCx,
|
|
|
|
JS::SourceBufferHolder& aSrcBuf,
|
|
|
|
JS::Handle<JSObject*> aEvaluationGlobal,
|
|
|
|
JS::CompileOptions &aCompileOptions,
|
2018-10-04 13:50:55 +03:00
|
|
|
JS::MutableHandle<JSObject*> aModule);
|
2016-05-07 14:46:38 +03:00
|
|
|
|
2018-02-15 16:18:59 +03:00
|
|
|
static nsresult InitModuleSourceElement(JSContext* aCx,
|
2018-10-04 13:50:55 +03:00
|
|
|
JS::Handle<JSObject*> aModule,
|
2018-02-15 16:18:59 +03:00
|
|
|
nsIScriptElement* aElement);
|
|
|
|
|
2017-08-22 12:07:49 +03:00
|
|
|
static nsresult ModuleInstantiate(JSContext* aCx,
|
2018-10-04 13:50:55 +03:00
|
|
|
JS::Handle<JSObject*> aModule);
|
2016-05-07 14:46:38 +03:00
|
|
|
|
2017-08-22 12:07:49 +03:00
|
|
|
static nsresult ModuleEvaluate(JSContext* aCx,
|
2018-10-04 13:50:55 +03:00
|
|
|
JS::Handle<JSObject*> aModule);
|
2016-05-07 14:46:38 +03:00
|
|
|
|
2014-10-31 00:40:09 +03:00
|
|
|
// Returns false if an exception got thrown on aCx. Passing a null
|
|
|
|
// aElement is allowed; that wil produce an empty aScopeChain.
|
|
|
|
static bool GetScopeChainForElement(JSContext* aCx,
|
|
|
|
mozilla::dom::Element* aElement,
|
|
|
|
JS::AutoObjectVector& aScopeChain);
|
2015-06-15 10:44:09 +03:00
|
|
|
|
2018-03-19 01:41:47 +03:00
|
|
|
// Returns a scope chain suitable for XBL execution.
|
|
|
|
//
|
|
|
|
// This is by default GetScopeChainForElemenet, but will be different if the
|
|
|
|
// <binding> element had the simpleScopeChain attribute.
|
|
|
|
//
|
|
|
|
// This is to prevent footguns like bug 1446342.
|
|
|
|
static bool GetScopeChainForXBL(JSContext* aCx,
|
|
|
|
mozilla::dom::Element* aBoundElement,
|
|
|
|
const nsXBLPrototypeBinding& aProtoBinding,
|
|
|
|
JS::AutoObjectVector& aScopeChain);
|
|
|
|
|
2015-06-15 10:44:09 +03:00
|
|
|
static void ResetTimeZone();
|
2004-02-10 01:48:53 +03:00
|
|
|
};
|
|
|
|
|
2014-07-05 19:30:54 +04:00
|
|
|
template<typename T>
|
|
|
|
inline bool
|
|
|
|
AssignJSString(JSContext *cx, T &dest, JSString *s)
|
|
|
|
{
|
2018-08-20 17:44:44 +03:00
|
|
|
size_t len = JS::GetStringLength(s);
|
2014-07-05 19:30:54 +04:00
|
|
|
static_assert(js::MaxStringLength < (1 << 28),
|
|
|
|
"Shouldn't overflow here or in SetCapacity");
|
2015-01-28 12:00:40 +03:00
|
|
|
if (MOZ_UNLIKELY(!dest.SetLength(len, mozilla::fallible))) {
|
2014-07-05 19:30:54 +04:00
|
|
|
JS_ReportOutOfMemory(cx);
|
|
|
|
return false;
|
|
|
|
}
|
2014-07-19 17:23:19 +04:00
|
|
|
return js::CopyStringChars(cx, dest.BeginWriting(), s, len);
|
2014-07-05 19:30:54 +04:00
|
|
|
}
|
2004-02-10 01:48:53 +03:00
|
|
|
|
2014-07-12 11:43:06 +04:00
|
|
|
inline void
|
|
|
|
AssignJSFlatString(nsAString &dest, JSFlatString *s)
|
|
|
|
{
|
|
|
|
size_t len = js::GetFlatStringLength(s);
|
|
|
|
static_assert(js::MaxStringLength < (1 << 28),
|
|
|
|
"Shouldn't overflow here or in SetCapacity");
|
|
|
|
dest.SetLength(len);
|
2014-07-19 17:23:19 +04:00
|
|
|
js::CopyFlatStringChars(dest.BeginWriting(), s, len);
|
2014-07-12 11:43:06 +04:00
|
|
|
}
|
|
|
|
|
2014-07-05 19:30:54 +04:00
|
|
|
class nsAutoJSString : public nsAutoString
|
2004-02-10 01:48:53 +03:00
|
|
|
{
|
|
|
|
public:
|
2014-06-11 07:15:56 +04:00
|
|
|
|
2010-12-03 11:24:17 +03:00
|
|
|
/**
|
2014-07-05 19:30:54 +04:00
|
|
|
* nsAutoJSString should be default constructed, which leaves it empty
|
|
|
|
* (this->IsEmpty()), and initialized with one of the init() methods below.
|
2010-12-03 11:24:17 +03:00
|
|
|
*/
|
2014-07-05 19:30:54 +04:00
|
|
|
nsAutoJSString() {}
|
2014-06-11 07:15:56 +04:00
|
|
|
|
|
|
|
bool init(JSContext* aContext, JSString* str)
|
2004-02-10 01:48:53 +03:00
|
|
|
{
|
2014-07-05 19:30:54 +04:00
|
|
|
return AssignJSString(aContext, *this, str);
|
2004-02-10 01:48:53 +03:00
|
|
|
}
|
|
|
|
|
2014-06-11 07:15:56 +04:00
|
|
|
bool init(JSContext* aContext, const JS::Value &v)
|
2012-06-02 10:39:06 +04:00
|
|
|
{
|
2014-06-11 07:15:56 +04:00
|
|
|
if (v.isString()) {
|
|
|
|
return init(aContext, v.toString());
|
|
|
|
}
|
2012-06-02 10:39:06 +04:00
|
|
|
|
2014-06-11 07:15:56 +04:00
|
|
|
// Stringify, making sure not to run script.
|
|
|
|
JS::Rooted<JSString*> str(aContext);
|
|
|
|
if (v.isObject()) {
|
|
|
|
str = JS_NewStringCopyZ(aContext, "[Object]");
|
|
|
|
} else {
|
|
|
|
JS::Rooted<JS::Value> rootedVal(aContext, v);
|
|
|
|
str = JS::ToString(aContext, rootedVal);
|
|
|
|
}
|
2010-12-03 11:24:17 +03:00
|
|
|
|
2014-06-11 07:15:56 +04:00
|
|
|
return str && init(aContext, str);
|
2010-07-15 10:19:36 +04:00
|
|
|
}
|
|
|
|
|
2014-06-11 07:15:56 +04:00
|
|
|
bool init(JSContext* aContext, jsid id)
|
2010-07-15 10:19:36 +04:00
|
|
|
{
|
2014-06-11 07:15:56 +04:00
|
|
|
JS::Rooted<JS::Value> v(aContext);
|
|
|
|
return JS_IdToValue(aContext, id, &v) && init(aContext, v);
|
2010-07-15 10:19:36 +04:00
|
|
|
}
|
|
|
|
|
2015-02-19 22:16:00 +03:00
|
|
|
bool init(const JS::Value &v);
|
|
|
|
|
2014-07-05 19:30:54 +04:00
|
|
|
~nsAutoJSString() {}
|
1998-12-23 01:03:20 +03:00
|
|
|
};
|
1998-12-03 03:33:00 +03:00
|
|
|
|
1998-12-23 01:03:20 +03:00
|
|
|
#endif /* nsJSUtils_h__ */
|