2009-10-02 01:21:19 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
2007-03-22 10:30:00 -07:00
|
|
|
*
|
|
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is Mozilla Communicator client code, released
|
|
|
|
* March 31, 1998.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
|
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
#ifndef jsfun_h___
|
|
|
|
#define jsfun_h___
|
|
|
|
/*
|
|
|
|
* JS function definitions.
|
|
|
|
*/
|
|
|
|
#include "jsprvtd.h"
|
|
|
|
#include "jspubtd.h"
|
2008-04-02 00:46:12 -07:00
|
|
|
#include "jsobj.h"
|
2010-07-23 14:41:56 -07:00
|
|
|
#include "jsatom.h"
|
2010-11-16 15:34:24 -08:00
|
|
|
#include "jsscript.h"
|
2010-07-23 14:41:56 -07:00
|
|
|
#include "jsstr.h"
|
2010-10-06 10:41:36 -07:00
|
|
|
#include "jsopcode.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-04-05 21:17:22 -07:00
|
|
|
/*
|
2009-05-29 05:23:58 -07:00
|
|
|
* The high two bits of JSFunction.flags encode whether the function is native
|
|
|
|
* or interpreted, and if interpreted, what kind of optimized closure form (if
|
2009-04-05 21:17:22 -07:00
|
|
|
* any) it might be.
|
|
|
|
*
|
|
|
|
* 00 not interpreted
|
|
|
|
* 01 interpreted, neither flat nor null closure
|
|
|
|
* 10 interpreted, flat closure
|
|
|
|
* 11 interpreted, null closure
|
|
|
|
*
|
|
|
|
* FUN_FLAT_CLOSURE implies FUN_INTERPRETED and u.i.script->upvarsOffset != 0.
|
|
|
|
* FUN_NULL_CLOSURE implies FUN_INTERPRETED and u.i.script->upvarsOffset == 0.
|
|
|
|
*
|
|
|
|
* FUN_INTERPRETED but not FUN_FLAT_CLOSURE and u.i.script->upvarsOffset != 0
|
|
|
|
* is an Algol-like function expression or nested function, i.e., a function
|
|
|
|
* that never escapes upward or downward (heapward), and is only ever called.
|
|
|
|
*
|
|
|
|
* Finally, FUN_INTERPRETED and u.i.script->upvarsOffset == 0 could be either
|
|
|
|
* a non-closure (a global function definition, or any function that uses no
|
|
|
|
* outer names), or a closure of an escaping function that uses outer names
|
|
|
|
* whose values can't be snapshot (because the outer names could be reassigned
|
|
|
|
* after the closure is formed, or because assignments could not be analyzed
|
|
|
|
* due to with or eval).
|
|
|
|
*
|
|
|
|
* Such a hard-case function must use JSOP_NAME, etc., and reify outer function
|
|
|
|
* activations' call objects, etc. if it's not a global function.
|
|
|
|
*
|
|
|
|
* NB: JSFUN_EXPR_CLOSURE reuses JSFUN_STUB_GSOPS, which is an API request flag
|
|
|
|
* bit only, never stored in fun->flags.
|
|
|
|
*
|
|
|
|
* If we need more bits in the future, all flags for FUN_INTERPRETED functions
|
|
|
|
* can move to u.i.script->flags. For now we use function flag bits to minimize
|
|
|
|
* pointer-chasing.
|
|
|
|
*/
|
2010-07-23 14:41:56 -07:00
|
|
|
#define JSFUN_JOINABLE 0x0001 /* function is null closure that does not
|
|
|
|
appear to call itself via its own name
|
|
|
|
or arguments.callee */
|
|
|
|
|
2010-10-03 22:46:39 -07:00
|
|
|
#define JSFUN_PROTOTYPE 0x0800 /* function is Function.prototype for some
|
|
|
|
global object */
|
|
|
|
|
2009-04-05 21:17:22 -07:00
|
|
|
#define JSFUN_EXPR_CLOSURE 0x1000 /* expression closure: function(x) x*x */
|
2009-09-04 13:44:31 -07:00
|
|
|
#define JSFUN_TRCINFO 0x2000 /* when set, u.n.trcinfo is non-null,
|
|
|
|
JSFunctionSpec::call points to a
|
|
|
|
JSNativeTraceInfo. */
|
2009-04-05 21:17:22 -07:00
|
|
|
#define JSFUN_INTERPRETED 0x4000 /* use u.i if kind >= this value else u.n */
|
2011-03-15 12:18:36 -07:00
|
|
|
#define JSFUN_FLAT_CLOSURE 0x8000 /* flat (aka "display") closure */
|
2009-04-05 21:17:22 -07:00
|
|
|
#define JSFUN_NULL_CLOSURE 0xc000 /* null closure entrains no scope chain */
|
|
|
|
#define JSFUN_KINDMASK 0xc000 /* encode interp vs. native and closure
|
|
|
|
optimization level -- see above */
|
2007-08-01 21:33:52 -07:00
|
|
|
|
2009-10-02 01:21:19 -07:00
|
|
|
#define FUN_OBJECT(fun) (static_cast<JSObject *>(fun))
|
2009-04-05 21:17:22 -07:00
|
|
|
#define FUN_KIND(fun) ((fun)->flags & JSFUN_KINDMASK)
|
|
|
|
#define FUN_SET_KIND(fun,k) ((fun)->flags = ((fun)->flags & ~JSFUN_KINDMASK) | (k))
|
|
|
|
#define FUN_INTERPRETED(fun) (FUN_KIND(fun) >= JSFUN_INTERPRETED)
|
|
|
|
#define FUN_FLAT_CLOSURE(fun)(FUN_KIND(fun) == JSFUN_FLAT_CLOSURE)
|
|
|
|
#define FUN_NULL_CLOSURE(fun)(FUN_KIND(fun) == JSFUN_NULL_CLOSURE)
|
2011-05-20 11:27:27 -07:00
|
|
|
#define FUN_SCRIPT(fun) (FUN_INTERPRETED(fun) ? (fun)->script() : NULL)
|
2008-10-08 15:08:33 -07:00
|
|
|
#define FUN_CLASP(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
|
2009-03-03 22:53:27 -08:00
|
|
|
fun->u.n.clasp)
|
2008-10-08 15:08:33 -07:00
|
|
|
#define FUN_TRCINFO(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
|
2009-09-04 13:44:31 -07:00
|
|
|
JS_ASSERT((fun)->flags & JSFUN_TRCINFO), \
|
2009-03-03 22:53:27 -08:00
|
|
|
fun->u.n.trcinfo)
|
2008-10-08 15:08:33 -07:00
|
|
|
|
2010-10-13 11:49:22 -07:00
|
|
|
struct JSFunction : public JSObject_Slots2
|
2010-02-10 15:17:52 -08:00
|
|
|
{
|
2010-10-13 11:49:22 -07:00
|
|
|
/* Functions always have two fixed slots (FUN_CLASS_RESERVED_SLOTS). */
|
|
|
|
|
2009-05-29 05:23:58 -07:00
|
|
|
uint16 nargs; /* maximum number of specified arguments,
|
|
|
|
reflected as f.length/f.arity */
|
|
|
|
uint16 flags; /* flags, see JSFUN_* below and in jsapi.h */
|
2010-06-17 18:36:28 -07:00
|
|
|
union U {
|
2009-05-29 05:23:58 -07:00
|
|
|
struct {
|
2010-07-14 23:19:36 -07:00
|
|
|
js::Native native; /* native method pointer or null */
|
|
|
|
js::Class *clasp; /* class of objects constructed
|
2009-05-29 05:23:58 -07:00
|
|
|
by this function */
|
2009-09-04 13:44:31 -07:00
|
|
|
JSNativeTraceInfo *trcinfo;
|
2009-05-29 05:23:58 -07:00
|
|
|
} n;
|
2010-06-17 18:36:28 -07:00
|
|
|
struct Scripted {
|
2010-10-15 19:11:51 -07:00
|
|
|
JSScript *script; /* interpreted bytecode descriptor or null */
|
2009-06-04 18:58:47 -07:00
|
|
|
uint16 skipmin; /* net skip amount up (toward zero) from
|
|
|
|
script->staticLevel to nearest upvar,
|
|
|
|
including upvars in nested functions */
|
|
|
|
JSPackedBool wrapper; /* true if this function is a wrapper that
|
|
|
|
rewrites bytecode optimized for a function
|
|
|
|
judged non-escaping by the compiler, which
|
|
|
|
then escaped via the debugger or a rogue
|
|
|
|
indirect eval; if true, then this function
|
|
|
|
object's proto is the wrapped object */
|
2010-08-29 11:57:08 -07:00
|
|
|
js::Shape *names; /* argument and variable names */
|
2009-05-29 05:23:58 -07:00
|
|
|
} i;
|
2010-10-15 19:11:51 -07:00
|
|
|
void *nativeOrScript;
|
2009-05-29 05:23:58 -07:00
|
|
|
} u;
|
|
|
|
JSAtom *atom; /* name for diagnostics and decompiling */
|
|
|
|
|
2010-08-03 12:20:48 -07:00
|
|
|
bool optimizedClosure() const { return FUN_KIND(this) > JSFUN_INTERPRETED; }
|
|
|
|
bool isInterpreted() const { return FUN_INTERPRETED(this); }
|
2010-08-16 12:35:04 -07:00
|
|
|
bool isNative() const { return !FUN_INTERPRETED(this); }
|
|
|
|
bool isConstructor() const { return flags & JSFUN_CONSTRUCTOR; }
|
2010-08-03 12:20:48 -07:00
|
|
|
bool isHeavyweight() const { return JSFUN_HEAVYWEIGHT_TEST(flags); }
|
2010-11-16 14:13:29 -08:00
|
|
|
bool isFlatClosure() const { return FUN_KIND(this) == JSFUN_FLAT_CLOSURE; }
|
2010-10-03 22:46:39 -07:00
|
|
|
bool isFunctionPrototype() const { return flags & JSFUN_PROTOTYPE; }
|
2011-04-25 15:28:30 -07:00
|
|
|
bool isInterpretedConstructor() const { return isInterpreted() && !isFunctionPrototype(); }
|
2010-12-22 18:06:08 -08:00
|
|
|
/* Returns the strictness of this function, which must be interpreted. */
|
2010-08-11 23:26:59 -07:00
|
|
|
inline bool inStrictMode() const;
|
2010-11-16 15:34:24 -08:00
|
|
|
void setArgCount(uint16 nargs) {
|
|
|
|
JS_ASSERT(this->nargs == 0);
|
|
|
|
this->nargs = nargs;
|
2010-01-15 11:32:14 -08:00
|
|
|
}
|
|
|
|
|
2010-06-01 15:01:11 -07:00
|
|
|
/* uint16 representation bounds number of call object dynamic slots. */
|
2010-06-01 17:21:01 -07:00
|
|
|
enum { MAX_ARGS_AND_VARS = 2 * ((1U << 16) - 1) };
|
2010-06-01 15:01:11 -07:00
|
|
|
|
2010-08-29 11:57:08 -07:00
|
|
|
#define JS_LOCAL_NAME_TO_ATOM(nameWord) ((JSAtom *) ((nameWord) & ~(jsuword) 1))
|
|
|
|
#define JS_LOCAL_NAME_IS_CONST(nameWord) ((((nameWord) & (jsuword) 1)) != 0)
|
2010-02-10 15:17:52 -08:00
|
|
|
|
|
|
|
bool mightEscape() const {
|
2010-11-16 15:34:24 -08:00
|
|
|
return isInterpreted() && (isFlatClosure() || !script()->bindings.hasUpvars());
|
2010-02-10 15:17:52 -08:00
|
|
|
}
|
2010-07-23 14:41:56 -07:00
|
|
|
|
|
|
|
bool joinable() const {
|
|
|
|
return flags & JSFUN_JOINABLE;
|
|
|
|
}
|
|
|
|
|
2010-08-09 22:43:33 -07:00
|
|
|
JSObject &compiledFunObj() {
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2010-07-23 14:41:56 -07:00
|
|
|
private:
|
|
|
|
/*
|
|
|
|
* js_FunctionClass reserves two slots, which are free in JSObject::fslots
|
|
|
|
* without requiring dslots allocation. Null closures that can be joined to
|
|
|
|
* a compiler-created function object use the first one to hold a mutable
|
|
|
|
* methodAtom() state variable, needed for correct foo.caller handling.
|
|
|
|
*/
|
|
|
|
enum {
|
|
|
|
METHOD_ATOM_SLOT = JSSLOT_FUN_METHOD_ATOM
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
2011-07-13 15:43:33 -07:00
|
|
|
inline void setJoinable();
|
2010-07-23 14:41:56 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Method name imputed from property uniquely assigned to or initialized,
|
|
|
|
* where the function does not need to be cloned to carry a scope chain or
|
|
|
|
* flattened upvars.
|
|
|
|
*/
|
|
|
|
JSAtom *methodAtom() const {
|
2010-10-13 11:49:22 -07:00
|
|
|
return (joinable() && getSlot(METHOD_ATOM_SLOT).isString())
|
2011-03-14 13:59:53 -07:00
|
|
|
? &getSlot(METHOD_ATOM_SLOT).toString()->asAtom()
|
2010-07-23 14:41:56 -07:00
|
|
|
: NULL;
|
|
|
|
}
|
|
|
|
|
2011-07-13 15:43:33 -07:00
|
|
|
inline void setMethodAtom(JSAtom *atom);
|
2010-08-29 11:57:08 -07:00
|
|
|
|
2010-08-09 22:43:33 -07:00
|
|
|
JSScript *script() const {
|
|
|
|
JS_ASSERT(isInterpreted());
|
|
|
|
return u.i.script;
|
|
|
|
}
|
|
|
|
|
2011-05-13 08:56:26 -07:00
|
|
|
js::Native native() const {
|
|
|
|
JS_ASSERT(isNative());
|
|
|
|
return u.n.native;
|
|
|
|
}
|
|
|
|
|
2011-03-28 19:27:14 -07:00
|
|
|
js::Native maybeNative() const {
|
|
|
|
return isInterpreted() ? NULL : native();
|
2010-08-09 22:43:33 -07:00
|
|
|
}
|
|
|
|
|
2010-10-15 19:11:51 -07:00
|
|
|
static uintN offsetOfNativeOrScript() {
|
|
|
|
JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, i.script));
|
|
|
|
JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, nativeOrScript));
|
|
|
|
return offsetof(JSFunction, u.nativeOrScript);
|
|
|
|
}
|
|
|
|
|
2010-10-13 11:49:22 -07:00
|
|
|
/* Number of extra fixed function object slots. */
|
2010-08-29 11:57:08 -07:00
|
|
|
static const uint32 CLASS_RESERVED_SLOTS = JSObject::FUN_CLASS_RESERVED_SLOTS;
|
2009-05-29 05:23:58 -07:00
|
|
|
};
|
|
|
|
|
2008-10-08 15:08:33 -07:00
|
|
|
/*
|
2009-09-04 13:44:31 -07:00
|
|
|
* Trace-annotated native. This expands to a JSFunctionSpec initializer (like
|
2010-07-14 23:19:36 -07:00
|
|
|
* JS_FN in jsapi.h). fastcall is a FastNative; trcinfo is a
|
2009-09-04 13:44:31 -07:00
|
|
|
* JSNativeTraceInfo*.
|
2008-10-08 15:08:33 -07:00
|
|
|
*/
|
|
|
|
#ifdef JS_TRACER
|
|
|
|
/* MSVC demands the intermediate (void *) cast here. */
|
2011-06-10 19:03:57 -07:00
|
|
|
# define JS_TN(name,fastcall,nargs,flags,trcinfo) \
|
|
|
|
JS_FN(name, JS_DATA_TO_FUNC_PTR(Native, trcinfo), nargs, \
|
|
|
|
(flags) | JSFUN_STUB_GSOPS | JSFUN_TRCINFO)
|
2008-10-08 15:08:33 -07:00
|
|
|
#else
|
2011-06-10 19:03:57 -07:00
|
|
|
# define JS_TN(name,fastcall,nargs,flags,trcinfo) \
|
|
|
|
JS_FN(name, fastcall, nargs, flags)
|
2008-10-08 15:08:33 -07:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-07-14 23:19:36 -07:00
|
|
|
extern JS_PUBLIC_DATA(js::Class) js_CallClass;
|
|
|
|
extern JS_PUBLIC_DATA(js::Class) js_FunctionClass;
|
2011-05-05 08:53:36 -07:00
|
|
|
extern JS_FRIEND_DATA(js::Class) js_DeclEnvClass;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-12-30 13:49:26 -08:00
|
|
|
inline bool
|
2010-08-29 11:57:08 -07:00
|
|
|
JSObject::isCall() const
|
2009-12-30 13:49:26 -08:00
|
|
|
{
|
2010-08-29 11:57:08 -07:00
|
|
|
return getClass() == &js_CallClass;
|
2009-12-30 13:49:26 -08:00
|
|
|
}
|
|
|
|
|
2010-06-16 14:13:01 -07:00
|
|
|
inline bool
|
2010-08-29 11:57:08 -07:00
|
|
|
JSObject::isFunction() const
|
2010-06-16 14:13:01 -07:00
|
|
|
{
|
2010-08-29 11:57:08 -07:00
|
|
|
return getClass() == &js_FunctionClass;
|
2010-06-16 14:13:01 -07:00
|
|
|
}
|
|
|
|
|
2010-08-16 12:35:04 -07:00
|
|
|
inline JSFunction *
|
|
|
|
JSObject::getFunctionPrivate() const
|
|
|
|
{
|
|
|
|
JS_ASSERT(isFunction());
|
|
|
|
return reinterpret_cast<JSFunction *>(getPrivate());
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace js {
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
/*
|
|
|
|
* NB: jsapi.h and jsobj.h must be included before any call to this macro.
|
|
|
|
*/
|
|
|
|
#define VALUE_IS_FUNCTION(cx, v) \
|
2010-03-31 22:13:51 -07:00
|
|
|
(!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isFunction())
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-07-14 23:19:36 -07:00
|
|
|
static JS_ALWAYS_INLINE bool
|
|
|
|
IsFunctionObject(const js::Value &v)
|
|
|
|
{
|
|
|
|
return v.isObject() && v.toObject().isFunction();
|
|
|
|
}
|
|
|
|
|
|
|
|
static JS_ALWAYS_INLINE bool
|
|
|
|
IsFunctionObject(const js::Value &v, JSObject **funobj)
|
|
|
|
{
|
|
|
|
return v.isObject() && (*funobj = &v.toObject())->isFunction();
|
|
|
|
}
|
|
|
|
|
2010-08-16 12:35:04 -07:00
|
|
|
static JS_ALWAYS_INLINE bool
|
2011-06-14 16:36:13 -07:00
|
|
|
IsFunctionObject(const js::Value &v, JSObject **funobj, JSFunction **fun)
|
2010-08-16 12:35:04 -07:00
|
|
|
{
|
2011-06-14 16:36:13 -07:00
|
|
|
bool b = IsFunctionObject(v, funobj);
|
2010-08-16 12:35:04 -07:00
|
|
|
if (b)
|
2011-06-14 16:36:13 -07:00
|
|
|
*fun = (*funobj)->getFunctionPrivate();
|
2010-08-16 12:35:04 -07:00
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2011-06-14 16:36:13 -07:00
|
|
|
static JS_ALWAYS_INLINE bool
|
|
|
|
IsFunctionObject(const js::Value &v, JSFunction **fun)
|
|
|
|
{
|
|
|
|
JSObject *funobj;
|
|
|
|
return IsFunctionObject(v, &funobj, fun);
|
|
|
|
}
|
|
|
|
|
2011-05-13 08:56:26 -07:00
|
|
|
static JS_ALWAYS_INLINE bool
|
|
|
|
IsNativeFunction(const js::Value &v)
|
|
|
|
{
|
|
|
|
JSFunction *fun;
|
|
|
|
return IsFunctionObject(v, &fun) && fun->isNative();
|
|
|
|
}
|
|
|
|
|
|
|
|
static JS_ALWAYS_INLINE bool
|
|
|
|
IsNativeFunction(const js::Value &v, JSFunction **fun)
|
|
|
|
{
|
|
|
|
return IsFunctionObject(v, fun) && (*fun)->isNative();
|
|
|
|
}
|
|
|
|
|
2011-03-28 19:27:14 -07:00
|
|
|
static JS_ALWAYS_INLINE bool
|
|
|
|
IsNativeFunction(const js::Value &v, Native native)
|
|
|
|
{
|
|
|
|
JSFunction *fun;
|
|
|
|
return IsFunctionObject(v, &fun) && fun->maybeNative() == native;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* When we have an object of a builtin class, we don't quite know what its
|
|
|
|
* valueOf/toString methods are, since these methods may have been overwritten
|
|
|
|
* or shadowed. However, we can still do better than js_TryMethod by
|
|
|
|
* hard-coding the necessary properties for us to find the native we expect.
|
|
|
|
*
|
|
|
|
* TODO: a per-thread shape-based cache would be faster and simpler.
|
|
|
|
*/
|
|
|
|
static JS_ALWAYS_INLINE bool
|
|
|
|
ClassMethodIsNative(JSContext *cx, JSObject *obj, Class *clasp, jsid methodid, Native native)
|
|
|
|
{
|
|
|
|
JS_ASSERT(obj->getClass() == clasp);
|
|
|
|
|
|
|
|
Value v;
|
|
|
|
if (!HasDataProperty(obj, methodid, &v)) {
|
|
|
|
JSObject *proto = obj->getProto();
|
|
|
|
if (!proto || proto->getClass() != clasp || !HasDataProperty(proto, methodid, &v))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return js::IsNativeFunction(v, native);
|
|
|
|
}
|
|
|
|
|
2010-11-18 10:49:45 -08:00
|
|
|
extern JS_ALWAYS_INLINE bool
|
|
|
|
SameTraceType(const Value &lhs, const Value &rhs)
|
|
|
|
{
|
|
|
|
return SameType(lhs, rhs) &&
|
|
|
|
(lhs.isPrimitive() ||
|
|
|
|
lhs.toObject().isFunction() == rhs.toObject().isFunction());
|
|
|
|
}
|
|
|
|
|
2008-03-28 15:27:36 -07:00
|
|
|
/*
|
|
|
|
* Macro to access the private slot of the function object after the slot is
|
|
|
|
* initialized.
|
|
|
|
*/
|
|
|
|
#define GET_FUNCTION_PRIVATE(cx, funobj) \
|
2010-03-31 22:13:51 -07:00
|
|
|
(JS_ASSERT((funobj)->isFunction()), \
|
2009-09-05 08:59:11 -07:00
|
|
|
(JSFunction *) (funobj)->getPrivate())
|
2008-03-28 15:27:36 -07:00
|
|
|
|
2009-10-05 16:55:21 -07:00
|
|
|
/*
|
|
|
|
* Return true if this is a compiler-created internal function accessed by
|
|
|
|
* its own object. Such a function object must not be accessible to script
|
|
|
|
* or embedding code.
|
|
|
|
*/
|
|
|
|
inline bool
|
2010-03-30 00:44:28 -07:00
|
|
|
IsInternalFunctionObject(JSObject *funobj)
|
2009-10-05 16:55:21 -07:00
|
|
|
{
|
2010-03-31 22:13:51 -07:00
|
|
|
JS_ASSERT(funobj->isFunction());
|
2009-10-05 16:55:21 -07:00
|
|
|
JSFunction *fun = (JSFunction *) funobj->getPrivate();
|
|
|
|
return funobj == fun && (fun->flags & JSFUN_LAMBDA) && !funobj->getParent();
|
|
|
|
}
|
2010-03-30 00:44:28 -07:00
|
|
|
|
2010-08-16 12:35:04 -07:00
|
|
|
/* Valueified JS_IsConstructing. */
|
|
|
|
static JS_ALWAYS_INLINE bool
|
|
|
|
IsConstructing(const Value *vp)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
JSObject *callee = &JS_CALLEE(cx, vp).toObject();
|
|
|
|
if (callee->isFunction()) {
|
|
|
|
JSFunction *fun = callee->getFunctionPrivate();
|
|
|
|
JS_ASSERT((fun->flags & JSFUN_CONSTRUCTOR) != 0);
|
|
|
|
} else {
|
|
|
|
JS_ASSERT(callee->getClass()->construct != NULL);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return vp[1].isMagic();
|
|
|
|
}
|
|
|
|
|
|
|
|
static JS_ALWAYS_INLINE bool
|
|
|
|
IsConstructing_PossiblyWithGivenThisObject(const Value *vp, JSObject **ctorThis)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
JSObject *callee = &JS_CALLEE(cx, vp).toObject();
|
|
|
|
if (callee->isFunction()) {
|
|
|
|
JSFunction *fun = callee->getFunctionPrivate();
|
|
|
|
JS_ASSERT((fun->flags & JSFUN_CONSTRUCTOR) != 0);
|
|
|
|
} else {
|
|
|
|
JS_ASSERT(callee->getClass()->construct != NULL);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
bool isCtor = vp[1].isMagic();
|
|
|
|
if (isCtor)
|
|
|
|
*ctorThis = vp[1].getMagicObjectOrNullPayload();
|
|
|
|
return isCtor;
|
|
|
|
}
|
|
|
|
|
2010-11-11 12:40:29 -08:00
|
|
|
inline const char *
|
|
|
|
GetFunctionNameBytes(JSContext *cx, JSFunction *fun, JSAutoByteString *bytes)
|
|
|
|
{
|
|
|
|
if (fun->atom)
|
2011-03-14 13:59:53 -07:00
|
|
|
return bytes->encode(cx, fun->atom);
|
2010-11-11 12:40:29 -08:00
|
|
|
return js_anonymous_str;
|
|
|
|
}
|
|
|
|
|
2011-03-02 19:57:44 -08:00
|
|
|
extern bool
|
2011-01-26 18:28:49 -08:00
|
|
|
IsBuiltinFunctionConstructor(JSFunction *fun);
|
|
|
|
|
2011-02-14 12:04:07 -08:00
|
|
|
/*
|
|
|
|
* Preconditions: funobj->isInterpreted() && !funobj->isFunctionPrototype() &&
|
|
|
|
* !funobj->isBoundFunction(). This is sufficient to establish that funobj has
|
|
|
|
* a non-configurable non-method .prototype data property, thought it might not
|
|
|
|
* have been resolved yet, and its value could be anything.
|
|
|
|
*
|
|
|
|
* Return the shape of the .prototype property of funobj, resolving it if
|
|
|
|
* needed. On error, return NULL.
|
|
|
|
*
|
|
|
|
* This is not safe to call on trace because it defines properties, which can
|
|
|
|
* trigger lookups that could reenter.
|
|
|
|
*/
|
|
|
|
const Shape *
|
|
|
|
LookupInterpretedFunctionPrototype(JSContext *cx, JSObject *funobj);
|
|
|
|
|
2010-08-16 12:35:04 -07:00
|
|
|
} /* namespace js */
|
|
|
|
|
2010-08-02 23:52:12 -07:00
|
|
|
extern JSString *
|
|
|
|
fun_toStringHelper(JSContext *cx, JSObject *obj, uintN indent);
|
|
|
|
|
2010-08-16 12:35:04 -07:00
|
|
|
extern JSFunction *
|
|
|
|
js_NewFunction(JSContext *cx, JSObject *funobj, js::Native native, uintN nargs,
|
2011-06-10 19:03:57 -07:00
|
|
|
uintN flags, JSObject *parent, JSAtom *atom);
|
2010-03-30 00:44:28 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
extern JSObject *
|
|
|
|
js_InitFunctionClass(JSContext *cx, JSObject *obj);
|
|
|
|
|
|
|
|
extern JSObject *
|
|
|
|
js_InitArgumentsClass(JSContext *cx, JSObject *obj);
|
|
|
|
|
2007-08-04 00:00:43 -07:00
|
|
|
extern void
|
2008-03-29 03:34:29 -07:00
|
|
|
js_FinalizeFunction(JSContext *cx, JSFunction *fun);
|
2007-08-04 00:00:43 -07:00
|
|
|
|
2010-01-15 11:32:14 -08:00
|
|
|
extern JSObject * JS_FASTCALL
|
2010-02-19 09:44:23 -08:00
|
|
|
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
|
|
|
|
JSObject *proto);
|
|
|
|
|
|
|
|
inline JSObject *
|
2011-06-03 20:48:16 -07:00
|
|
|
CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
|
|
|
|
bool ignoreSingletonClone = false)
|
2010-02-19 09:44:23 -08:00
|
|
|
{
|
|
|
|
JS_ASSERT(parent);
|
|
|
|
JSObject *proto;
|
|
|
|
if (!js_GetClassPrototype(cx, parent, JSProto_Function, &proto))
|
|
|
|
return NULL;
|
2011-06-03 20:48:16 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* For attempts to clone functions at a function definition opcode or from
|
|
|
|
* a method barrier, don't perform the clone if the function has singleton
|
|
|
|
* type. CloneFunctionObject was called pessimistically, and we need to
|
|
|
|
* preserve the type's property that if it is singleton there is only a
|
|
|
|
* single object with its type in existence.
|
|
|
|
*/
|
2011-07-15 10:14:07 -07:00
|
|
|
if (ignoreSingletonClone && fun->hasSingletonType()) {
|
2011-06-03 20:48:16 -07:00
|
|
|
JS_ASSERT(fun->getProto() == proto);
|
|
|
|
fun->setParent(parent);
|
|
|
|
return fun;
|
|
|
|
}
|
|
|
|
|
2010-02-19 09:44:23 -08:00
|
|
|
return js_CloneFunctionObject(cx, fun, parent, proto);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-08-29 11:57:08 -07:00
|
|
|
extern JSObject * JS_FASTCALL
|
|
|
|
js_AllocFlatClosure(JSContext *cx, JSFunction *fun, JSObject *scopeChain);
|
|
|
|
|
2010-12-29 23:46:50 -08:00
|
|
|
extern JSObject *
|
2010-10-06 10:41:36 -07:00
|
|
|
js_NewFlatClosure(JSContext *cx, JSFunction *fun, JSOp op, size_t oplen);
|
2008-03-29 03:34:29 -07:00
|
|
|
|
|
|
|
extern JSFunction *
|
2010-10-28 08:15:53 -07:00
|
|
|
js_DefineFunction(JSContext *cx, JSObject *obj, jsid id, js::Native native,
|
2011-06-10 19:03:57 -07:00
|
|
|
uintN nargs, uintN flags);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
/*
|
2011-05-24 16:04:18 -07:00
|
|
|
* Flags for js_ValueToFunction and js_ReportIsNotFunction.
|
2007-03-22 10:30:00 -07:00
|
|
|
*/
|
2011-07-07 21:02:57 -07:00
|
|
|
#define JSV2F_CONSTRUCT INITIAL_CONSTRUCT
|
2007-03-22 10:30:00 -07:00
|
|
|
#define JSV2F_SEARCH_STACK 0x10000
|
|
|
|
|
|
|
|
extern JSFunction *
|
2010-07-14 23:19:36 -07:00
|
|
|
js_ValueToFunction(JSContext *cx, const js::Value *vp, uintN flags);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
extern JSObject *
|
2010-07-14 23:19:36 -07:00
|
|
|
js_ValueToFunctionObject(JSContext *cx, js::Value *vp, uintN flags);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
extern JSObject *
|
2010-07-14 23:19:36 -07:00
|
|
|
js_ValueToCallableObject(JSContext *cx, js::Value *vp, uintN flags);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
extern void
|
2010-07-14 23:19:36 -07:00
|
|
|
js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, uintN flags);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-01-15 11:32:14 -08:00
|
|
|
extern JSObject * JS_FASTCALL
|
|
|
|
js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSObject *scopeChain);
|
|
|
|
|
2009-08-14 11:43:16 -07:00
|
|
|
extern void
|
2011-04-13 09:27:37 -07:00
|
|
|
js_PutCallObject(js::StackFrame *fp);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-01-15 11:32:14 -08:00
|
|
|
extern JSBool JS_FASTCALL
|
2011-04-13 09:27:37 -07:00
|
|
|
js_PutCallObjectOnTrace(JSObject *scopeChain, uint32 nargs, js::Value *argv,
|
|
|
|
uint32 nvars, js::Value *slots);
|
2010-01-15 11:32:14 -08:00
|
|
|
|
2010-11-16 15:30:57 -08:00
|
|
|
namespace js {
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-03-14 11:30:36 -07:00
|
|
|
JSObject *
|
2011-04-13 09:27:37 -07:00
|
|
|
CreateFunCallObject(JSContext *cx, StackFrame *fp);
|
2011-03-14 11:30:36 -07:00
|
|
|
|
|
|
|
JSObject *
|
2011-04-13 09:27:37 -07:00
|
|
|
CreateEvalCallObject(JSContext *cx, StackFrame *fp);
|
2011-03-14 11:30:36 -07:00
|
|
|
|
2009-06-25 12:12:20 -07:00
|
|
|
extern JSBool
|
2010-11-16 15:30:57 -08:00
|
|
|
GetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
2009-07-27 18:13:53 -07:00
|
|
|
|
|
|
|
extern JSBool
|
2010-11-16 15:30:57 -08:00
|
|
|
GetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-11-16 15:30:57 -08:00
|
|
|
extern JSBool
|
2010-12-29 23:46:50 -08:00
|
|
|
GetCallUpvar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
|
2010-11-16 15:30:57 -08:00
|
|
|
|
|
|
|
extern JSBool
|
2011-02-09 11:31:40 -08:00
|
|
|
SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
|
2010-11-16 15:30:57 -08:00
|
|
|
|
|
|
|
extern JSBool
|
2011-02-09 11:31:40 -08:00
|
|
|
SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
|
2010-11-16 15:34:24 -08:00
|
|
|
|
|
|
|
extern JSBool
|
2011-02-09 11:31:40 -08:00
|
|
|
SetCallUpvar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
|
2010-11-16 15:30:57 -08:00
|
|
|
|
|
|
|
} // namespace js
|
2009-06-09 00:51:02 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
extern JSBool
|
2011-04-13 09:27:37 -07:00
|
|
|
js_GetArgsValue(JSContext *cx, js::StackFrame *fp, js::Value *vp);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
extern JSBool
|
2011-04-13 09:27:37 -07:00
|
|
|
js_GetArgsProperty(JSContext *cx, js::StackFrame *fp, jsid id, js::Value *vp);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-08-11 23:27:33 -07:00
|
|
|
/*
|
|
|
|
* Get the arguments object for the given frame. If the frame is strict mode
|
|
|
|
* code, its current arguments will be copied into the arguments object.
|
|
|
|
*
|
|
|
|
* NB: Callers *must* get the arguments object before any parameters are
|
|
|
|
* mutated when the frame is strict mode code! The emitter ensures this
|
|
|
|
* occurs for strict mode functions containing syntax which might mutate a
|
|
|
|
* named parameter by synthesizing an arguments access at the start of the
|
|
|
|
* function.
|
|
|
|
*/
|
2007-03-22 10:30:00 -07:00
|
|
|
extern JSObject *
|
2011-04-13 09:27:37 -07:00
|
|
|
js_GetArgsObject(JSContext *cx, js::StackFrame *fp);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-08-14 11:43:16 -07:00
|
|
|
extern void
|
2011-04-13 09:27:37 -07:00
|
|
|
js_PutArgsObject(js::StackFrame *fp);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-01-15 11:32:14 -08:00
|
|
|
inline bool
|
|
|
|
js_IsNamedLambda(JSFunction *fun) { return (fun->flags & JSFUN_LAMBDA) && fun->atom; }
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
extern JSBool
|
2009-05-06 16:03:10 -07:00
|
|
|
js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-25 12:12:19 -07:00
|
|
|
extern JSBool
|
2010-07-14 23:19:36 -07:00
|
|
|
js_fun_apply(JSContext *cx, uintN argc, js::Value *vp);
|
2008-10-29 23:59:19 -07:00
|
|
|
|
2009-06-25 12:12:19 -07:00
|
|
|
extern JSBool
|
2010-07-14 23:19:36 -07:00
|
|
|
js_fun_call(JSContext *cx, uintN argc, js::Value *vp);
|
2008-10-29 23:59:19 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif /* jsfun_h___ */
|