diff --git a/js/public/CompilationAndEvaluation.h b/js/public/CompilationAndEvaluation.h new file mode 100644 index 0000000000..c3838d4c88 --- /dev/null +++ b/js/public/CompilationAndEvaluation.h @@ -0,0 +1,236 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* 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/. */ + +/* Functions for compiling and evaluating scripts. */ + +#ifndef js_CompilationAndEvaluation_h +#define js_CompilationAndEvaluation_h + +#include // size_t +#include // FILE + +#include "jstypes.h" // JS_PUBLIC_API + +#include "js/CompileOptions.h" // JS::CompileOptions, JS::ReadOnlyCompileOptions +#include "js/RootingAPI.h" // JS::Handle, JS::MutableHandle +#include "js/GCVector.h" + +struct JSContext; +class JSFunction; +class JSObject; +class JSScript; + +namespace JS { + +class AutoObjectVector : public Rooted> { + using Vec = GCVector; + using Base = Rooted; + public: + explicit AutoObjectVector(JSContext* cx) : Base(cx, Vec(cx)) {} + explicit AutoObjectVector(js::ContextFriendFields* cx) : Base(cx, Vec(cx)) {} +}; + +class SourceBufferHolder; + +} // namespace JS + +/** + * Given a buffer, return false if the buffer might become a valid + * javascript statement with the addition of more lines. Otherwise return + * true. The intent is to support interactive compilation - accumulate + * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to + * the compiler. + */ +extern JS_PUBLIC_API(bool) +JS_BufferIsCompilableUnit(JSContext* cx, JS::Handle obj, const char* utf8, + size_t length); + +/* + * NB: JS_ExecuteScript and the JS::Evaluate APIs come in two flavors: either + * they use the global as the scope, or they take an AutoObjectVector of objects + * to use as the scope chain. In the former case, the global is also used as + * the "this" keyword value and the variables object (ECMA parlance for where + * 'var' and 'function' bind names) of the execution context for script. In the + * latter case, the first object in the provided list is used, unless the list + * is empty, in which case the global is used. + * + * Why a runtime option? The alternative is to add APIs duplicating those + * for the other value of flags, and that doesn't seem worth the code bloat + * cost. Such new entry points would probably have less obvious names, too, so + * would not tend to be used. The ContextOptionsRef adjustment, OTOH, can be + * more easily hacked into existing code that does not depend on the bug; such + * code can continue to use the familiar JS::Evaluate, etc., entry points. + */ + +/** + * Evaluate a script in the scope of the current global of cx. + */ +extern JS_PUBLIC_API(bool) +JS_ExecuteScript(JSContext* cx, JS::HandleScript script, JS::MutableHandleValue rval); + +extern JS_PUBLIC_API(bool) +JS_ExecuteScript(JSContext* cx, JS::HandleScript script); + +/** + * As above, but providing an explicit scope chain. envChain must not include + * the global object on it; that's implicit. It needs to contain the other + * objects that should end up on the script's scope chain. + */ +extern JS_PUBLIC_API(bool) +JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& envChain, + JS::HandleScript script, JS::MutableHandleValue rval); + +extern JS_PUBLIC_API(bool) +JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& envChain, JS::HandleScript script); + +/** + * |script| will always be set. On failure, it will be set to nullptr. + */ +extern JS_PUBLIC_API(bool) +JS_CompileScript(JSContext* cx, const char* ascii, size_t length, + const JS::CompileOptions& options, + JS::MutableHandleScript script); + +/** + * |script| will always be set. On failure, it will be set to nullptr. + */ +extern JS_PUBLIC_API(bool) +JS_CompileUCScript(JSContext* cx, const char16_t* chars, size_t length, + const JS::CompileOptions& options, + JS::MutableHandleScript script); + +namespace JS { + +/** + * Like the above, but handles a cross-compartment script. If the script is + * cross-compartment, it is cloned into the current compartment before executing. + */ +extern JS_PUBLIC_API(bool) +CloneAndExecuteScript(JSContext* cx, JS::Handle script, + JS::MutableHandleValue rval); + +/** + * Evaluate the given source buffer in the scope of the current global of cx. + */ +extern JS_PUBLIC_API(bool) +Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options, + SourceBufferHolder& srcBuf, JS::MutableHandleValue rval); + +/** + * As above, but providing an explicit scope chain. envChain must not include + * the global object on it; that's implicit. It needs to contain the other + * objects that should end up on the script's scope chain. + */ +extern JS_PUBLIC_API(bool) +Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options, + SourceBufferHolder& srcBuf, JS::MutableHandleValue rval); + +/** + * Evaluate the given character buffer in the scope of the current global of cx. + */ +extern JS_PUBLIC_API(bool) +Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options, + const char16_t* chars, size_t length, JS::MutableHandleValue rval); + +/** + * As above, but providing an explicit scope chain. envChain must not include + * the global object on it; that's implicit. It needs to contain the other + * objects that should end up on the script's scope chain. + */ +extern JS_PUBLIC_API(bool) +Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options, + const char16_t* chars, size_t length, JS::MutableHandleValue rval); + +/** + * Evaluate the given byte buffer in the scope of the current global of cx. + */ +extern JS_PUBLIC_API(bool) +Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options, + const char* bytes, size_t length, JS::MutableHandleValue rval); + +/** + * Evaluate the given file in the scope of the current global of cx. + */ +extern JS_PUBLIC_API(bool) +Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options, + const char* filename, JS::MutableHandleValue rval); + +/** + * |script| will always be set. On failure, it will be set to nullptr. + */ +extern JS_PUBLIC_API(bool) +Compile(JSContext* cx, const ReadOnlyCompileOptions& options, + SourceBufferHolder& srcBuf, JS::MutableHandleScript script); + +extern JS_PUBLIC_API(bool) +Compile(JSContext* cx, const ReadOnlyCompileOptions& options, + const char* bytes, size_t length, JS::MutableHandleScript script); + +extern JS_PUBLIC_API(bool) +Compile(JSContext* cx, const ReadOnlyCompileOptions& options, + const char16_t* chars, size_t length, JS::MutableHandleScript script); + +extern JS_PUBLIC_API(bool) +Compile(JSContext* cx, const ReadOnlyCompileOptions& options, + FILE* file, JS::MutableHandleScript script); + +extern JS_PUBLIC_API(bool) +Compile(JSContext* cx, const ReadOnlyCompileOptions& options, + const char* filename, JS::MutableHandleScript script); + +extern JS_PUBLIC_API(bool) +CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, + SourceBufferHolder& srcBuf, JS::MutableHandleScript script); + +extern JS_PUBLIC_API(bool) +CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, + const char* bytes, size_t length, JS::MutableHandleScript script); + +extern JS_PUBLIC_API(bool) +CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, + const char16_t* chars, size_t length, JS::MutableHandleScript script); + +extern JS_PUBLIC_API(bool) +CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, + FILE* file, JS::MutableHandleScript script); + +extern JS_PUBLIC_API(bool) +CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, + const char* filename, JS::MutableHandleScript script); + +/** + * Compile a function with envChain plus the global as its scope chain. + * envChain must contain objects in the current compartment of cx. The actual + * scope chain used for the function will consist of With wrappers for those + * objects, followed by the current global of the compartment cx is in. This + * global must not be explicitly included in the scope chain. + */ +extern JS_PUBLIC_API(bool) +CompileFunction(JSContext* cx, AutoObjectVector& envChain, + const ReadOnlyCompileOptions& options, + const char* name, unsigned nargs, const char* const* argnames, + const char16_t* chars, size_t length, JS::MutableHandleFunction fun); + +/** + * Same as above, but taking a SourceBufferHolder for the function body. + */ +extern JS_PUBLIC_API(bool) +CompileFunction(JSContext* cx, AutoObjectVector& envChain, + const ReadOnlyCompileOptions& options, + const char* name, unsigned nargs, const char* const* argnames, + SourceBufferHolder& srcBuf, JS::MutableHandleFunction fun); + +/** + * Same as above, but taking a const char * for the function body. + */ +extern JS_PUBLIC_API(bool) +CompileFunction(JSContext* cx, AutoObjectVector& envChain, + const ReadOnlyCompileOptions& options, + const char* name, unsigned nargs, const char* const* argnames, + const char* bytes, size_t length, JS::MutableHandleFunction fun); + +} /* namespace JS */ + +#endif /* js_CompilationAndEvaluation_h */ diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 39828d25ff..ac7610f5f8 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -29,6 +29,7 @@ #include "js/CallArgs.h" #include "js/CharacterEncoding.h" #include "js/Class.h" +#include "js/CompilationAndEvaluation.h" #include "js/CompileOptions.h" #include "js/GCVector.h" #include "js/HashTable.h" @@ -242,14 +243,6 @@ class AutoIdVector : public Rooted> { bool appendAll(const AutoIdVector& other) { return this->Base::appendAll(other.get()); } }; -class AutoObjectVector : public Rooted> { - using Vec = GCVector; - using Base = Rooted; - public: - explicit AutoObjectVector(JSContext* cx) : Base(cx, Vec(cx)) {} - explicit AutoObjectVector(js::ContextFriendFields* cx) : Base(cx, Vec(cx)) {} -}; - using ValueVector = JS::GCVector; using IdVector = JS::GCVector; using ScriptVector = JS::GCVector; @@ -3595,32 +3588,7 @@ CloneFunctionObject(JSContext* cx, HandleObject funobj, AutoObjectVector& scopeC } // namespace JS -/** - * Given a buffer, return false if the buffer might become a valid - * javascript statement with the addition of more lines. Otherwise return - * true. The intent is to support interactive compilation - accumulate - * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to - * the compiler. - */ -extern JS_PUBLIC_API(bool) -JS_BufferIsCompilableUnit(JSContext* cx, JS::Handle obj, const char* utf8, - size_t length); -/** - * |script| will always be set. On failure, it will be set to nullptr. - */ -extern JS_PUBLIC_API(bool) -JS_CompileScript(JSContext* cx, const char* ascii, size_t length, - const JS::CompileOptions& options, - JS::MutableHandleScript script); - -/** - * |script| will always be set. On failure, it will be set to nullptr. - */ -extern JS_PUBLIC_API(bool) -JS_CompileUCScript(JSContext* cx, const char16_t* chars, size_t length, - const JS::CompileOptions& options, - JS::MutableHandleScript script); extern JS_PUBLIC_API(JSObject*) JS_GetGlobalFromScript(JSScript* script); @@ -3634,84 +3602,6 @@ JS_GetScriptBaseLineNumber(JSContext* cx, JSScript* script); extern JS_PUBLIC_API(JSScript*) JS_GetFunctionScript(JSContext* cx, JS::HandleFunction fun); -namespace JS { - -/** - * |script| will always be set. On failure, it will be set to nullptr. - */ -extern JS_PUBLIC_API(bool) -Compile(JSContext* cx, const ReadOnlyCompileOptions& options, - SourceBufferHolder& srcBuf, JS::MutableHandleScript script); - -extern JS_PUBLIC_API(bool) -Compile(JSContext* cx, const ReadOnlyCompileOptions& options, - const char* bytes, size_t length, JS::MutableHandleScript script); - -extern JS_PUBLIC_API(bool) -Compile(JSContext* cx, const ReadOnlyCompileOptions& options, - const char16_t* chars, size_t length, JS::MutableHandleScript script); - -extern JS_PUBLIC_API(bool) -Compile(JSContext* cx, const ReadOnlyCompileOptions& options, - FILE* file, JS::MutableHandleScript script); - -extern JS_PUBLIC_API(bool) -Compile(JSContext* cx, const ReadOnlyCompileOptions& options, - const char* filename, JS::MutableHandleScript script); - -extern JS_PUBLIC_API(bool) -CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, - SourceBufferHolder& srcBuf, JS::MutableHandleScript script); - -extern JS_PUBLIC_API(bool) -CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, - const char* bytes, size_t length, JS::MutableHandleScript script); - -extern JS_PUBLIC_API(bool) -CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, - const char16_t* chars, size_t length, JS::MutableHandleScript script); - -extern JS_PUBLIC_API(bool) -CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, - FILE* file, JS::MutableHandleScript script); - -extern JS_PUBLIC_API(bool) -CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, - const char* filename, JS::MutableHandleScript script); - -/** - * Compile a function with envChain plus the global as its scope chain. - * envChain must contain objects in the current compartment of cx. The actual - * scope chain used for the function will consist of With wrappers for those - * objects, followed by the current global of the compartment cx is in. This - * global must not be explicitly included in the scope chain. - */ -extern JS_PUBLIC_API(bool) -CompileFunction(JSContext* cx, AutoObjectVector& envChain, - const ReadOnlyCompileOptions& options, - const char* name, unsigned nargs, const char* const* argnames, - const char16_t* chars, size_t length, JS::MutableHandleFunction fun); - -/** - * Same as above, but taking a SourceBufferHolder for the function body. - */ -extern JS_PUBLIC_API(bool) -CompileFunction(JSContext* cx, AutoObjectVector& envChain, - const ReadOnlyCompileOptions& options, - const char* name, unsigned nargs, const char* const* argnames, - SourceBufferHolder& srcBuf, JS::MutableHandleFunction fun); - -/** - * Same as above, but taking a const char * for the function body. - */ -extern JS_PUBLIC_API(bool) -CompileFunction(JSContext* cx, AutoObjectVector& envChain, - const ReadOnlyCompileOptions& options, - const char* name, unsigned nargs, const char* const* argnames, - const char* bytes, size_t length, JS::MutableHandleFunction fun); - -} /* namespace JS */ - extern JS_PUBLIC_API(JSString*) JS_DecompileScript(JSContext* cx, JS::Handle script); @@ -3719,104 +3609,8 @@ extern JS_PUBLIC_API(JSString*) JS_DecompileFunction(JSContext* cx, JS::Handle fun); -/* - * NB: JS_ExecuteScript and the JS::Evaluate APIs come in two flavors: either - * they use the global as the scope, or they take an AutoObjectVector of objects - * to use as the scope chain. In the former case, the global is also used as - * the "this" keyword value and the variables object (ECMA parlance for where - * 'var' and 'function' bind names) of the execution context for script. In the - * latter case, the first object in the provided list is used, unless the list - * is empty, in which case the global is used. - * - * Why a runtime option? The alternative is to add APIs duplicating those - * for the other value of flags, and that doesn't seem worth the code bloat - * cost. Such new entry points would probably have less obvious names, too, so - * would not tend to be used. The ContextOptionsRef adjustment, OTOH, can be - * more easily hacked into existing code that does not depend on the bug; such - * code can continue to use the familiar JS::Evaluate, etc., entry points. - */ - -/** - * Evaluate a script in the scope of the current global of cx. - */ -extern JS_PUBLIC_API(bool) -JS_ExecuteScript(JSContext* cx, JS::HandleScript script, JS::MutableHandleValue rval); - -extern JS_PUBLIC_API(bool) -JS_ExecuteScript(JSContext* cx, JS::HandleScript script); - -/** - * As above, but providing an explicit scope chain. envChain must not include - * the global object on it; that's implicit. It needs to contain the other - * objects that should end up on the script's scope chain. - */ -extern JS_PUBLIC_API(bool) -JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& envChain, - JS::HandleScript script, JS::MutableHandleValue rval); - -extern JS_PUBLIC_API(bool) -JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& envChain, JS::HandleScript script); - namespace JS { -/** - * Like the above, but handles a cross-compartment script. If the script is - * cross-compartment, it is cloned into the current compartment before executing. - */ -extern JS_PUBLIC_API(bool) -CloneAndExecuteScript(JSContext* cx, JS::Handle script, - JS::MutableHandleValue rval); - -} /* namespace JS */ - -namespace JS { - -/** - * Evaluate the given source buffer in the scope of the current global of cx. - */ -extern JS_PUBLIC_API(bool) -Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options, - SourceBufferHolder& srcBuf, JS::MutableHandleValue rval); - -/** - * As above, but providing an explicit scope chain. envChain must not include - * the global object on it; that's implicit. It needs to contain the other - * objects that should end up on the script's scope chain. - */ -extern JS_PUBLIC_API(bool) -Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options, - SourceBufferHolder& srcBuf, JS::MutableHandleValue rval); - -/** - * Evaluate the given character buffer in the scope of the current global of cx. - */ -extern JS_PUBLIC_API(bool) -Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options, - const char16_t* chars, size_t length, JS::MutableHandleValue rval); - -/** - * As above, but providing an explicit scope chain. envChain must not include - * the global object on it; that's implicit. It needs to contain the other - * objects that should end up on the script's scope chain. - */ -extern JS_PUBLIC_API(bool) -Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options, - const char16_t* chars, size_t length, JS::MutableHandleValue rval); - -/** - * Evaluate the given byte buffer in the scope of the current global of cx. - */ -extern JS_PUBLIC_API(bool) -Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options, - const char* bytes, size_t length, JS::MutableHandleValue rval); - -/** - * Evaluate the given file in the scope of the current global of cx. - */ -extern JS_PUBLIC_API(bool) -Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options, - const char* filename, JS::MutableHandleValue rval); - using ModuleResolveHook = JSObject* (*)(JSContext*, HandleValue, HandleString); /** diff --git a/js/src/moz.build b/js/src/moz.build index 383ea8233f..def03e98e1 100644 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -67,6 +67,7 @@ EXPORTS.js += [ '../public/CallNonGenericMethod.h', '../public/CharacterEncoding.h', '../public/Class.h', + '../public/CompilationAndEvaluation.h', '../public/CompileOptions.h', '../public/Conversions.h', '../public/Date.h',