1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jsfun.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,676 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jsfun_h 1.11 +#define jsfun_h 1.12 + 1.13 +/* 1.14 + * JS function definitions. 1.15 + */ 1.16 + 1.17 +#include "jsobj.h" 1.18 +#include "jsscript.h" 1.19 +#include "jstypes.h" 1.20 + 1.21 +namespace js { 1.22 +class FunctionExtended; 1.23 + 1.24 +typedef JSNative Native; 1.25 +typedef JSParallelNative ParallelNative; 1.26 +typedef JSThreadSafeNative ThreadSafeNative; 1.27 +} 1.28 + 1.29 +struct JSAtomState; 1.30 + 1.31 +class JSFunction : public JSObject 1.32 +{ 1.33 + public: 1.34 + static const js::Class class_; 1.35 + 1.36 + enum Flags { 1.37 + INTERPRETED = 0x0001, /* function has a JSScript and environment. */ 1.38 + NATIVE_CTOR = 0x0002, /* native that can be called as a constructor */ 1.39 + EXTENDED = 0x0004, /* structure is FunctionExtended */ 1.40 + IS_FUN_PROTO = 0x0010, /* function is Function.prototype for some global object */ 1.41 + EXPR_CLOSURE = 0x0020, /* expression closure: function(x) x*x */ 1.42 + HAS_GUESSED_ATOM = 0x0040, /* function had no explicit name, but a 1.43 + name was guessed for it anyway */ 1.44 + LAMBDA = 0x0080, /* function comes from a FunctionExpression, ArrowFunction, or 1.45 + Function() call (not a FunctionDeclaration or nonstandard 1.46 + function-statement) */ 1.47 + SELF_HOSTED = 0x0100, /* function is self-hosted builtin and must not be 1.48 + decompilable nor constructible. */ 1.49 + SELF_HOSTED_CTOR = 0x0200, /* function is self-hosted builtin constructor and 1.50 + must be constructible but not decompilable. */ 1.51 + HAS_REST = 0x0400, /* function has a rest (...) parameter */ 1.52 + // 0x0800 is available 1.53 + INTERPRETED_LAZY = 0x1000, /* function is interpreted but doesn't have a script yet */ 1.54 + ARROW = 0x2000, /* ES6 '(args) => body' syntax */ 1.55 + 1.56 + /* Derived Flags values for convenience: */ 1.57 + NATIVE_FUN = 0, 1.58 + NATIVE_LAMBDA_FUN = NATIVE_FUN | LAMBDA, 1.59 + INTERPRETED_LAMBDA = INTERPRETED | LAMBDA, 1.60 + INTERPRETED_LAMBDA_ARROW = INTERPRETED | LAMBDA | ARROW 1.61 + }; 1.62 + 1.63 + static void staticAsserts() { 1.64 + JS_STATIC_ASSERT(INTERPRETED == JS_FUNCTION_INTERPRETED_BIT); 1.65 + static_assert(sizeof(JSFunction) == sizeof(js::shadow::Function), 1.66 + "shadow interface must match actual interface"); 1.67 + } 1.68 + 1.69 + private: 1.70 + uint16_t nargs_; /* number of formal arguments 1.71 + (including defaults and the rest parameter unlike f.length) */ 1.72 + uint16_t flags_; /* bitfield composed of the above Flags enum */ 1.73 + union U { 1.74 + class Native { 1.75 + friend class JSFunction; 1.76 + js::Native native; /* native method pointer or null */ 1.77 + const JSJitInfo *jitinfo; /* Information about this function to be 1.78 + used by the JIT; 1.79 + use the accessor! */ 1.80 + } n; 1.81 + struct Scripted { 1.82 + union { 1.83 + JSScript *script_; /* interpreted bytecode descriptor or null; 1.84 + use the accessor! */ 1.85 + js::LazyScript *lazy_; /* lazily compiled script, or nullptr */ 1.86 + } s; 1.87 + JSObject *env_; /* environment for new activations; 1.88 + use the accessor! */ 1.89 + } i; 1.90 + void *nativeOrScript; 1.91 + } u; 1.92 + js::HeapPtrAtom atom_; /* name for diagnostics and decompiling */ 1.93 + 1.94 + public: 1.95 + 1.96 + /* Call objects must be created for each invocation of a heavyweight function. */ 1.97 + bool isHeavyweight() const { 1.98 + JS_ASSERT(!isInterpretedLazy()); 1.99 + 1.100 + if (isNative()) 1.101 + return false; 1.102 + 1.103 + // Note: this should be kept in sync with FunctionBox::isHeavyweight(). 1.104 + return nonLazyScript()->hasAnyAliasedBindings() || 1.105 + nonLazyScript()->funHasExtensibleScope() || 1.106 + nonLazyScript()->funNeedsDeclEnvObject() || 1.107 + isGenerator(); 1.108 + } 1.109 + 1.110 + size_t nargs() const { 1.111 + return nargs_; 1.112 + } 1.113 + 1.114 + uint16_t flags() const { 1.115 + return flags_; 1.116 + } 1.117 + 1.118 + /* A function can be classified as either native (C++) or interpreted (JS): */ 1.119 + bool isInterpreted() const { return flags() & (INTERPRETED | INTERPRETED_LAZY); } 1.120 + bool isNative() const { return !isInterpreted(); } 1.121 + 1.122 + /* Possible attributes of a native function: */ 1.123 + bool isNativeConstructor() const { return flags() & NATIVE_CTOR; } 1.124 + 1.125 + /* Possible attributes of an interpreted function: */ 1.126 + bool isFunctionPrototype() const { return flags() & IS_FUN_PROTO; } 1.127 + bool isExprClosure() const { return flags() & EXPR_CLOSURE; } 1.128 + bool hasGuessedAtom() const { return flags() & HAS_GUESSED_ATOM; } 1.129 + bool isLambda() const { return flags() & LAMBDA; } 1.130 + bool isSelfHostedBuiltin() const { return flags() & SELF_HOSTED; } 1.131 + bool isSelfHostedConstructor() const { return flags() & SELF_HOSTED_CTOR; } 1.132 + bool hasRest() const { return flags() & HAS_REST; } 1.133 + 1.134 + bool isInterpretedLazy() const { 1.135 + return flags() & INTERPRETED_LAZY; 1.136 + } 1.137 + bool hasScript() const { 1.138 + return flags() & INTERPRETED; 1.139 + } 1.140 + 1.141 + bool hasJITCode() const { 1.142 + if (!hasScript()) 1.143 + return false; 1.144 + 1.145 + return nonLazyScript()->hasBaselineScript() || nonLazyScript()->hasIonScript(); 1.146 + } 1.147 + 1.148 + // Arrow functions store their lexical |this| in the first extended slot. 1.149 + bool isArrow() const { return flags() & ARROW; } 1.150 + 1.151 + /* Compound attributes: */ 1.152 + bool isBuiltin() const { 1.153 + return isNative() || isSelfHostedBuiltin(); 1.154 + } 1.155 + bool isInterpretedConstructor() const { 1.156 + // Note: the JITs inline this check, so be careful when making changes 1.157 + // here. See IonMacroAssembler::branchIfNotInterpretedConstructor. 1.158 + return isInterpreted() && !isFunctionPrototype() && !isArrow() && 1.159 + (!isSelfHostedBuiltin() || isSelfHostedConstructor()); 1.160 + } 1.161 + bool isNamedLambda() const { 1.162 + return isLambda() && displayAtom() && !hasGuessedAtom(); 1.163 + } 1.164 + bool hasParallelNative() const { 1.165 + return isNative() && jitInfo() && jitInfo()->hasParallelNative(); 1.166 + } 1.167 + 1.168 + bool isBuiltinFunctionConstructor(); 1.169 + 1.170 + /* Returns the strictness of this function, which must be interpreted. */ 1.171 + bool strict() const { 1.172 + return nonLazyScript()->strict(); 1.173 + } 1.174 + 1.175 + void setFlags(uint16_t flags) { 1.176 + this->flags_ = flags; 1.177 + } 1.178 + 1.179 + // Can be called multiple times by the parser. 1.180 + void setArgCount(uint16_t nargs) { 1.181 + this->nargs_ = nargs; 1.182 + } 1.183 + 1.184 + // Can be called multiple times by the parser. 1.185 + void setHasRest() { 1.186 + flags_ |= HAS_REST; 1.187 + } 1.188 + 1.189 + void setIsSelfHostedBuiltin() { 1.190 + JS_ASSERT(!isSelfHostedBuiltin()); 1.191 + flags_ |= SELF_HOSTED; 1.192 + } 1.193 + 1.194 + void setIsSelfHostedConstructor() { 1.195 + JS_ASSERT(!isSelfHostedConstructor()); 1.196 + flags_ |= SELF_HOSTED_CTOR; 1.197 + } 1.198 + 1.199 + void setIsFunctionPrototype() { 1.200 + JS_ASSERT(!isFunctionPrototype()); 1.201 + flags_ |= IS_FUN_PROTO; 1.202 + } 1.203 + 1.204 + // Can be called multiple times by the parser. 1.205 + void setIsExprClosure() { 1.206 + flags_ |= EXPR_CLOSURE; 1.207 + } 1.208 + 1.209 + void setArrow() { 1.210 + flags_ |= ARROW; 1.211 + } 1.212 + 1.213 + JSAtom *atom() const { return hasGuessedAtom() ? nullptr : atom_.get(); } 1.214 + js::PropertyName *name() const { return hasGuessedAtom() || !atom_ ? nullptr : atom_->asPropertyName(); } 1.215 + void initAtom(JSAtom *atom) { atom_.init(atom); } 1.216 + 1.217 + JSAtom *displayAtom() const { 1.218 + return atom_; 1.219 + } 1.220 + 1.221 + void setGuessedAtom(JSAtom *atom) { 1.222 + JS_ASSERT(atom_ == nullptr); 1.223 + JS_ASSERT(atom != nullptr); 1.224 + JS_ASSERT(!hasGuessedAtom()); 1.225 + atom_ = atom; 1.226 + flags_ |= HAS_GUESSED_ATOM; 1.227 + } 1.228 + 1.229 + /* uint16_t representation bounds number of call object dynamic slots. */ 1.230 + enum { MAX_ARGS_AND_VARS = 2 * ((1U << 16) - 1) }; 1.231 + 1.232 + /* 1.233 + * For an interpreted function, accessors for the initial scope object of 1.234 + * activations (stack frames) of the function. 1.235 + */ 1.236 + JSObject *environment() const { 1.237 + JS_ASSERT(isInterpreted()); 1.238 + return u.i.env_; 1.239 + } 1.240 + 1.241 + void setEnvironment(JSObject *obj) { 1.242 + JS_ASSERT(isInterpreted()); 1.243 + *(js::HeapPtrObject *)&u.i.env_ = obj; 1.244 + } 1.245 + 1.246 + void initEnvironment(JSObject *obj) { 1.247 + JS_ASSERT(isInterpreted()); 1.248 + ((js::HeapPtrObject *)&u.i.env_)->init(obj); 1.249 + } 1.250 + 1.251 + static inline size_t offsetOfNargs() { return offsetof(JSFunction, nargs_); } 1.252 + static inline size_t offsetOfFlags() { return offsetof(JSFunction, flags_); } 1.253 + static inline size_t offsetOfEnvironment() { return offsetof(JSFunction, u.i.env_); } 1.254 + static inline size_t offsetOfAtom() { return offsetof(JSFunction, atom_); } 1.255 + 1.256 + static bool createScriptForLazilyInterpretedFunction(JSContext *cx, js::HandleFunction fun); 1.257 + void relazify(JSTracer *trc); 1.258 + 1.259 + // Function Scripts 1.260 + // 1.261 + // Interpreted functions may either have an explicit JSScript (hasScript()) 1.262 + // or be lazy with sufficient information to construct the JSScript if 1.263 + // necessary (isInterpretedLazy()). 1.264 + // 1.265 + // A lazy function will have a LazyScript if the function came from parsed 1.266 + // source, or nullptr if the function is a clone of a self hosted function. 1.267 + // 1.268 + // There are several methods to get the script of an interpreted function: 1.269 + // 1.270 + // - For all interpreted functions, getOrCreateScript() will get the 1.271 + // JSScript, delazifying the function if necessary. This is the safest to 1.272 + // use, but has extra checks, requires a cx and may trigger a GC. 1.273 + // 1.274 + // - For inlined functions which may have a LazyScript but whose JSScript 1.275 + // is known to exist, existingScriptForInlinedFunction() will get the 1.276 + // script and delazify the function if necessary. 1.277 + // 1.278 + // - For functions known to have a JSScript, nonLazyScript() will get it. 1.279 + 1.280 + JSScript *getOrCreateScript(JSContext *cx) { 1.281 + JS_ASSERT(isInterpreted()); 1.282 + JS_ASSERT(cx); 1.283 + if (isInterpretedLazy()) { 1.284 + JS::RootedFunction self(cx, this); 1.285 + if (!createScriptForLazilyInterpretedFunction(cx, self)) 1.286 + return nullptr; 1.287 + return self->nonLazyScript(); 1.288 + } 1.289 + return nonLazyScript(); 1.290 + } 1.291 + 1.292 + JSScript *existingScriptForInlinedFunction() { 1.293 + MOZ_ASSERT(isInterpreted()); 1.294 + if (isInterpretedLazy()) { 1.295 + // Get the script from the canonical function. Ion used the 1.296 + // canonical function to inline the script and because it has 1.297 + // Baseline code it has not been relazified. Note that we can't 1.298 + // use lazyScript->script_ here as it may be null in some cases, 1.299 + // see bug 976536. 1.300 + js::LazyScript *lazy = lazyScript(); 1.301 + JSFunction *fun = lazy->functionNonDelazifying(); 1.302 + MOZ_ASSERT(fun); 1.303 + JSScript *script = fun->nonLazyScript(); 1.304 + 1.305 + if (shadowZone()->needsBarrier()) 1.306 + js::LazyScript::writeBarrierPre(lazy); 1.307 + 1.308 + flags_ &= ~INTERPRETED_LAZY; 1.309 + flags_ |= INTERPRETED; 1.310 + initScript(script); 1.311 + } 1.312 + return nonLazyScript(); 1.313 + } 1.314 + 1.315 + JSScript *nonLazyScript() const { 1.316 + JS_ASSERT(hasScript()); 1.317 + JS_ASSERT(u.i.s.script_); 1.318 + return u.i.s.script_; 1.319 + } 1.320 + 1.321 + // Returns non-callsited-clone version of this. Use when return 1.322 + // value can flow to arbitrary JS (see Bug 944975). 1.323 + JSFunction* originalFunction() { 1.324 + if (this->hasScript() && this->nonLazyScript()->isCallsiteClone()) { 1.325 + return this->nonLazyScript()->donorFunction(); 1.326 + } else { 1.327 + return this; 1.328 + } 1.329 + } 1.330 + 1.331 + js::HeapPtrScript &mutableScript() { 1.332 + JS_ASSERT(isInterpreted()); 1.333 + return *(js::HeapPtrScript *)&u.i.s.script_; 1.334 + } 1.335 + 1.336 + js::LazyScript *lazyScript() const { 1.337 + JS_ASSERT(isInterpretedLazy() && u.i.s.lazy_); 1.338 + return u.i.s.lazy_; 1.339 + } 1.340 + 1.341 + js::LazyScript *lazyScriptOrNull() const { 1.342 + JS_ASSERT(isInterpretedLazy()); 1.343 + return u.i.s.lazy_; 1.344 + } 1.345 + 1.346 + js::GeneratorKind generatorKind() const { 1.347 + if (!isInterpreted()) 1.348 + return js::NotGenerator; 1.349 + if (hasScript()) 1.350 + return nonLazyScript()->generatorKind(); 1.351 + if (js::LazyScript *lazy = lazyScriptOrNull()) 1.352 + return lazy->generatorKind(); 1.353 + JS_ASSERT(isSelfHostedBuiltin()); 1.354 + return js::NotGenerator; 1.355 + } 1.356 + 1.357 + bool isGenerator() const { return generatorKind() != js::NotGenerator; } 1.358 + 1.359 + bool isLegacyGenerator() const { return generatorKind() == js::LegacyGenerator; } 1.360 + 1.361 + bool isStarGenerator() const { return generatorKind() == js::StarGenerator; } 1.362 + 1.363 + void setScript(JSScript *script_) { 1.364 + JS_ASSERT(hasScript()); 1.365 + mutableScript() = script_; 1.366 + } 1.367 + 1.368 + void initScript(JSScript *script_) { 1.369 + JS_ASSERT(hasScript()); 1.370 + mutableScript().init(script_); 1.371 + } 1.372 + 1.373 + void setUnlazifiedScript(JSScript *script) { 1.374 + // Note: createScriptForLazilyInterpretedFunction triggers a barrier on 1.375 + // lazy script before it is overwritten here. 1.376 + JS_ASSERT(isInterpretedLazy()); 1.377 + if (!lazyScript()->maybeScript()) 1.378 + lazyScript()->initScript(script); 1.379 + flags_ &= ~INTERPRETED_LAZY; 1.380 + flags_ |= INTERPRETED; 1.381 + initScript(script); 1.382 + } 1.383 + 1.384 + void initLazyScript(js::LazyScript *lazy) { 1.385 + JS_ASSERT(isInterpreted()); 1.386 + flags_ &= ~INTERPRETED; 1.387 + flags_ |= INTERPRETED_LAZY; 1.388 + u.i.s.lazy_ = lazy; 1.389 + } 1.390 + 1.391 + JSNative native() const { 1.392 + JS_ASSERT(isNative()); 1.393 + return u.n.native; 1.394 + } 1.395 + 1.396 + JSNative maybeNative() const { 1.397 + return isInterpreted() ? nullptr : native(); 1.398 + } 1.399 + 1.400 + JSParallelNative parallelNative() const { 1.401 + JS_ASSERT(hasParallelNative()); 1.402 + return jitInfo()->parallelNative; 1.403 + } 1.404 + 1.405 + JSParallelNative maybeParallelNative() const { 1.406 + return hasParallelNative() ? parallelNative() : nullptr; 1.407 + } 1.408 + 1.409 + void initNative(js::Native native, const JSJitInfo *jitinfo) { 1.410 + JS_ASSERT(native); 1.411 + u.n.native = native; 1.412 + u.n.jitinfo = jitinfo; 1.413 + } 1.414 + 1.415 + const JSJitInfo *jitInfo() const { 1.416 + JS_ASSERT(isNative()); 1.417 + return u.n.jitinfo; 1.418 + } 1.419 + 1.420 + void setJitInfo(const JSJitInfo *data) { 1.421 + JS_ASSERT(isNative()); 1.422 + u.n.jitinfo = data; 1.423 + } 1.424 + 1.425 + static unsigned offsetOfNativeOrScript() { 1.426 + JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, i.s.script_)); 1.427 + JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, nativeOrScript)); 1.428 + return offsetof(JSFunction, u.nativeOrScript); 1.429 + } 1.430 + 1.431 +#if JS_BITS_PER_WORD == 32 1.432 + static const js::gc::AllocKind FinalizeKind = js::gc::FINALIZE_OBJECT2_BACKGROUND; 1.433 + static const js::gc::AllocKind ExtendedFinalizeKind = js::gc::FINALIZE_OBJECT4_BACKGROUND; 1.434 +#else 1.435 + static const js::gc::AllocKind FinalizeKind = js::gc::FINALIZE_OBJECT4_BACKGROUND; 1.436 + static const js::gc::AllocKind ExtendedFinalizeKind = js::gc::FINALIZE_OBJECT8_BACKGROUND; 1.437 +#endif 1.438 + 1.439 + inline void trace(JSTracer *trc); 1.440 + 1.441 + /* Bound function accessors. */ 1.442 + 1.443 + inline bool initBoundFunction(JSContext *cx, js::HandleValue thisArg, 1.444 + const js::Value *args, unsigned argslen); 1.445 + 1.446 + JSObject *getBoundFunctionTarget() const { 1.447 + JS_ASSERT(isBoundFunction()); 1.448 + 1.449 + /* Bound functions abuse |parent| to store their target function. */ 1.450 + return getParent(); 1.451 + } 1.452 + 1.453 + const js::Value &getBoundFunctionThis() const; 1.454 + const js::Value &getBoundFunctionArgument(unsigned which) const; 1.455 + size_t getBoundFunctionArgumentCount() const; 1.456 + 1.457 + private: 1.458 + inline js::FunctionExtended *toExtended(); 1.459 + inline const js::FunctionExtended *toExtended() const; 1.460 + 1.461 + public: 1.462 + inline bool isExtended() const { 1.463 + JS_STATIC_ASSERT(FinalizeKind != ExtendedFinalizeKind); 1.464 + JS_ASSERT_IF(isTenured(), !!(flags() & EXTENDED) == (tenuredGetAllocKind() == ExtendedFinalizeKind)); 1.465 + return !!(flags() & EXTENDED); 1.466 + } 1.467 + 1.468 + /* 1.469 + * Accessors for data stored in extended functions. Use setExtendedSlot if 1.470 + * the function has already been initialized. Otherwise use 1.471 + * initExtendedSlot. 1.472 + */ 1.473 + inline void initializeExtended(); 1.474 + inline void initExtendedSlot(size_t which, const js::Value &val); 1.475 + inline void setExtendedSlot(size_t which, const js::Value &val); 1.476 + inline const js::Value &getExtendedSlot(size_t which) const; 1.477 + 1.478 + /* Constructs a new type for the function if necessary. */ 1.479 + static bool setTypeForScriptedFunction(js::ExclusiveContext *cx, js::HandleFunction fun, 1.480 + bool singleton = false); 1.481 + 1.482 + /* GC support. */ 1.483 + js::gc::AllocKind getAllocKind() const { 1.484 + js::gc::AllocKind kind = FinalizeKind; 1.485 + if (isExtended()) 1.486 + kind = ExtendedFinalizeKind; 1.487 + JS_ASSERT_IF(isTenured(), kind == tenuredGetAllocKind()); 1.488 + return kind; 1.489 + } 1.490 +}; 1.491 + 1.492 +extern JSString * 1.493 +fun_toStringHelper(JSContext *cx, js::HandleObject obj, unsigned indent); 1.494 + 1.495 +inline JSFunction::Flags 1.496 +JSAPIToJSFunctionFlags(unsigned flags) 1.497 +{ 1.498 + return (flags & JSFUN_CONSTRUCTOR) 1.499 + ? JSFunction::NATIVE_CTOR 1.500 + : JSFunction::NATIVE_FUN; 1.501 +} 1.502 + 1.503 +namespace js { 1.504 + 1.505 +extern bool 1.506 +Function(JSContext *cx, unsigned argc, Value *vp); 1.507 + 1.508 +extern bool 1.509 +Generator(JSContext *cx, unsigned argc, Value *vp); 1.510 + 1.511 +extern JSFunction * 1.512 +NewFunction(ExclusiveContext *cx, HandleObject funobj, JSNative native, unsigned nargs, 1.513 + JSFunction::Flags flags, HandleObject parent, HandleAtom atom, 1.514 + gc::AllocKind allocKind = JSFunction::FinalizeKind, 1.515 + NewObjectKind newKind = GenericObject); 1.516 + 1.517 +// If proto is nullptr, Function.prototype is used instead. 1.518 +extern JSFunction * 1.519 +NewFunctionWithProto(ExclusiveContext *cx, HandleObject funobj, JSNative native, unsigned nargs, 1.520 + JSFunction::Flags flags, HandleObject parent, HandleAtom atom, 1.521 + JSObject *proto, gc::AllocKind allocKind = JSFunction::FinalizeKind, 1.522 + NewObjectKind newKind = GenericObject); 1.523 + 1.524 +extern JSFunction * 1.525 +DefineFunction(JSContext *cx, HandleObject obj, HandleId id, JSNative native, 1.526 + unsigned nargs, unsigned flags, 1.527 + gc::AllocKind allocKind = JSFunction::FinalizeKind, 1.528 + NewObjectKind newKind = GenericObject); 1.529 + 1.530 +bool 1.531 +FunctionHasResolveHook(const JSAtomState &atomState, PropertyName *name); 1.532 + 1.533 +extern bool 1.534 +fun_resolve(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp); 1.535 + 1.536 +// ES6 9.2.5 IsConstructor 1.537 +bool IsConstructor(const Value &v); 1.538 + 1.539 +/* 1.540 + * Function extended with reserved slots for use by various kinds of functions. 1.541 + * Most functions do not have these extensions, but enough do that efficient 1.542 + * storage is required (no malloc'ed reserved slots). 1.543 + */ 1.544 +class FunctionExtended : public JSFunction 1.545 +{ 1.546 + public: 1.547 + static const unsigned NUM_EXTENDED_SLOTS = 2; 1.548 + 1.549 + /* Arrow functions store their lexical |this| in the first extended slot. */ 1.550 + static const unsigned ARROW_THIS_SLOT = 0; 1.551 + 1.552 + static inline size_t offsetOfExtendedSlot(unsigned which) { 1.553 + MOZ_ASSERT(which < NUM_EXTENDED_SLOTS); 1.554 + return offsetof(FunctionExtended, extendedSlots) + which * sizeof(HeapValue); 1.555 + } 1.556 + static inline size_t offsetOfArrowThisSlot() { 1.557 + return offsetOfExtendedSlot(ARROW_THIS_SLOT); 1.558 + } 1.559 + 1.560 + private: 1.561 + friend class JSFunction; 1.562 + 1.563 + /* Reserved slots available for storage by particular native functions. */ 1.564 + HeapValue extendedSlots[NUM_EXTENDED_SLOTS]; 1.565 +}; 1.566 + 1.567 +extern JSFunction * 1.568 +CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent, 1.569 + gc::AllocKind kind = JSFunction::FinalizeKind, 1.570 + NewObjectKind newKindArg = GenericObject); 1.571 + 1.572 + 1.573 +extern bool 1.574 +FindBody(JSContext *cx, HandleFunction fun, ConstTwoByteChars chars, size_t length, 1.575 + size_t *bodyStart, size_t *bodyEnd); 1.576 + 1.577 +} // namespace js 1.578 + 1.579 +inline js::FunctionExtended * 1.580 +JSFunction::toExtended() 1.581 +{ 1.582 + JS_ASSERT(isExtended()); 1.583 + return static_cast<js::FunctionExtended *>(this); 1.584 +} 1.585 + 1.586 +inline const js::FunctionExtended * 1.587 +JSFunction::toExtended() const 1.588 +{ 1.589 + JS_ASSERT(isExtended()); 1.590 + return static_cast<const js::FunctionExtended *>(this); 1.591 +} 1.592 + 1.593 +inline void 1.594 +JSFunction::initializeExtended() 1.595 +{ 1.596 + JS_ASSERT(isExtended()); 1.597 + 1.598 + JS_ASSERT(mozilla::ArrayLength(toExtended()->extendedSlots) == 2); 1.599 + toExtended()->extendedSlots[0].init(js::UndefinedValue()); 1.600 + toExtended()->extendedSlots[1].init(js::UndefinedValue()); 1.601 +} 1.602 + 1.603 +inline void 1.604 +JSFunction::initExtendedSlot(size_t which, const js::Value &val) 1.605 +{ 1.606 + JS_ASSERT(which < mozilla::ArrayLength(toExtended()->extendedSlots)); 1.607 + toExtended()->extendedSlots[which].init(val); 1.608 +} 1.609 + 1.610 +inline void 1.611 +JSFunction::setExtendedSlot(size_t which, const js::Value &val) 1.612 +{ 1.613 + JS_ASSERT(which < mozilla::ArrayLength(toExtended()->extendedSlots)); 1.614 + toExtended()->extendedSlots[which] = val; 1.615 +} 1.616 + 1.617 +inline const js::Value & 1.618 +JSFunction::getExtendedSlot(size_t which) const 1.619 +{ 1.620 + JS_ASSERT(which < mozilla::ArrayLength(toExtended()->extendedSlots)); 1.621 + return toExtended()->extendedSlots[which]; 1.622 +} 1.623 + 1.624 +namespace js { 1.625 + 1.626 +JSString *FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lambdaParen); 1.627 + 1.628 +template<XDRMode mode> 1.629 +bool 1.630 +XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, 1.631 + HandleScript enclosingScript, MutableHandleObject objp); 1.632 + 1.633 +extern JSObject * 1.634 +CloneFunctionAndScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun); 1.635 + 1.636 +/* 1.637 + * Report an error that call.thisv is not compatible with the specified class, 1.638 + * assuming that the method (clasp->name).prototype.<name of callee function> 1.639 + * is what was called. 1.640 + */ 1.641 +extern void 1.642 +ReportIncompatibleMethod(JSContext *cx, CallReceiver call, const Class *clasp); 1.643 + 1.644 +/* 1.645 + * Report an error that call.thisv is not an acceptable this for the callee 1.646 + * function. 1.647 + */ 1.648 +extern void 1.649 +ReportIncompatible(JSContext *cx, CallReceiver call); 1.650 + 1.651 +bool 1.652 +CallOrConstructBoundFunction(JSContext *, unsigned, js::Value *); 1.653 + 1.654 +extern const JSFunctionSpec function_methods[]; 1.655 + 1.656 +} /* namespace js */ 1.657 + 1.658 +extern bool 1.659 +js_fun_apply(JSContext *cx, unsigned argc, js::Value *vp); 1.660 + 1.661 +extern bool 1.662 +js_fun_call(JSContext *cx, unsigned argc, js::Value *vp); 1.663 + 1.664 +extern JSObject* 1.665 +js_fun_bind(JSContext *cx, js::HandleObject target, js::HandleValue thisArg, 1.666 + js::Value *boundArgs, unsigned argslen); 1.667 + 1.668 +#ifdef DEBUG 1.669 +namespace JS { 1.670 +namespace detail { 1.671 + 1.672 +JS_PUBLIC_API(void) 1.673 +CheckIsValidConstructible(Value calleev); 1.674 + 1.675 +} // namespace detail 1.676 +} // namespace JS 1.677 +#endif 1.678 + 1.679 +#endif /* jsfun_h */