1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11 #include "jsfuninlines.h"
13 #include "mozilla/ArrayUtils.h"
14 #include "mozilla/PodOperations.h"
15 #include "mozilla/Range.h"
28 #include "jswrapper.h"
30 #include "builtin/Eval.h"
31 #include "builtin/Object.h"
32 #include "frontend/BytecodeCompiler.h"
33 #include "frontend/TokenStream.h"
34 #include "gc/Marking.h"
36 #include "jit/JitFrameIterator.h"
37 #include "js/CallNonGenericMethod.h"
38 #include "vm/GlobalObject.h"
39 #include "vm/Interpreter.h"
41 #include "vm/StringBuffer.h"
42 #include "vm/WrapperObject.h"
45 #include "jsscriptinlines.h"
47 #include "vm/Interpreter-inl.h"
48 #include "vm/Stack-inl.h"
51 using namespace js::gc
;
52 using namespace js::types
;
53 using namespace js::frontend
;
55 using mozilla::ArrayLength
;
56 using mozilla::PodCopy
;
57 using mozilla::RangedPtr
;
60 fun_enumerate(JSContext
* cx
, HandleObject obj
)
62 MOZ_ASSERT(obj
->is
<JSFunction
>());
67 if (!obj
->isBoundFunction() && !obj
->as
<JSFunction
>().isArrow()) {
68 id
= NameToId(cx
->names().prototype
);
69 if (!JSObject::hasProperty(cx
, obj
, id
, &found
))
73 id
= NameToId(cx
->names().length
);
74 if (!JSObject::hasProperty(cx
, obj
, id
, &found
))
77 id
= NameToId(cx
->names().name
);
78 if (!JSObject::hasProperty(cx
, obj
, id
, &found
))
85 IsFunction(HandleValue v
)
87 return v
.isObject() && v
.toObject().is
<JSFunction
>();
91 AdvanceToActiveCallLinear(NonBuiltinScriptFrameIter
& iter
, HandleFunction fun
)
93 MOZ_ASSERT(!fun
->isBuiltin());
94 MOZ_ASSERT(!fun
->isBoundFunction(), "all bound functions are currently native (ergo builtin)");
96 for (; !iter
.done(); ++iter
) {
97 if (!iter
.isFunctionFrame() || iter
.isEvalFrame())
99 if (iter
.callee() == fun
)
106 ThrowTypeErrorBehavior(JSContext
* cx
)
108 JS_ReportErrorFlagsAndNumber(cx
, JSREPORT_ERROR
, js_GetErrorMessage
, nullptr,
109 JSMSG_THROW_TYPE_ERROR
);
112 // Beware: this function can be invoked on *any* function! That includes
113 // natives, strict mode functions, bound functions, arrow functions,
114 // self-hosted functions and constructors, asm.js functions, functions with
115 // destructuring arguments and/or a rest argument, and probably a few more I
116 // forgot. Turn back and save yourself while you still can. It's too late for
119 ArgumentsRestrictions(JSContext
* cx
, HandleFunction fun
)
121 // Throw if the function is a strict mode function or a bound function.
122 if ((!fun
->isBuiltin() && fun
->isInterpreted() && fun
->strict()) ||
123 fun
->isBoundFunction())
125 ThrowTypeErrorBehavior(cx
);
129 // Functions with rest arguments don't include a local |arguments| binding.
130 // Similarly, "arguments" shouldn't work on them.
131 if (fun
->hasRest()) {
132 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, nullptr,
133 JSMSG_FUNCTION_ARGUMENTS_AND_REST
);
137 // Otherwise emit a strict warning about |f.arguments| to discourage use of
138 // this non-standard, performance-harmful feature.
139 if (!JS_ReportErrorFlagsAndNumber(cx
, JSREPORT_WARNING
| JSREPORT_STRICT
, js_GetErrorMessage
,
140 nullptr, JSMSG_DEPRECATED_USAGE
, js_arguments_str
))
149 ArgumentsGetterImpl(JSContext
* cx
, CallArgs args
)
151 MOZ_ASSERT(IsFunction(args
.thisv()));
153 RootedFunction
fun(cx
, &args
.thisv().toObject().as
<JSFunction
>());
154 if (!ArgumentsRestrictions(cx
, fun
))
157 // FIXME: Bug 929642 will break "arguments" and "caller" properties on
158 // builtin functions, at which point this condition should be added
159 // to the early exit at the start of ArgumentsGuts.
160 if (fun
->isBuiltin()) {
161 args
.rval().setNull();
165 // Return null if this function wasn't found on the stack.
166 NonBuiltinScriptFrameIter
iter(cx
);
167 if (!AdvanceToActiveCallLinear(iter
, fun
)) {
168 args
.rval().setNull();
172 Rooted
<ArgumentsObject
*> argsobj(cx
, ArgumentsObject::createUnexpected(cx
, iter
));
176 // Disabling compiling of this script in IonMonkey. IonMonkey doesn't
177 // guarantee |f.arguments| can be fully recovered, so we try to mitigate
178 // observing this behavior by detecting its use early.
179 JSScript
* script
= iter
.script();
180 jit::ForbidCompilation(cx
, script
);
182 args
.rval().setObject(*argsobj
);
187 ArgumentsGetter(JSContext
* cx
, unsigned argc
, Value
* vp
)
189 CallArgs args
= CallArgsFromVp(argc
, vp
);
190 return CallNonGenericMethod
<IsFunction
, ArgumentsGetterImpl
>(cx
, args
);
194 ArgumentsSetterImpl(JSContext
* cx
, CallArgs args
)
196 MOZ_ASSERT(IsFunction(args
.thisv()));
198 RootedFunction
fun(cx
, &args
.thisv().toObject().as
<JSFunction
>());
199 if (!ArgumentsRestrictions(cx
, fun
))
202 // FIXME: Bug 929642 will break "arguments" and "caller" properties on
203 // builtin functions, at which point this bit should be removed.
204 if (fun
->isBuiltin()) {
205 args
.rval().setUndefined();
209 // If the function passes the gauntlet, return |undefined|.
210 args
.rval().setUndefined();
215 ArgumentsSetter(JSContext
* cx
, unsigned argc
, Value
* vp
)
217 CallArgs args
= CallArgsFromVp(argc
, vp
);
218 return CallNonGenericMethod
<IsFunction
, ArgumentsSetterImpl
>(cx
, args
);
221 // Beware: this function can be invoked on *any* function! That includes
222 // natives, strict mode functions, bound functions, arrow functions,
223 // self-hosted functions and constructors, asm.js functions, functions with
224 // destructuring arguments and/or a rest argument, and probably a few more I
225 // forgot. Turn back and save yourself while you still can. It's too late for
228 CallerRestrictions(JSContext
* cx
, HandleFunction fun
)
230 // Throw if the function is a strict mode function or a bound function.
231 if ((!fun
->isBuiltin() && fun
->isInterpreted() && fun
->strict()) ||
232 fun
->isBoundFunction())
234 ThrowTypeErrorBehavior(cx
);
238 // Otherwise emit a strict warning about |f.caller| to discourage use of
239 // this non-standard, performance-harmful feature.
240 if (!JS_ReportErrorFlagsAndNumber(cx
, JSREPORT_WARNING
| JSREPORT_STRICT
, js_GetErrorMessage
,
241 nullptr, JSMSG_DEPRECATED_USAGE
, js_caller_str
))
250 CallerGetterImpl(JSContext
* cx
, CallArgs args
)
252 MOZ_ASSERT(IsFunction(args
.thisv()));
254 // Beware! This function can be invoked on *any* function! It can't
255 // assume it'll never be invoked on natives, strict mode functions, bound
256 // functions, or anything else that ordinarily has immutable .caller
257 // defined with [[ThrowTypeError]].
258 RootedFunction
fun(cx
, &args
.thisv().toObject().as
<JSFunction
>());
259 if (!CallerRestrictions(cx
, fun
))
262 // FIXME: Bug 929642 will break "arguments" and "caller" properties on
263 // builtin functions, at which point this condition should be added
264 // to the early exit at the start of CallerRestrictions.
265 if (fun
->isBuiltin()) {
266 args
.rval().setNull();
270 // Also return null if this function wasn't found on the stack.
271 NonBuiltinScriptFrameIter
iter(cx
);
272 if (!AdvanceToActiveCallLinear(iter
, fun
)) {
273 args
.rval().setNull();
278 if (iter
.done() || !iter
.isFunctionFrame()) {
279 args
.rval().setNull();
283 // It might seem we need to replace call site clones with the original
284 // functions here. But we're iterating over *non-builtin* frames, and the
285 // only call site-clonable scripts are for builtin, self-hosted functions
286 // (see assertions in js::CloneFunctionAtCallsite). So the callee can't be
287 // a call site clone.
288 JSFunction
* maybeClone
= iter
.callee();
289 MOZ_ASSERT(!maybeClone
->nonLazyScript()->isCallsiteClone(),
290 "non-builtin functions aren't call site-clonable");
292 RootedObject
caller(cx
, maybeClone
);
293 if (!cx
->compartment()->wrap(cx
, &caller
))
296 // Censor the caller if we don't have full access to it. If we do, but the
297 // caller is a function with strict mode code, throw a TypeError per ES5.
298 // If we pass these checks, we can return the computed caller.
300 JSObject
* callerObj
= CheckedUnwrap(caller
);
302 args
.rval().setNull();
306 JSFunction
* callerFun
= &callerObj
->as
<JSFunction
>();
307 MOZ_ASSERT(!callerFun
->isBuiltin(), "non-builtin iterator returned a builtin?");
309 if (callerFun
->strict()) {
310 JS_ReportErrorFlagsAndNumber(cx
, JSREPORT_ERROR
, js_GetErrorMessage
, nullptr,
311 JSMSG_CALLER_IS_STRICT
);
316 args
.rval().setObject(*caller
);
321 CallerGetter(JSContext
* cx
, unsigned argc
, Value
* vp
)
323 CallArgs args
= CallArgsFromVp(argc
, vp
);
324 return CallNonGenericMethod
<IsFunction
, CallerGetterImpl
>(cx
, args
);
328 CallerSetterImpl(JSContext
* cx
, CallArgs args
)
330 MOZ_ASSERT(IsFunction(args
.thisv()));
332 // Beware! This function can be invoked on *any* function! It can't
333 // assume it'll never be invoked on natives, strict mode functions, bound
334 // functions, or anything else that ordinarily has immutable .caller
335 // defined with [[ThrowTypeError]].
336 RootedFunction
fun(cx
, &args
.thisv().toObject().as
<JSFunction
>());
337 if (!CallerRestrictions(cx
, fun
))
340 // Return |undefined| unless an error must be thrown.
341 args
.rval().setUndefined();
343 // FIXME: Bug 929642 will break "arguments" and "caller" properties on
344 // builtin functions, at which point this bit should be removed.
345 if (fun
->isBuiltin())
348 // We can almost just return |undefined| here -- but if the caller function
349 // was strict mode code, we still have to throw a TypeError. This requires
350 // computing the caller, checking that no security boundaries are crossed,
351 // and throwing a TypeError if the resulting caller is strict.
353 NonBuiltinScriptFrameIter
iter(cx
);
354 if (!AdvanceToActiveCallLinear(iter
, fun
))
358 if (iter
.done() || !iter
.isFunctionFrame())
361 // It might seem we need to replace call site clones with the original
362 // functions here. But we're iterating over *non-builtin* frames, and the
363 // only call site-clonable scripts are for builtin, self-hosted functions
364 // (see assertions in js::CloneFunctionAtCallsite). So the callee can't be
365 // a call site clone.
366 JSFunction
* maybeClone
= iter
.callee();
367 MOZ_ASSERT(!maybeClone
->nonLazyScript()->isCallsiteClone(),
368 "non-builtin functions aren't call site-clonable");
370 RootedObject
caller(cx
, maybeClone
);
371 if (!cx
->compartment()->wrap(cx
, &caller
)) {
372 cx
->clearPendingException();
376 // If we don't have full access to the caller, or the caller is not strict,
377 // return undefined. Otherwise throw a TypeError.
378 JSObject
* callerObj
= CheckedUnwrap(caller
);
382 JSFunction
* callerFun
= &callerObj
->as
<JSFunction
>();
383 MOZ_ASSERT(!callerFun
->isBuiltin(), "non-builtin iterator returned a builtin?");
385 if (callerFun
->strict()) {
386 JS_ReportErrorFlagsAndNumber(cx
, JSREPORT_ERROR
, js_GetErrorMessage
, nullptr,
387 JSMSG_CALLER_IS_STRICT
);
395 CallerSetter(JSContext
* cx
, unsigned argc
, Value
* vp
)
397 CallArgs args
= CallArgsFromVp(argc
, vp
);
398 return CallNonGenericMethod
<IsFunction
, CallerSetterImpl
>(cx
, args
);
401 static const JSPropertySpec function_properties
[] = {
402 JS_PSGS("arguments", ArgumentsGetter
, ArgumentsSetter
, 0),
403 JS_PSGS("caller", CallerGetter
, CallerSetter
, 0),
408 ResolveInterpretedFunctionPrototype(JSContext
* cx
, HandleObject obj
)
411 JSFunction
* fun
= &obj
->as
<JSFunction
>();
412 JS_ASSERT(fun
->isInterpreted() || fun
->isAsmJSNative());
413 JS_ASSERT(!fun
->isFunctionPrototype());
416 // Assert that fun is not a compiler-created function object, which
417 // must never leak to script or embedding code and then be mutated.
418 // Also assert that obj is not bound, per the ES5 15.3.4.5 ref above.
419 JS_ASSERT(!IsInternalFunctionObject(obj
));
420 JS_ASSERT(!obj
->isBoundFunction());
422 // Make the prototype object an instance of Object with the same parent as
423 // the function object itself, unless the function is an ES6 generator. In
424 // that case, per the 15 July 2013 ES6 draft, section 15.19.3, its parent is
425 // the GeneratorObjectPrototype singleton.
426 bool isStarGenerator
= obj
->as
<JSFunction
>().isStarGenerator();
427 Rooted
<GlobalObject
*> global(cx
, &obj
->global());
430 objProto
= GlobalObject::getOrCreateStarGeneratorObjectPrototype(cx
, global
);
432 objProto
= obj
->global().getOrCreateObjectPrototype(cx
);
435 const Class
* clasp
= &JSObject::class_
;
437 RootedObject
proto(cx
, NewObjectWithGivenProto(cx
, clasp
, objProto
, nullptr, SingletonObject
));
441 // Per ES5 15.3.5.2 a user-defined function's .prototype property is
442 // initially non-configurable, non-enumerable, and writable.
443 RootedValue
protoVal(cx
, ObjectValue(*proto
));
444 if (!JSObject::defineProperty(cx
, obj
, cx
->names().prototype
,
445 protoVal
, JS_PropertyStub
, JS_StrictPropertyStub
,
451 // Per ES5 13.2 the prototype's .constructor property is configurable,
452 // non-enumerable, and writable. However, per the 15 July 2013 ES6 draft,
453 // section 15.19.3, the .prototype of a generator function does not link
454 // back with a .constructor.
455 if (!isStarGenerator
) {
456 RootedValue
objVal(cx
, ObjectValue(*obj
));
457 if (!JSObject::defineProperty(cx
, proto
, cx
->names().constructor
,
458 objVal
, JS_PropertyStub
, JS_StrictPropertyStub
, 0))
468 js::FunctionHasResolveHook(const JSAtomState
& atomState
, PropertyName
* name
)
470 return name
== atomState
.prototype
|| name
== atomState
.length
|| name
== atomState
.name
;
474 js::fun_resolve(JSContext
* cx
, HandleObject obj
, HandleId id
, MutableHandleObject objp
)
476 if (!JSID_IS_ATOM(id
))
479 RootedFunction
fun(cx
, &obj
->as
<JSFunction
>());
481 if (JSID_IS_ATOM(id
, cx
->names().prototype
)) {
483 * Built-in functions do not have a .prototype property per ECMA-262,
484 * or (Object.prototype, Function.prototype, etc.) have that property
487 * ES5 15.3.4: the non-native function object named Function.prototype
488 * does not have a .prototype property.
490 * ES5 15.3.4.5: bound functions don't have a prototype property. The
491 * isBuiltin() test covers this case because bound functions are native
492 * (and thus built-in) functions by definition/construction.
494 * ES6 19.2.4.3: arrow functions also don't have a prototype property.
496 if (fun
->isBuiltin() || fun
->isArrow() || fun
->isFunctionPrototype())
499 if (!ResolveInterpretedFunctionPrototype(cx
, fun
))
505 if (JSID_IS_ATOM(id
, cx
->names().length
) || JSID_IS_ATOM(id
, cx
->names().name
)) {
506 JS_ASSERT(!IsInternalFunctionObject(obj
));
509 if (JSID_IS_ATOM(id
, cx
->names().length
)) {
510 if (fun
->isInterpretedLazy() && !fun
->getOrCreateScript(cx
))
512 uint16_t length
= fun
->hasScript() ? fun
->nonLazyScript()->funLength() :
513 fun
->nargs() - fun
->hasRest();
516 v
.setString(fun
->atom() == nullptr ? cx
->runtime()->emptyString
: fun
->atom());
519 if (!DefineNativeProperty(cx
, fun
, id
, v
, JS_PropertyStub
, JS_StrictPropertyStub
,
520 JSPROP_PERMANENT
| JSPROP_READONLY
)) {
530 template<XDRMode mode
>
532 js::XDRInterpretedFunction(XDRState
<mode
>* xdr
, HandleObject enclosingScope
, HandleScript enclosingScript
,
533 MutableHandleObject objp
)
537 IsStarGenerator
= 0x2,
539 HasSingletonType
= 0x8
542 /* NB: Keep this in sync with CloneFunctionAndScript. */
543 RootedAtom
atom(xdr
->cx());
544 uint32_t firstword
= 0; /* bitmask of FirstWordFlag */
545 uint32_t flagsword
= 0; /* word for argument count and fun->flags */
547 JSContext
* cx
= xdr
->cx();
548 RootedFunction
fun(cx
);
549 RootedScript
script(cx
);
550 Rooted
<LazyScript
*> lazy(cx
);
552 if (mode
== XDR_ENCODE
) {
553 fun
= &objp
->as
<JSFunction
>();
554 if (!fun
->isInterpreted()) {
555 JSAutoByteString funNameBytes
;
556 if (const char* name
= GetFunctionNameBytes(cx
, fun
, &funNameBytes
)) {
557 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, nullptr,
558 JSMSG_NOT_SCRIPTED_FUNCTION
, name
);
563 if (fun
->atom() || fun
->hasGuessedAtom())
564 firstword
|= HasAtom
;
566 if (fun
->isStarGenerator())
567 firstword
|= IsStarGenerator
;
569 if (fun
->isInterpretedLazy()) {
570 // This can only happen for re-lazified cloned functions, so this
571 // does not apply to any JSFunction produced by the parser, only to
572 // JSFunction created by the runtime.
573 JS_ASSERT(!fun
->lazyScript()->maybeScript());
575 // Encode a lazy script.
577 lazy
= fun
->lazyScript();
579 // Encode the script.
580 script
= fun
->nonLazyScript();
583 if (fun
->hasSingletonType())
584 firstword
|= HasSingletonType
;
586 atom
= fun
->displayAtom();
587 flagsword
= (fun
->nargs() << 16) | fun
->flags();
589 // The environment of any function which is not reused will always be
590 // null, it is later defined when a function is cloned or reused to
591 // mirror the scope chain.
592 JS_ASSERT_IF(fun
->hasSingletonType() &&
593 !((lazy
&& lazy
->hasBeenCloned()) || (script
&& script
->hasBeenCloned())),
594 fun
->environment() == nullptr);
597 if (!xdr
->codeUint32(&firstword
))
600 if ((firstword
& HasAtom
) && !XDRAtom(xdr
, &atom
))
602 if (!xdr
->codeUint32(&flagsword
))
605 if (mode
== XDR_DECODE
) {
606 JSObject
* proto
= nullptr;
607 if (firstword
& IsStarGenerator
) {
608 proto
= GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx
, cx
->global());
613 gc::AllocKind allocKind
= JSFunction::FinalizeKind
;
614 if (uint16_t(flagsword
) & JSFunction::EXTENDED
)
615 allocKind
= JSFunction::ExtendedFinalizeKind
;
616 fun
= NewFunctionWithProto(cx
, NullPtr(), nullptr, 0, JSFunction::INTERPRETED
,
617 /* parent = */ NullPtr(), NullPtr(), proto
,
618 allocKind
, TenuredObject
);
624 if (firstword
& IsLazy
) {
625 if (!XDRLazyScript(xdr
, enclosingScope
, enclosingScript
, fun
, &lazy
))
628 if (!XDRScript(xdr
, enclosingScope
, enclosingScript
, fun
, &script
))
632 if (mode
== XDR_DECODE
) {
633 fun
->setArgCount(flagsword
>> 16);
634 fun
->setFlags(uint16_t(flagsword
));
636 if (firstword
& IsLazy
) {
637 fun
->initLazyScript(lazy
);
639 fun
->initScript(script
);
640 script
->setFunction(fun
);
641 JS_ASSERT(fun
->nargs() == script
->bindings
.numArgs());
644 bool singleton
= firstword
& HasSingletonType
;
645 if (!JSFunction::setTypeForScriptedFunction(cx
, fun
, singleton
))
654 js::XDRInterpretedFunction(XDRState
<XDR_ENCODE
>*, HandleObject
, HandleScript
, MutableHandleObject
);
657 js::XDRInterpretedFunction(XDRState
<XDR_DECODE
>*, HandleObject
, HandleScript
, MutableHandleObject
);
660 js::CloneFunctionAndScript(JSContext
* cx
, HandleObject enclosingScope
, HandleFunction srcFun
)
662 /* NB: Keep this in sync with XDRInterpretedFunction. */
663 JSObject
* cloneProto
= nullptr;
664 if (srcFun
->isStarGenerator()) {
665 cloneProto
= GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx
, cx
->global());
670 gc::AllocKind allocKind
= JSFunction::FinalizeKind
;
671 if (srcFun
->isExtended())
672 allocKind
= JSFunction::ExtendedFinalizeKind
;
673 RootedFunction
clone(cx
, NewFunctionWithProto(cx
, NullPtr(), nullptr, 0,
674 JSFunction::INTERPRETED
, NullPtr(), NullPtr(),
675 cloneProto
, allocKind
, TenuredObject
));
679 RootedScript
srcScript(cx
, srcFun
->getOrCreateScript(cx
));
682 RootedScript
clonedScript(cx
, CloneScript(cx
, enclosingScope
, clone
, srcScript
));
686 clone
->setArgCount(srcFun
->nargs());
687 clone
->setFlags(srcFun
->flags());
688 clone
->initAtom(srcFun
->displayAtom());
689 clone
->initScript(clonedScript
);
690 clonedScript
->setFunction(clone
);
691 if (!JSFunction::setTypeForScriptedFunction(cx
, clone
))
694 RootedScript
cloneScript(cx
, clone
->nonLazyScript());
699 * [[HasInstance]] internal method for Function objects: fetch the .prototype
700 * property of its 'this' parameter, and walks the prototype chain of v (only
701 * if v is an object) returning true if .prototype is found.
704 fun_hasInstance(JSContext
* cx
, HandleObject objArg
, MutableHandleValue v
, bool* bp
)
706 RootedObject
obj(cx
, objArg
);
708 while (obj
->is
<JSFunction
>() && obj
->isBoundFunction())
709 obj
= obj
->as
<JSFunction
>().getBoundFunctionTarget();
711 RootedValue
pval(cx
);
712 if (!JSObject::getProperty(cx
, obj
, obj
, cx
->names().prototype
, &pval
))
715 if (pval
.isPrimitive()) {
717 * Throw a runtime error if instanceof is called on a function that
718 * has a non-object as its .prototype value.
720 RootedValue
val(cx
, ObjectValue(*obj
));
721 js_ReportValueError(cx
, JSMSG_BAD_PROTOTYPE
, -1, val
, js::NullPtr());
725 RootedObject
pobj(cx
, &pval
.toObject());
727 if (!IsDelegate(cx
, pobj
, v
, &isDelegate
))
734 JSFunction::trace(JSTracer
* trc
)
737 MarkValueRange(trc
, ArrayLength(toExtended()->extendedSlots
),
738 toExtended()->extendedSlots
, "nativeReserved");
742 MarkString(trc
, &atom_
, "atom");
744 if (isInterpreted()) {
745 // Functions can be be marked as interpreted despite having no script
746 // yet at some points when parsing, and can be lazy with no lazy script
747 // for self-hosted code.
748 if (hasScript() && u
.i
.s
.script_
) {
749 // Functions can be relazified under the following conditions:
750 // - their compartment isn't currently executing scripts or being
752 // - they are not in the self-hosting compartment
753 // - they aren't generators
754 // - they don't have JIT code attached
755 // - they don't have child functions
756 // - they have information for un-lazifying them again later
757 // This information can either be a LazyScript, or the name of a
758 // self-hosted function which can be cloned over again. The latter
759 // is stored in the first extended slot.
760 if (IS_GC_MARKING_TRACER(trc
) && !compartment()->hasBeenEntered() &&
761 !compartment()->debugMode() && !compartment()->isSelfHosting
&&
762 u
.i
.s
.script_
->isRelazifiable() && (!isSelfHostedBuiltin() || isExtended()))
766 MarkScriptUnbarriered(trc
, &u
.i
.s
.script_
, "script");
768 } else if (isInterpretedLazy() && u
.i
.s
.lazy_
) {
769 MarkLazyScriptUnbarriered(trc
, &u
.i
.s
.lazy_
, "lazyScript");
772 MarkObjectUnbarriered(trc
, &u
.i
.env_
, "fun_environment");
777 fun_trace(JSTracer
* trc
, JSObject
* obj
)
779 obj
->as
<JSFunction
>().trace(trc
);
783 ThrowTypeError(JSContext
* cx
, unsigned argc
, Value
* vp
)
785 ThrowTypeErrorBehavior(cx
);
790 CreateFunctionConstructor(JSContext
* cx
, JSProtoKey key
)
792 Rooted
<GlobalObject
*> self(cx
, cx
->global());
793 RootedObject
functionProto(cx
, &self
->getPrototype(JSProto_Function
).toObject());
795 RootedObject
ctor(cx
, NewObjectWithGivenProto(cx
, &JSFunction::class_
, functionProto
,
796 self
, SingletonObject
));
799 RootedObject
functionCtor(cx
, NewFunction(cx
, ctor
, Function
, 1, JSFunction::NATIVE_CTOR
, self
,
800 HandlePropertyName(cx
->names().Function
)));
804 JS_ASSERT(ctor
== functionCtor
);
810 CreateFunctionPrototype(JSContext
* cx
, JSProtoKey key
)
812 Rooted
<GlobalObject
*> self(cx
, cx
->global());
814 RootedObject
objectProto(cx
, &self
->getPrototype(JSProto_Object
).toObject());
815 JSObject
* functionProto_
= NewObjectWithGivenProto(cx
, &JSFunction::class_
,
816 objectProto
, self
, SingletonObject
);
820 RootedFunction
functionProto(cx
, &functionProto_
->as
<JSFunction
>());
823 * Bizarrely, |Function.prototype| must be an interpreted function, so
824 * give it the guts to be one.
827 JSObject
* proto
= NewFunction(cx
, functionProto
, nullptr, 0, JSFunction::INTERPRETED
,
828 self
, js::NullPtr());
832 JS_ASSERT(proto
== functionProto
);
833 functionProto
->setIsFunctionPrototype();
836 const char* rawSource
= "() {\n}";
837 size_t sourceLen
= strlen(rawSource
);
838 jschar
* source
= InflateString(cx
, rawSource
, &sourceLen
);
843 cx
->new_
<ScriptSource
>();
848 ScriptSourceHolder
ssHolder(ss
);
849 ss
->setSource(source
, sourceLen
);
850 CompileOptions
options(cx
);
851 options
.setNoScriptRval(true)
852 .setVersion(JSVERSION_DEFAULT
);
853 RootedScriptSource
sourceObject(cx
, ScriptSourceObject::create(cx
, ss
));
857 RootedScript
script(cx
, JSScript::Create(cx
,
858 /* enclosingScope = */ js::NullPtr(),
859 /* savedCallerFun = */ false,
861 /* staticLevel = */ 0,
865 if (!script
|| !JSScript::fullyInitTrivial(cx
, script
))
868 functionProto
->initScript(script
);
869 types::TypeObject
* protoType
= functionProto
->getType(cx
);
873 protoType
->interpretedFunction
= functionProto
;
874 script
->setFunction(functionProto
);
877 * The default 'new' type of Function.prototype is required by type
878 * inference to have unknown properties, to simplify handling of e.g.
879 * CloneFunctionObject.
881 if (!JSObject::setNewTypeUnknown(cx
, &JSFunction::class_
, functionProto
))
884 // Construct the unique [[%ThrowTypeError%]] function object, used only for
885 // "callee" and "caller" accessors on strict mode arguments objects. (The
886 // spec also uses this for "arguments" and "caller" on various functions,
887 // but we're experimenting with implementing them using accessors on
888 // |Function.prototype| right now.)
889 RootedObject
tte(cx
, NewObjectWithGivenProto(cx
, &JSFunction::class_
, functionProto
, self
,
893 RootedFunction
throwTypeError(cx
, NewFunction(cx
, tte
, ThrowTypeError
, 0,
894 JSFunction::NATIVE_FUN
, self
, js::NullPtr()));
895 if (!throwTypeError
|| !JSObject::preventExtensions(cx
, throwTypeError
))
897 self
->setThrowTypeError(throwTypeError
);
899 return functionProto
;
902 const Class
JSFunction::class_
= {
904 JSCLASS_NEW_RESOLVE
| JSCLASS_IMPLEMENTS_BARRIERS
|
905 JSCLASS_HAS_CACHED_PROTO(JSProto_Function
),
906 JS_PropertyStub
, /* addProperty */
907 JS_DeletePropertyStub
, /* delProperty */
908 JS_PropertyStub
, /* getProperty */
909 JS_StrictPropertyStub
, /* setProperty */
911 (JSResolveOp
)js::fun_resolve
,
913 nullptr, /* finalize */
916 nullptr, /* construct */
919 CreateFunctionConstructor
,
920 CreateFunctionPrototype
,
927 const Class
* const js::FunctionClassPtr
= &JSFunction::class_
;
929 /* Find the body of a function (not including braces). */
931 js::FindBody(JSContext
* cx
, HandleFunction fun
, HandleLinearString src
, size_t* bodyStart
,
934 // We don't need principals, since those are only used for error reporting.
935 CompileOptions
options(cx
);
936 options
.setFileAndLine("internal-findBody", 0);
938 // For asm.js modules, there's no script.
939 if (fun
->hasScript())
940 options
.setVersion(fun
->nonLazyScript()->getVersion());
942 AutoKeepAtoms
keepAtoms(cx
->perThreadData
);
944 AutoStableStringChars
stableChars(cx
);
945 if (!stableChars
.initTwoByte(cx
, src
))
948 const mozilla::Range
<const jschar
> srcChars
= stableChars
.twoByteRange();
949 TokenStream
ts(cx
, options
, srcChars
.start().get(), srcChars
.length(), nullptr);
952 // Skip arguments list.
954 switch (ts
.getToken()) {
974 TokenKind tt
= ts
.getToken();
979 bool braced
= tt
== TOK_LC
;
980 JS_ASSERT_IF(fun
->isExprClosure(), !braced
);
981 *bodyStart
= ts
.currentToken().pos
.begin
;
984 mozilla::RangedPtr
<const jschar
> end
= srcChars
.end();
985 if (end
[-1] == '}') {
989 for (; unicode::IsSpaceOrBOM2(end
[-1]); end
--)
992 *bodyEnd
= end
- srcChars
.start();
993 JS_ASSERT(*bodyStart
<= *bodyEnd
);
998 js::FunctionToString(JSContext
* cx
, HandleFunction fun
, bool bodyOnly
, bool lambdaParen
)
1000 if (fun
->isInterpretedLazy() && !fun
->getOrCreateScript(cx
))
1003 if (IsAsmJSModule(fun
))
1004 return AsmJSModuleToString(cx
, fun
, !lambdaParen
);
1005 if (IsAsmJSFunction(fun
))
1006 return AsmJSFunctionToString(cx
, fun
);
1008 StringBuffer
out(cx
);
1009 RootedScript
script(cx
);
1011 if (fun
->hasScript()) {
1012 script
= fun
->nonLazyScript();
1013 if (script
->isGeneratorExp()) {
1014 if ((!bodyOnly
&& !out
.append("function genexp() {")) ||
1015 !out
.append("\n [generator expression]\n") ||
1016 (!bodyOnly
&& !out
.append("}")))
1020 return out
.finishString();
1024 // If we're not in pretty mode, put parentheses around lambda functions.
1025 if (fun
->isInterpreted() && !lambdaParen
&& fun
->isLambda() && !fun
->isArrow()) {
1026 if (!out
.append("("))
1029 if (!fun
->isArrow()) {
1030 if (!(fun
->isStarGenerator() ? out
.append("function* ") : out
.append("function ")))
1034 if (!out
.append(fun
->atom()))
1038 bool haveSource
= fun
->isInterpreted() && !fun
->isSelfHostedBuiltin();
1039 if (haveSource
&& !script
->scriptSource()->hasSourceData() &&
1040 !JSScript::loadSource(cx
, script
->scriptSource(), &haveSource
))
1045 Rooted
<JSFlatString
*> src(cx
, script
->sourceData(cx
));
1049 bool exprBody
= fun
->isExprClosure();
1051 // The source data for functions created by calling the Function
1052 // constructor is only the function's body. This depends on the fact,
1053 // asserted below, that in Function("function f() {}"), the inner
1054 // function's sourceStart points to the '(', not the 'f'.
1055 bool funCon
= !fun
->isArrow() &&
1056 script
->sourceStart() == 0 &&
1057 script
->sourceEnd() == script
->scriptSource()->length() &&
1058 script
->scriptSource()->argumentsNotIncluded();
1060 // Functions created with the constructor can't be arrow functions or
1061 // expression closures.
1062 JS_ASSERT_IF(funCon
, !fun
->isArrow());
1063 JS_ASSERT_IF(funCon
, !exprBody
);
1064 JS_ASSERT_IF(!funCon
&& !fun
->isArrow(),
1065 src
->length() > 0 && src
->latin1OrTwoByteChar(0) == '(');
1067 // If a function inherits strict mode by having scopes above it that
1068 // have "use strict", we insert "use strict" into the body of the
1069 // function. This ensures that if the result of toString is evaled, the
1070 // resulting function will have the same semantics.
1071 bool addUseStrict
= script
->strict() && !script
->explicitUseStrict() && !fun
->isArrow();
1073 bool buildBody
= funCon
&& !bodyOnly
;
1075 // This function was created with the Function constructor. We don't
1076 // have source for the arguments, so we have to generate that. Part
1077 // of bug 755821 should be cobbling the arguments passed into the
1078 // Function constructor into the source string.
1079 if (!out
.append("("))
1082 // Fish out the argument names.
1083 BindingVector
* localNames
= cx
->new_
<BindingVector
>(cx
);
1084 ScopedJSDeletePtr
<BindingVector
> freeNames(localNames
);
1085 if (!FillBindingVector(script
, localNames
))
1087 for (unsigned i
= 0; i
< fun
->nargs(); i
++) {
1088 if ((i
&& !out
.append(", ")) ||
1089 (i
== unsigned(fun
->nargs() - 1) && fun
->hasRest() && !out
.append("...")) ||
1090 !out
.append((*localNames
)[i
].name())) {
1094 if (!out
.append(") {\n"))
1097 if ((bodyOnly
&& !funCon
) || addUseStrict
) {
1098 // We need to get at the body either because we're only supposed to
1099 // return the body or we need to insert "use strict" into the body.
1100 size_t bodyStart
= 0, bodyEnd
;
1102 // If the function is defined in the Function constructor, we
1103 // already have a body.
1105 JS_ASSERT(!buildBody
);
1106 if (!FindBody(cx
, fun
, src
, &bodyStart
, &bodyEnd
))
1109 bodyEnd
= src
->length();
1113 // Output source up to beginning of body.
1114 if (!out
.appendSubstring(src
, 0, bodyStart
))
1117 // We can't insert a statement into a function with an
1118 // expression body. Do what the decompiler did, and insert a
1120 if (!out
.append("/* use strict */ "))
1123 if (!out
.append("\n\"use strict\";\n"))
1128 // Output just the body (for bodyOnly) or the body and possibly
1129 // closing braces (for addUseStrict).
1130 size_t dependentEnd
= bodyOnly
? bodyEnd
: src
->length();
1131 if (!out
.appendSubstring(src
, bodyStart
, dependentEnd
- bodyStart
))
1134 if (!out
.append(src
))
1138 if (!out
.append("\n}"))
1142 // Slap a semicolon on the end of functions with an expression body.
1143 if (exprBody
&& !out
.append(";"))
1145 } else if (!lambdaParen
&& fun
->isLambda() && !fun
->isArrow()) {
1146 if (!out
.append(")"))
1149 } else if (fun
->isInterpreted() && !fun
->isSelfHostedBuiltin()) {
1150 if ((!bodyOnly
&& !out
.append("() {\n ")) ||
1151 !out
.append("[sourceless code]") ||
1152 (!bodyOnly
&& !out
.append("\n}")))
1154 if (!lambdaParen
&& fun
->isLambda() && !fun
->isArrow() && !out
.append(")"))
1157 JS_ASSERT(!fun
->isExprClosure());
1159 if ((!bodyOnly
&& !out
.append("() {\n "))
1160 || !out
.append("[native code]")
1161 || (!bodyOnly
&& !out
.append("\n}")))
1166 return out
.finishString();
1170 fun_toStringHelper(JSContext
* cx
, HandleObject obj
, unsigned indent
)
1172 if (!obj
->is
<JSFunction
>()) {
1173 if (obj
->is
<ProxyObject
>())
1174 return Proxy::fun_toString(cx
, obj
, indent
);
1175 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, nullptr,
1176 JSMSG_INCOMPATIBLE_PROTO
,
1177 js_Function_str
, js_toString_str
,
1182 RootedFunction
fun(cx
, &obj
->as
<JSFunction
>());
1183 return FunctionToString(cx
, fun
, false, indent
!= JS_DONT_PRETTY_PRINT
);
1187 js::fun_toString(JSContext
* cx
, unsigned argc
, Value
* vp
)
1189 CallArgs args
= CallArgsFromVp(argc
, vp
);
1190 JS_ASSERT(IsFunctionObject(args
.calleev()));
1192 uint32_t indent
= 0;
1194 if (args
.length() != 0 && !ToUint32(cx
, args
[0], &indent
))
1197 RootedObject
obj(cx
, ToObject(cx
, args
.thisv()));
1201 RootedString
str(cx
, fun_toStringHelper(cx
, obj
, indent
));
1205 args
.rval().setString(str
);
1211 fun_toSource(JSContext
* cx
, unsigned argc
, Value
* vp
)
1213 CallArgs args
= CallArgsFromVp(argc
, vp
);
1214 JS_ASSERT(IsFunctionObject(args
.calleev()));
1216 RootedObject
obj(cx
, ToObject(cx
, args
.thisv()));
1220 RootedString
str(cx
);
1221 if (obj
->isCallable())
1222 str
= fun_toStringHelper(cx
, obj
, JS_DONT_PRETTY_PRINT
);
1224 str
= ObjectToSource(cx
, obj
);
1228 args
.rval().setString(str
);
1234 js_fun_call(JSContext
* cx
, unsigned argc
, Value
* vp
)
1236 CallArgs args
= CallArgsFromVp(argc
, vp
);
1238 HandleValue fval
= args
.thisv();
1239 if (!IsCallable(fval
)) {
1240 ReportIncompatibleMethod(cx
, args
, &JSFunction::class_
);
1244 args
.setCallee(fval
);
1245 args
.setThis(args
.get(0));
1247 if (args
.length() > 0) {
1248 for (size_t i
= 0; i
< args
.length() - 1; i
++)
1249 args
[i
].set(args
[i
+ 1]);
1250 args
= CallArgsFromVp(args
.length() - 1, vp
);
1253 return Invoke(cx
, args
);
1258 js_fun_apply(JSContext
* cx
, unsigned argc
, Value
* vp
)
1260 CallArgs args
= CallArgsFromVp(argc
, vp
);
1263 HandleValue fval
= args
.thisv();
1264 if (!IsCallable(fval
)) {
1265 ReportIncompatibleMethod(cx
, args
, &JSFunction::class_
);
1270 if (args
.length() < 2 || args
[1].isNullOrUndefined())
1271 return js_fun_call(cx
, (args
.length() > 0) ? 1 : 0, vp
);
1273 InvokeArgs
args2(cx
);
1275 // A JS_OPTIMIZED_ARGUMENTS magic value means that 'arguments' flows into
1276 // this apply call from a scripted caller and, as an optimization, we've
1277 // avoided creating it since apply can simply pull the argument values from
1278 // the calling frame (which we must do now).
1279 if (args
[1].isMagic(JS_OPTIMIZED_ARGUMENTS
)) {
1281 ScriptFrameIter
iter(cx
);
1282 JS_ASSERT(iter
.numActualArgs() <= ARGS_LENGTH_MAX
);
1283 if (!args2
.init(iter
.numActualArgs()))
1286 args2
.setCallee(fval
);
1287 args2
.setThis(args
[0]);
1290 iter
.unaliasedForEachActual(cx
, CopyTo(args2
.array()));
1293 if (!args
[1].isObject()) {
1294 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, nullptr,
1295 JSMSG_BAD_APPLY_ARGS
, js_apply_str
);
1299 // Steps 4-5 (note erratum removing steps originally numbered 5 and 7 in
1300 // original version of ES5).
1301 RootedObject
aobj(cx
, &args
[1].toObject());
1303 if (!GetLengthProperty(cx
, aobj
, &length
))
1307 if (length
> ARGS_LENGTH_MAX
) {
1308 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, nullptr, JSMSG_TOO_MANY_FUN_APPLY_ARGS
);
1312 if (!args2
.init(length
))
1315 // Push fval, obj, and aobj's elements as args.
1316 args2
.setCallee(fval
);
1317 args2
.setThis(args
[0]);
1320 if (!GetElements(cx
, aobj
, length
, args2
.array()))
1325 if (!Invoke(cx
, args2
))
1328 args
.rval().set(args2
.rval());
1332 static const uint32_t JSSLOT_BOUND_FUNCTION_THIS
= 0;
1333 static const uint32_t JSSLOT_BOUND_FUNCTION_ARGS_COUNT
= 1;
1335 static const uint32_t BOUND_FUNCTION_RESERVED_SLOTS
= 2;
1338 JSFunction::initBoundFunction(JSContext
* cx
, HandleValue thisArg
,
1339 const Value
* args
, unsigned argslen
)
1341 RootedFunction
self(cx
, this);
1344 * Convert to a dictionary to set the BOUND_FUNCTION flag and increase
1345 * the slot span to cover the arguments and additional slots for the 'this'
1346 * value and arguments count.
1348 if (!self
->toDictionaryMode(cx
))
1351 if (!self
->setFlag(cx
, BaseShape::BOUND_FUNCTION
))
1354 if (!JSObject::setSlotSpan(cx
, self
, BOUND_FUNCTION_RESERVED_SLOTS
+ argslen
))
1357 self
->setSlot(JSSLOT_BOUND_FUNCTION_THIS
, thisArg
);
1358 self
->setSlot(JSSLOT_BOUND_FUNCTION_ARGS_COUNT
, PrivateUint32Value(argslen
));
1360 self
->initSlotRange(BOUND_FUNCTION_RESERVED_SLOTS
, args
, argslen
);
1366 JSFunction::getBoundFunctionThis() const
1368 JS_ASSERT(isBoundFunction());
1370 return getSlot(JSSLOT_BOUND_FUNCTION_THIS
);
1374 JSFunction::getBoundFunctionArgument(unsigned which
) const
1376 JS_ASSERT(isBoundFunction());
1377 JS_ASSERT(which
< getBoundFunctionArgumentCount());
1379 return getSlot(BOUND_FUNCTION_RESERVED_SLOTS
+ which
);
1383 JSFunction::getBoundFunctionArgumentCount() const
1385 JS_ASSERT(isBoundFunction());
1387 return getSlot(JSSLOT_BOUND_FUNCTION_ARGS_COUNT
).toPrivateUint32();
1391 JSFunction::createScriptForLazilyInterpretedFunction(JSContext
* cx
, HandleFunction fun
)
1393 JS_ASSERT(fun
->isInterpretedLazy());
1395 Rooted
<LazyScript
*> lazy(cx
, fun
->lazyScriptOrNull());
1397 // Trigger a pre barrier on the lazy script being overwritten.
1398 if (cx
->zone()->needsIncrementalBarrier())
1399 LazyScript::writeBarrierPre(lazy
);
1401 // Suppress GC for now although we should be able to remove this by
1402 // making 'lazy' a Rooted<LazyScript*> (which requires adding a
1403 // THING_ROOT_LAZY_SCRIPT).
1404 AutoSuppressGC
suppressGC(cx
);
1406 RootedScript
script(cx
, lazy
->maybeScript());
1409 fun
->setUnlazifiedScript(script
);
1410 // Remember the lazy script on the compiled script, so it can be
1411 // stored on the function again in case of re-lazification.
1412 // Only functions without inner functions are re-lazified.
1413 if (!lazy
->numInnerFunctions())
1414 script
->setLazyScript(lazy
);
1418 if (fun
!= lazy
->functionNonDelazifying()) {
1419 if (!lazy
->functionDelazifying(cx
))
1421 script
= lazy
->functionNonDelazifying()->nonLazyScript();
1425 fun
->setUnlazifiedScript(script
);
1429 // Lazy script caching is only supported for leaf functions. If a
1430 // script with inner functions was returned by the cache, those inner
1431 // functions would be delazified when deep cloning the script, even if
1432 // they have never executed.
1434 // Additionally, the lazy script cache is not used during incremental
1435 // GCs, to avoid resurrecting dead scripts after incremental sweeping
1437 if (!lazy
->numInnerFunctions() && !JS::IsIncrementalGCInProgress(cx
->runtime())) {
1438 LazyScriptCache::Lookup
lookup(cx
, lazy
);
1439 cx
->runtime()->lazyScriptCache
.lookup(lookup
, script
.address());
1443 RootedObject
enclosingScope(cx
, lazy
->enclosingScope());
1444 RootedScript
clonedScript(cx
, CloneScript(cx
, enclosingScope
, fun
, script
));
1448 clonedScript
->setSourceObject(lazy
->sourceObject());
1450 fun
->initAtom(script
->functionNonDelazifying()->displayAtom());
1451 clonedScript
->setFunction(fun
);
1453 fun
->setUnlazifiedScript(clonedScript
);
1455 if (!lazy
->maybeScript())
1456 lazy
->initScript(clonedScript
);
1460 JS_ASSERT(lazy
->source()->hasSourceData());
1462 // Parse and compile the script from source.
1463 UncompressedSourceCache::AutoHoldEntry holder
;
1464 const jschar
* chars
= lazy
->source()->chars(cx
, holder
);
1468 const jschar
* lazyStart
= chars
+ lazy
->begin();
1469 size_t lazyLength
= lazy
->end() - lazy
->begin();
1471 if (!frontend::CompileLazyFunction(cx
, lazy
, lazyStart
, lazyLength
))
1474 script
= fun
->nonLazyScript();
1476 // Remember the compiled script on the lazy script itself, in case
1477 // there are clones of the function still pointing to the lazy script.
1478 if (!lazy
->maybeScript())
1479 lazy
->initScript(script
);
1481 // Try to insert the newly compiled script into the lazy script cache.
1482 if (!lazy
->numInnerFunctions()) {
1483 // A script's starting column isn't set by the bytecode emitter, so
1484 // specify this from the lazy script so that if an identical lazy
1485 // script is encountered later a match can be determined.
1486 script
->setColumn(lazy
->column());
1488 LazyScriptCache::Lookup
lookup(cx
, lazy
);
1489 cx
->runtime()->lazyScriptCache
.insert(lookup
, script
);
1491 // Remember the lazy script on the compiled script, so it can be
1492 // stored on the function again in case of re-lazification.
1493 // Only functions without inner functions are re-lazified.
1494 script
->setLazyScript(lazy
);
1499 /* Lazily cloned self-hosted script. */
1500 JS_ASSERT(fun
->isSelfHostedBuiltin());
1501 RootedAtom
funAtom(cx
, &fun
->getExtendedSlot(0).toString()->asAtom());
1504 Rooted
<PropertyName
*> funName(cx
, funAtom
->asPropertyName());
1505 return cx
->runtime()->cloneSelfHostedFunctionScript(cx
, funName
, fun
);
1509 JSFunction::relazify(JSTracer
* trc
)
1511 JSScript
* script
= nonLazyScript();
1512 JS_ASSERT(script
->isRelazifiable());
1513 JS_ASSERT(!compartment()->hasBeenEntered());
1514 JS_ASSERT(!compartment()->debugMode());
1516 // If the script's canonical function isn't lazy, we have to mark the
1517 // script. Otherwise, the following scenario would leave it unmarked
1518 // and cause it to be swept while a function is still expecting it to be
1520 // 1. an incremental GC slice causes the canonical function to relazify
1521 // 2. a clone is used and delazifies the canonical function
1522 // 3. another GC slice causes the clone to relazify
1523 // The result is that no function marks the script, but the canonical
1524 // function expects it to be valid.
1525 if (script
->functionNonDelazifying()->hasScript())
1526 MarkScriptUnbarriered(trc
, &u
.i
.s
.script_
, "script");
1528 flags_
&= ~INTERPRETED
;
1529 flags_
|= INTERPRETED_LAZY
;
1530 LazyScript
* lazy
= script
->maybeLazyScript();
1533 JS_ASSERT(!isSelfHostedBuiltin());
1534 // If this is the script stored in the lazy script to be cloned
1535 // for un-lazifying other functions, reset it so the script can
1537 if (lazy
->maybeScript() == script
)
1538 lazy
->resetScript();
1539 MarkLazyScriptUnbarriered(trc
, &u
.i
.s
.lazy_
, "lazyScript");
1541 JS_ASSERT(isSelfHostedBuiltin());
1542 JS_ASSERT(isExtended());
1543 JS_ASSERT(getExtendedSlot(0).toString()->isAtom());
1547 /* ES5 15.3.4.5.1 and 15.3.4.5.2. */
1549 js::CallOrConstructBoundFunction(JSContext
* cx
, unsigned argc
, Value
* vp
)
1551 CallArgs args
= CallArgsFromVp(argc
, vp
);
1552 RootedFunction
fun(cx
, &args
.callee().as
<JSFunction
>());
1553 JS_ASSERT(fun
->isBoundFunction());
1555 /* 15.3.4.5.1 step 1, 15.3.4.5.2 step 3. */
1556 unsigned argslen
= fun
->getBoundFunctionArgumentCount();
1558 if (args
.length() + argslen
> ARGS_LENGTH_MAX
) {
1559 js_ReportAllocationOverflow(cx
);
1563 /* 15.3.4.5.1 step 3, 15.3.4.5.2 step 1. */
1564 RootedObject
target(cx
, fun
->getBoundFunctionTarget());
1566 /* 15.3.4.5.1 step 2. */
1567 const Value
& boundThis
= fun
->getBoundFunctionThis();
1569 InvokeArgs
invokeArgs(cx
);
1570 if (!invokeArgs
.init(args
.length() + argslen
))
1573 /* 15.3.4.5.1, 15.3.4.5.2 step 4. */
1574 for (unsigned i
= 0; i
< argslen
; i
++)
1575 invokeArgs
[i
].set(fun
->getBoundFunctionArgument(i
));
1576 PodCopy(invokeArgs
.array() + argslen
, vp
+ 2, args
.length());
1578 /* 15.3.4.5.1, 15.3.4.5.2 step 5. */
1579 invokeArgs
.setCallee(ObjectValue(*target
));
1581 bool constructing
= args
.isConstructing();
1583 invokeArgs
.setThis(boundThis
);
1585 if (constructing
? !InvokeConstructor(cx
, invokeArgs
) : !Invoke(cx
, invokeArgs
))
1588 args
.rval().set(invokeArgs
.rval());
1593 fun_isGenerator(JSContext
* cx
, unsigned argc
, Value
* vp
)
1595 CallArgs args
= CallArgsFromVp(argc
, vp
);
1597 if (!IsFunctionObject(args
.thisv(), &fun
)) {
1598 args
.rval().setBoolean(false);
1602 args
.rval().setBoolean(fun
->isGenerator());
1608 fun_bind(JSContext
* cx
, unsigned argc
, Value
* vp
)
1610 CallArgs args
= CallArgsFromVp(argc
, vp
);
1613 Value thisv
= args
.thisv();
1616 if (!IsCallable(thisv
)) {
1617 ReportIncompatibleMethod(cx
, args
, &JSFunction::class_
);
1622 Value
* boundArgs
= nullptr;
1623 unsigned argslen
= 0;
1624 if (args
.length() > 1) {
1625 boundArgs
= args
.array() + 1;
1626 argslen
= args
.length() - 1;
1630 RootedValue
thisArg(cx
, args
.length() >= 1 ? args
[0] : UndefinedValue());
1631 RootedObject
target(cx
, &thisv
.toObject());
1632 JSObject
* boundFunction
= js_fun_bind(cx
, target
, thisArg
, boundArgs
, argslen
);
1637 args
.rval().setObject(*boundFunction
);
1642 js_fun_bind(JSContext
* cx
, HandleObject target
, HandleValue thisArg
,
1643 Value
* boundArgs
, unsigned argslen
)
1646 unsigned length
= 0;
1647 if (target
->is
<JSFunction
>()) {
1648 unsigned nargs
= target
->as
<JSFunction
>().nargs();
1649 if (nargs
> argslen
)
1650 length
= nargs
- argslen
;
1653 /* Step 4-6, 10-11. */
1654 RootedAtom
name(cx
, target
->is
<JSFunction
>() ? target
->as
<JSFunction
>().atom() : nullptr);
1656 RootedObject
funobj(cx
, NewFunction(cx
, js::NullPtr(), CallOrConstructBoundFunction
, length
,
1657 JSFunction::NATIVE_CTOR
, target
, name
));
1661 /* NB: Bound functions abuse |parent| to store their target. */
1662 if (!JSObject::setParent(cx
, funobj
, target
))
1665 if (!funobj
->as
<JSFunction
>().initBoundFunction(cx
, thisArg
, boundArgs
, argslen
))
1668 /* Steps 17, 19-21 are handled by fun_resolve. */
1669 /* Step 18 is the default for new functions. */
1674 * Report "malformed formal parameter" iff no illegal char or similar scanner
1675 * error was already reported.
1678 OnBadFormal(JSContext
* cx
, TokenKind tt
)
1680 if (tt
!= TOK_ERROR
)
1681 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, nullptr, JSMSG_BAD_FORMAL
);
1683 JS_ASSERT(cx
->isExceptionPending());
1687 const JSFunctionSpec
js::function_methods
[] = {
1689 JS_FN(js_toSource_str
, fun_toSource
, 0,0),
1691 JS_FN(js_toString_str
, fun_toString
, 0,0),
1692 JS_FN(js_apply_str
, js_fun_apply
, 2,0),
1693 JS_FN(js_call_str
, js_fun_call
, 1,0),
1694 JS_FN("bind", fun_bind
, 1,0),
1695 JS_FN("isGenerator", fun_isGenerator
,0,0),
1700 FunctionConstructor(JSContext
* cx
, unsigned argc
, Value
* vp
, GeneratorKind generatorKind
)
1702 CallArgs args
= CallArgsFromVp(argc
, vp
);
1703 RootedString
arg(cx
); // used multiple times below
1705 /* Block this call if security callbacks forbid it. */
1706 Rooted
<GlobalObject
*> global(cx
, &args
.callee().global());
1707 if (!GlobalObject::isRuntimeCodeGenEnabled(cx
, global
)) {
1708 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, nullptr, JSMSG_CSP_BLOCKED_FUNCTION
);
1712 AutoKeepAtoms
keepAtoms(cx
->perThreadData
);
1713 AutoNameVector
formals(cx
);
1715 bool hasRest
= false;
1717 bool isStarGenerator
= generatorKind
== StarGenerator
;
1718 JS_ASSERT(generatorKind
!= LegacyGenerator
);
1720 RootedScript
maybeScript(cx
);
1721 const char* filename
;
1723 JSPrincipals
* originPrincipals
;
1725 DescribeScriptedCallerForCompilation(cx
, &maybeScript
, &filename
, &lineno
, &pcOffset
,
1728 const char* introductionType
= "Function";
1729 if (generatorKind
!= NotGenerator
)
1730 introductionType
= "GeneratorFunction";
1732 const char* introducerFilename
= filename
;
1733 if (maybeScript
&& maybeScript
->scriptSource()->introducerFilename())
1734 introducerFilename
= maybeScript
->scriptSource()->introducerFilename();
1736 CompileOptions
options(cx
);
1737 options
.setOriginPrincipals(originPrincipals
)
1738 .setFileAndLine(filename
, 1)
1739 .setNoScriptRval(false)
1740 .setCompileAndGo(true)
1741 .setIntroductionInfo(introducerFilename
, introductionType
, lineno
, maybeScript
, pcOffset
);
1743 unsigned n
= args
.length() ? args
.length() - 1 : 0;
1746 * Collect the function-argument arguments into one string, separated
1747 * by commas, then make a tokenstream from that string, and scan it to
1748 * get the arguments. We need to throw the full scanner at the
1749 * problem, because the argument string can legitimately contain
1750 * comments and linefeeds. XXX It might be better to concatenate
1751 * everything up into a function definition and pass it to the
1752 * compiler, but doing it this way is less of a delta from the old
1753 * code. See ECMA 15.3.2.1.
1755 size_t args_length
= 0;
1756 for (unsigned i
= 0; i
< n
; i
++) {
1757 /* Collect the lengths for all the function-argument arguments. */
1758 arg
= ToString
<CanGC
>(cx
, args
[i
]);
1761 args
[i
].setString(arg
);
1764 * Check for overflow. The < test works because the maximum
1765 * JSString length fits in 2 fewer bits than size_t has.
1767 size_t old_args_length
= args_length
;
1768 args_length
= old_args_length
+ arg
->length();
1769 if (args_length
< old_args_length
) {
1770 js_ReportAllocationOverflow(cx
);
1775 /* Add 1 for each joining comma and check for overflow (two ways). */
1776 size_t old_args_length
= args_length
;
1777 args_length
= old_args_length
+ n
- 1;
1778 if (args_length
< old_args_length
||
1779 args_length
>= ~(size_t)0 / sizeof(jschar
)) {
1780 js_ReportAllocationOverflow(cx
);
1785 * Allocate a string to hold the concatenated arguments, including room
1786 * for a terminating 0. Mark cx->tempLifeAlloc for later release, to
1787 * free collected_args and its tokenstream in one swoop.
1789 LifoAllocScope
las(&cx
->tempLifoAlloc());
1790 jschar
* cp
= cx
->tempLifoAlloc().newArray
<jschar
>(args_length
+ 1);
1792 js_ReportOutOfMemory(cx
);
1795 ConstTwoByteChars
collected_args(cp
, args_length
+ 1);
1798 * Concatenate the arguments into the new string, separated by commas.
1800 for (unsigned i
= 0; i
< n
; i
++) {
1801 JSLinearString
* argLinear
= args
[i
].toString()->ensureLinear(cx
);
1805 CopyChars(cp
, *argLinear
);
1806 cp
+= argLinear
->length();
1808 /* Add separating comma or terminating 0. */
1809 *cp
++ = (i
+ 1 < n
) ? ',' : 0;
1813 * Initialize a tokenstream that reads from the given string. No
1814 * StrictModeGetter is needed because this TokenStream won't report any
1815 * strict mode errors. Any strict mode errors which might be reported
1816 * here (duplicate argument names, etc.) will be detected when we
1817 * compile the function body.
1819 TokenStream
ts(cx
, options
, collected_args
.get(), args_length
,
1820 /* strictModeGetter = */ nullptr);
1821 bool yieldIsValidName
= ts
.versionNumber() < JSVERSION_1_7
&& !isStarGenerator
;
1823 /* The argument string may be empty or contain no tokens. */
1824 TokenKind tt
= ts
.getToken();
1825 if (tt
!= TOK_EOF
) {
1828 * Check that it's a name. This also implicitly guards against
1829 * TOK_ERROR, which was already reported.
1832 ts
.reportError(JSMSG_PARAMETER_AFTER_REST
);
1836 if (tt
== TOK_YIELD
&& yieldIsValidName
)
1839 if (tt
!= TOK_NAME
) {
1840 if (tt
== TOK_TRIPLEDOT
) {
1843 if (tt
== TOK_YIELD
&& yieldIsValidName
)
1845 if (tt
!= TOK_NAME
) {
1846 if (tt
!= TOK_ERROR
)
1847 ts
.reportError(JSMSG_NO_REST_NAME
);
1851 return OnBadFormal(cx
, tt
);
1855 if (!formals
.append(ts
.currentName()))
1859 * Get the next token. Stop on end of stream. Otherwise
1860 * insist on a comma, get another name, and iterate.
1865 if (tt
!= TOK_COMMA
)
1866 return OnBadFormal(cx
, tt
);
1873 for (unsigned i
= 0; i
< formals
.length(); ++i
) {
1874 JSString
* str
= formals
[i
];
1875 JS_ASSERT(str
->asAtom().asPropertyName() == formals
[i
]);
1879 RootedString
str(cx
);
1881 str
= cx
->runtime()->emptyString
;
1883 str
= ToString
<CanGC
>(cx
, args
[args
.length() - 1]);
1887 JS::Anchor
<JSString
*> strAnchor(str
);
1890 * NB: (new Function) is not lexically closed by its caller, it's just an
1891 * anonymous function in the top-level scope that its constructor inhabits.
1892 * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,
1893 * and so would a call to f from another top-level's script or function.
1895 RootedAtom
anonymousAtom(cx
, cx
->names().anonymous
);
1896 JSObject
* proto
= nullptr;
1897 if (isStarGenerator
) {
1898 proto
= GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx
, global
);
1902 RootedFunction
fun(cx
, NewFunctionWithProto(cx
, js::NullPtr(), nullptr, 0,
1903 JSFunction::INTERPRETED_LAMBDA
, global
,
1904 anonymousAtom
, proto
,
1905 JSFunction::FinalizeKind
, TenuredObject
));
1909 if (!JSFunction::setTypeForScriptedFunction(cx
, fun
))
1915 AutoStableStringChars
stableChars(cx
);
1916 if (!stableChars
.initTwoByte(cx
, str
))
1919 mozilla::Range
<const jschar
> chars
= stableChars
.twoByteRange();
1920 SourceBufferHolder::Ownership ownership
= stableChars
.maybeGiveOwnershipToCaller()
1921 ? SourceBufferHolder::GiveOwnership
1922 : SourceBufferHolder::NoOwnership
;
1924 SourceBufferHolder
srcBuf(chars
.start().get(), chars
.length(), ownership
);
1925 if (isStarGenerator
)
1926 ok
= frontend::CompileStarGeneratorBody(cx
, &fun
, options
, formals
, srcBuf
);
1928 ok
= frontend::CompileFunctionBody(cx
, &fun
, options
, formals
, srcBuf
);
1929 args
.rval().setObject(*fun
);
1934 js::Function(JSContext
* cx
, unsigned argc
, Value
* vp
)
1936 return FunctionConstructor(cx
, argc
, vp
, NotGenerator
);
1940 js::Generator(JSContext
* cx
, unsigned argc
, Value
* vp
)
1942 return FunctionConstructor(cx
, argc
, vp
, StarGenerator
);
1946 JSFunction::isBuiltinFunctionConstructor()
1948 return maybeNative() == Function
|| maybeNative() == Generator
;
1952 js::NewFunction(ExclusiveContext
* cx
, HandleObject funobjArg
, Native native
, unsigned nargs
,
1953 JSFunction::Flags flags
, HandleObject parent
, HandleAtom atom
,
1954 gc::AllocKind allocKind
/* = JSFunction::FinalizeKind */,
1955 NewObjectKind newKind
/* = GenericObject */)
1957 return NewFunctionWithProto(cx
, funobjArg
, native
, nargs
, flags
, parent
, atom
, nullptr,
1958 allocKind
, newKind
);
1962 js::NewFunctionWithProto(ExclusiveContext
* cx
, HandleObject funobjArg
, Native native
,
1963 unsigned nargs
, JSFunction::Flags flags
, HandleObject parent
,
1964 HandleAtom atom
, JSObject
* proto
,
1965 gc::AllocKind allocKind
/* = JSFunction::FinalizeKind */,
1966 NewObjectKind newKind
/* = GenericObject */)
1968 JS_ASSERT(allocKind
== JSFunction::FinalizeKind
|| allocKind
== JSFunction::ExtendedFinalizeKind
);
1969 JS_ASSERT(sizeof(JSFunction
) <= gc::Arena::thingSize(JSFunction::FinalizeKind
));
1970 JS_ASSERT(sizeof(FunctionExtended
) <= gc::Arena::thingSize(JSFunction::ExtendedFinalizeKind
));
1972 RootedObject
funobj(cx
, funobjArg
);
1974 JS_ASSERT(funobj
->is
<JSFunction
>());
1975 JS_ASSERT(funobj
->getParent() == parent
);
1976 JS_ASSERT_IF(native
, funobj
->hasSingletonType());
1978 // Don't give asm.js module functions a singleton type since they
1979 // are cloned (via CloneFunctionObjectIfNotSingleton) which assumes
1980 // that hasSingletonType implies isInterpreted.
1981 if (native
&& !IsAsmJSModuleNative(native
))
1982 newKind
= SingletonObject
;
1983 funobj
= NewObjectWithClassProto(cx
, &JSFunction::class_
, proto
,
1984 SkipScopeParent(parent
), allocKind
, newKind
);
1988 RootedFunction
fun(cx
, &funobj
->as
<JSFunction
>());
1990 if (allocKind
== JSFunction::ExtendedFinalizeKind
)
1991 flags
= JSFunction::Flags(flags
| JSFunction::EXTENDED
);
1993 /* Initialize all function members. */
1994 fun
->setArgCount(uint16_t(nargs
));
1995 fun
->setFlags(flags
);
1996 if (fun
->isInterpreted()) {
1998 fun
->mutableScript().init(nullptr);
1999 fun
->initEnvironment(parent
);
2001 JS_ASSERT(fun
->isNative());
2003 fun
->initNative(native
, nullptr);
2005 if (allocKind
== JSFunction::ExtendedFinalizeKind
)
2006 fun
->initializeExtended();
2007 fun
->initAtom(atom
);
2013 js::CloneFunctionObject(JSContext
* cx
, HandleFunction fun
, HandleObject parent
, gc::AllocKind allocKind
,
2014 NewObjectKind newKindArg
/* = GenericObject */)
2017 JS_ASSERT(!fun
->isBoundFunction());
2019 bool useSameScript
= cx
->compartment() == fun
->compartment() &&
2020 !fun
->hasSingletonType() &&
2021 !types::UseNewTypeForClone(fun
);
2023 if (!useSameScript
&& fun
->isInterpretedLazy() && !fun
->getOrCreateScript(cx
))
2026 NewObjectKind newKind
= useSameScript
? newKindArg
: SingletonObject
;
2027 JSObject
* cloneProto
= nullptr;
2028 if (fun
->isStarGenerator()) {
2029 cloneProto
= GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx
, cx
->global());
2033 JSObject
* cloneobj
= NewObjectWithClassProto(cx
, &JSFunction::class_
, cloneProto
,
2034 SkipScopeParent(parent
), allocKind
, newKind
);
2037 RootedFunction
clone(cx
, &cloneobj
->as
<JSFunction
>());
2039 uint16_t flags
= fun
->flags() & ~JSFunction::EXTENDED
;
2040 if (allocKind
== JSFunction::ExtendedFinalizeKind
)
2041 flags
|= JSFunction::EXTENDED
;
2043 clone
->setArgCount(fun
->nargs());
2044 clone
->setFlags(flags
);
2045 if (fun
->hasScript()) {
2046 clone
->initScript(fun
->nonLazyScript());
2047 clone
->initEnvironment(parent
);
2048 } else if (fun
->isInterpretedLazy()) {
2049 LazyScript
* lazy
= fun
->lazyScriptOrNull();
2050 clone
->initLazyScript(lazy
);
2051 clone
->initEnvironment(parent
);
2053 clone
->initNative(fun
->native(), fun
->jitInfo());
2055 clone
->initAtom(fun
->displayAtom());
2057 if (allocKind
== JSFunction::ExtendedFinalizeKind
) {
2058 if (fun
->isExtended() && fun
->compartment() == cx
->compartment()) {
2059 for (unsigned i
= 0; i
< FunctionExtended::NUM_EXTENDED_SLOTS
; i
++)
2060 clone
->initExtendedSlot(i
, fun
->getExtendedSlot(i
));
2062 clone
->initializeExtended();
2066 if (useSameScript
) {
2068 * Clone the function, reusing its script. We can use the same type as
2069 * the original function provided that its prototype is correct.
2071 if (fun
->getProto() == clone
->getProto())
2072 clone
->setType(fun
->type());
2076 RootedFunction
cloneRoot(cx
, clone
);
2079 * Across compartments we have to clone the script for interpreted
2080 * functions. Cross-compartment cloning only happens via JSAPI
2081 * (JS_CloneFunctionObject) which dynamically ensures that 'script' has
2082 * no enclosing lexical scope (only the global scope).
2084 if (cloneRoot
->isInterpreted() && !CloneFunctionScript(cx
, fun
, cloneRoot
, newKindArg
))
2091 js::DefineFunction(JSContext
* cx
, HandleObject obj
, HandleId id
, Native native
,
2092 unsigned nargs
, unsigned flags
, AllocKind allocKind
/* = FinalizeKind */,
2093 NewObjectKind newKind
/* = GenericObject */)
2096 StrictPropertyOp sop
;
2098 RootedFunction
fun(cx
);
2100 if (flags
& JSFUN_STUB_GSOPS
) {
2102 * JSFUN_STUB_GSOPS is a request flag only, not stored in fun->flags or
2103 * the defined property's attributes. This allows us to encode another,
2104 * internal flag using the same bit, JSFUN_EXPR_CLOSURE -- see jsfun.h
2107 flags
&= ~JSFUN_STUB_GSOPS
;
2108 gop
= JS_PropertyStub
;
2109 sop
= JS_StrictPropertyStub
;
2115 JSFunction::Flags funFlags
;
2117 funFlags
= JSFunction::INTERPRETED_LAZY
;
2119 funFlags
= JSAPIToJSFunctionFlags(flags
);
2120 RootedAtom
atom(cx
, JSID_IS_ATOM(id
) ? JSID_TO_ATOM(id
) : nullptr);
2121 fun
= NewFunction(cx
, NullPtr(), native
, nargs
, funFlags
, obj
, atom
, allocKind
, newKind
);
2125 RootedValue
funVal(cx
, ObjectValue(*fun
));
2126 if (!JSObject::defineGeneric(cx
, obj
, id
, funVal
, gop
, sop
, flags
& ~JSFUN_FLAGS_MASK
))
2133 js::ReportIncompatibleMethod(JSContext
* cx
, CallReceiver call
, const Class
* clasp
)
2135 RootedValue
thisv(cx
, call
.thisv());
2138 if (thisv
.isObject()) {
2139 JS_ASSERT(thisv
.toObject().getClass() != clasp
||
2140 !thisv
.toObject().isNative() ||
2141 !thisv
.toObject().getProto() ||
2142 thisv
.toObject().getProto()->getClass() != clasp
);
2143 } else if (thisv
.isString()) {
2144 JS_ASSERT(clasp
!= &StringObject::class_
);
2145 } else if (thisv
.isNumber()) {
2146 JS_ASSERT(clasp
!= &NumberObject::class_
);
2147 } else if (thisv
.isBoolean()) {
2148 JS_ASSERT(clasp
!= &BooleanObject::class_
);
2149 } else if (thisv
.isSymbol()) {
2150 JS_ASSERT(clasp
!= &SymbolObject::class_
);
2152 JS_ASSERT(thisv
.isUndefined() || thisv
.isNull());
2156 if (JSFunction
* fun
= ReportIfNotFunction(cx
, call
.calleev())) {
2157 JSAutoByteString funNameBytes
;
2158 if (const char* funName
= GetFunctionNameBytes(cx
, fun
, &funNameBytes
)) {
2159 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, nullptr, JSMSG_INCOMPATIBLE_PROTO
,
2160 clasp
->name
, funName
, InformalValueTypeName(thisv
));
2166 js::ReportIncompatible(JSContext
* cx
, CallReceiver call
)
2168 if (JSFunction
* fun
= ReportIfNotFunction(cx
, call
.calleev())) {
2169 JSAutoByteString funNameBytes
;
2170 if (const char* funName
= GetFunctionNameBytes(cx
, fun
, &funNameBytes
)) {
2171 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, nullptr, JSMSG_INCOMPATIBLE_METHOD
,
2172 funName
, "method", InformalValueTypeName(call
.thisv()));
2178 JSObject::hasIdempotentProtoChain() const
2180 // Return false if obj (or an object on its proto chain) is non-native or
2181 // has a resolve or lookup hook.
2182 JSObject
* obj
= const_cast<JSObject
*>(this);
2184 if (!obj
->isNative())
2187 JSResolveOp resolve
= obj
->getClass()->resolve
;
2188 if (resolve
!= JS_ResolveStub
&& resolve
!= (JSResolveOp
) js::fun_resolve
)
2191 if (obj
->getOps()->lookupProperty
|| obj
->getOps()->lookupGeneric
|| obj
->getOps()->lookupElement
)
2194 obj
= obj
->getProto();
2204 CheckIsValidConstructible(Value calleev
)
2206 JSObject
* callee
= &calleev
.toObject();
2207 if (callee
->is
<JSFunction
>())
2208 JS_ASSERT(callee
->as
<JSFunction
>().isNativeConstructor());
2210 JS_ASSERT(callee
->getClass()->construct
!= nullptr);
2213 } // namespace detail