Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/js/src/vm/JSFunction.h
Line
Count
Source (jump to first uncovered line)
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/. */
6
7
#ifndef vm_JSFunction_h
8
#define vm_JSFunction_h
9
10
/*
11
 * JS function definitions.
12
 */
13
14
#include "jstypes.h"
15
16
#include "vm/JSObject.h"
17
#include "vm/JSScript.h"
18
19
namespace js {
20
21
class FunctionExtended;
22
23
typedef JSNative           Native;
24
} // namespace js
25
26
struct JSAtomState;
27
28
static const uint32_t JSSLOT_BOUND_FUNCTION_TARGET     = 2;
29
static const uint32_t JSSLOT_BOUND_FUNCTION_THIS       = 3;
30
static const uint32_t JSSLOT_BOUND_FUNCTION_ARGS       = 4;
31
32
static const char FunctionConstructorMedialSigils[] = ") {\n";
33
static const char FunctionConstructorFinalBrace[] = "\n}";
34
35
enum class FunctionPrefixKind {
36
    None,
37
    Get,
38
    Set
39
};
40
41
class JSFunction : public js::NativeObject
42
{
43
  public:
44
    static const js::Class class_;
45
46
    enum FunctionKind {
47
        NormalFunction = 0,
48
        Arrow,                      /* ES6 '(args) => body' syntax */
49
        Method,                     /* ES6 MethodDefinition */
50
        ClassConstructor,
51
        Getter,
52
        Setter,
53
        AsmJS,                      /* function is an asm.js module or exported function */
54
        FunctionKindLimit
55
    };
56
57
    enum Flags {
58
        INTERPRETED      = 0x0001,  /* function has a JSScript and environment. */
59
        CONSTRUCTOR      = 0x0002,  /* function that can be called as a constructor */
60
        EXTENDED         = 0x0004,  /* structure is FunctionExtended */
61
        BOUND_FUN        = 0x0008,  /* function was created with Function.prototype.bind. */
62
        WASM_OPTIMIZED   = 0x0010,  /* asm.js/wasm function that has a jit entry */
63
        HAS_GUESSED_ATOM = 0x0020,  /* function had no explicit name, but a
64
                                       name was guessed for it anyway. See
65
                                       atom_ for more info about this flag. */
66
        HAS_BOUND_FUNCTION_NAME_PREFIX = 0x0020, /* bound functions reuse the HAS_GUESSED_ATOM
67
                                                    flag to track if atom_ already contains the
68
                                                    "bound " function name prefix */
69
        LAMBDA           = 0x0040,  /* function comes from a FunctionExpression, ArrowFunction, or
70
                                       Function() call (not a FunctionDeclaration or nonstandard
71
                                       function-statement) */
72
        SELF_HOSTED      = 0x0080,  /* function is self-hosted builtin and must not be
73
                                       decompilable nor constructible. */
74
        HAS_INFERRED_NAME = 0x0100, /* function had no explicit name, but a name was
75
                                       set by SetFunctionName at compile time or
76
                                       SetFunctionNameIfNoOwnName at runtime. See
77
                                       atom_ for more info about this flag. */
78
        INTERPRETED_LAZY = 0x0200,  /* function is interpreted but doesn't have a script yet */
79
        RESOLVED_LENGTH  = 0x0400,  /* f.length has been resolved (see fun_resolve). */
80
        RESOLVED_NAME    = 0x0800,  /* f.name has been resolved (see fun_resolve). */
81
        NEW_SCRIPT_CLEARED  = 0x1000, /* For a function used as an interpreted constructor, whether
82
                                         a 'new' type had constructor information cleared. */
83
84
        FUNCTION_KIND_SHIFT = 13,
85
        FUNCTION_KIND_MASK  = 0x7 << FUNCTION_KIND_SHIFT,
86
87
        ASMJS_KIND = AsmJS << FUNCTION_KIND_SHIFT,
88
        ARROW_KIND = Arrow << FUNCTION_KIND_SHIFT,
89
        METHOD_KIND = Method << FUNCTION_KIND_SHIFT,
90
        CLASSCONSTRUCTOR_KIND = ClassConstructor << FUNCTION_KIND_SHIFT,
91
        GETTER_KIND = Getter << FUNCTION_KIND_SHIFT,
92
        SETTER_KIND = Setter << FUNCTION_KIND_SHIFT,
93
94
        /* Derived Flags values for convenience: */
95
        NATIVE_FUN = 0,
96
        NATIVE_CTOR = NATIVE_FUN | CONSTRUCTOR,
97
        NATIVE_CLASS_CTOR = NATIVE_FUN | CONSTRUCTOR | CLASSCONSTRUCTOR_KIND,
98
        ASMJS_CTOR = ASMJS_KIND | NATIVE_CTOR,
99
        ASMJS_LAMBDA_CTOR = ASMJS_KIND | NATIVE_CTOR | LAMBDA,
100
        ASMJS_NATIVE = ASMJS_KIND | NATIVE_FUN,
101
        WASM_FUN = NATIVE_FUN | WASM_OPTIMIZED,
102
        INTERPRETED_METHOD = INTERPRETED | METHOD_KIND,
103
        INTERPRETED_METHOD_GENERATOR_OR_ASYNC = INTERPRETED | METHOD_KIND,
104
        INTERPRETED_CLASS_CONSTRUCTOR = INTERPRETED | CLASSCONSTRUCTOR_KIND | CONSTRUCTOR,
105
        INTERPRETED_GETTER = INTERPRETED | GETTER_KIND,
106
        INTERPRETED_SETTER = INTERPRETED | SETTER_KIND,
107
        INTERPRETED_LAMBDA = INTERPRETED | LAMBDA | CONSTRUCTOR,
108
        INTERPRETED_LAMBDA_ARROW = INTERPRETED | LAMBDA | ARROW_KIND,
109
        INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC = INTERPRETED | LAMBDA,
110
        INTERPRETED_NORMAL = INTERPRETED | CONSTRUCTOR,
111
        INTERPRETED_GENERATOR_OR_ASYNC = INTERPRETED,
112
        NO_XDR_FLAGS = RESOLVED_LENGTH | RESOLVED_NAME,
113
114
        STABLE_ACROSS_CLONES = CONSTRUCTOR | LAMBDA | SELF_HOSTED | FUNCTION_KIND_MASK
115
    };
116
117
    static_assert((INTERPRETED | INTERPRETED_LAZY) == js::JS_FUNCTION_INTERPRETED_BITS,
118
                  "jsfriendapi.h's JSFunction::INTERPRETED-alike is wrong");
119
    static_assert(((FunctionKindLimit - 1) << FUNCTION_KIND_SHIFT) <= FUNCTION_KIND_MASK,
120
                  "FunctionKind doesn't fit into flags_");
121
122
  private:
123
    uint16_t        nargs_;       /* number of formal arguments
124
                                     (including defaults and the rest parameter unlike f.length) */
125
    uint16_t        flags_;       /* bitfield composed of the above Flags enum, as well as the kind */
126
    union U {
127
        class {
128
            friend class JSFunction;
129
            js::Native func_;          /* native method pointer or null */
130
            union {
131
                // Information about this function to be used by the JIT, only
132
                // used if isBuiltinNative(); use the accessor!
133
                const JSJitInfo* jitInfo_;
134
                // asm.js function index, only used if isAsmJSNative().
135
                size_t asmJSFuncIndex_;
136
                // for wasm, a pointer to a fast jit->wasm table entry.
137
                void** wasmJitEntry_;
138
            } extra;
139
        } native;
140
        struct {
141
            JSObject* env_;            /* environment for new activations */
142
            union {
143
                JSScript* script_;     /* interpreted bytecode descriptor or
144
                                          null; use the accessor! */
145
                js::LazyScript* lazy_; /* lazily compiled script, or nullptr */
146
            } s;
147
        } scripted;
148
    } u;
149
150
    // The |atom_| field can have different meanings depending on the function
151
    // type and flags. It is used for diagnostics, decompiling, and
152
    //
153
    // 1. If the function is not a bound function:
154
    //   a. If HAS_GUESSED_ATOM is not set, to store the initial value of the
155
    //      "name" property of functions. But also see RESOLVED_NAME.
156
    //   b. If HAS_GUESSED_ATOM is set, |atom_| is only used for diagnostics,
157
    //      but must not be used for the "name" property.
158
    //   c. If HAS_INFERRED_NAME is set, the function wasn't given an explicit
159
    //      name in the source text, e.g. |function fn(){}|, but instead it
160
    //      was inferred based on how the function was defined in the source
161
    //      text. The exact name inference rules are defined in the ECMAScript
162
    //      specification.
163
    //      Name inference can happen at compile-time, for example in
164
    //      |var fn = function(){}|, or it can happen at runtime, for example
165
    //      in |var o = {[Symbol.iterator]: function(){}}|. When it happens at
166
    //      compile-time, the HAS_INFERRED_NAME is set directly in the
167
    //      bytecode emitter, when it happens at runtime, the flag is set when
168
    //      evaluating the JSOP_SETFUNNAME bytecode.
169
    //   d. HAS_GUESSED_ATOM and HAS_INFERRED_NAME cannot both be set.
170
    //   e. |atom_| can be null if neither an explicit, nor inferred, nor a
171
    //      guessed name was set.
172
    //   f. HAS_INFERRED_NAME can be set for cloned singleton function, even
173
    //      though the clone shouldn't receive an inferred name. See the
174
    //      comments in NewFunctionClone() and SetFunctionNameIfNoOwnName()
175
    //      for details.
176
    //
177
    // 2. If the function is a bound function:
178
    //   a. To store the initial value of the "name" property.
179
    //   b. If HAS_BOUND_FUNCTION_NAME_PREFIX is not set, |atom_| doesn't
180
    //      contain the "bound " prefix which is prepended to the "name"
181
    //      property of bound functions per ECMAScript.
182
    //   c. Bound functions can never have an inferred or guessed name.
183
    //   d. |atom_| is never null for bound functions.
184
    js::GCPtrAtom atom_;
185
186
  public:
187
    static inline JS::Result<JSFunction*, JS::OOM&>
188
    create(JSContext* cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
189
           js::HandleShape shape, js::HandleObjectGroup group);
190
191
    /* Call objects must be created for each invocation of this function. */
192
323
    bool needsCallObject() const {
193
323
        MOZ_ASSERT(!isInterpretedLazy());
194
323
195
323
        if (isNative()) {
196
0
            return false;
197
0
        }
198
323
199
323
        // Note: this should be kept in sync with
200
323
        // FunctionBox::needsCallObjectRegardlessOfBindings().
201
323
        MOZ_ASSERT_IF(nonLazyScript()->funHasExtensibleScope() ||
202
323
                      nonLazyScript()->needsHomeObject()       ||
203
323
                      nonLazyScript()->isDerivedClassConstructor() ||
204
323
                      isGenerator() ||
205
323
                      isAsync(),
206
323
                      nonLazyScript()->bodyScope()->hasEnvironment());
207
323
208
323
        return nonLazyScript()->bodyScope()->hasEnvironment();
209
323
    }
210
211
    bool needsExtraBodyVarEnvironment() const;
212
    bool needsNamedLambdaEnvironment() const;
213
214
217
    bool needsFunctionEnvironmentObjects() const {
215
217
        return needsCallObject() || needsNamedLambdaEnvironment();
216
217
    }
217
218
40
    bool needsSomeEnvironmentObject() const {
219
40
        return needsFunctionEnvironmentObjects() || needsExtraBodyVarEnvironment();
220
40
    }
221
222
1.62M
    size_t nargs() const {
223
1.62M
        return nargs_;
224
1.62M
    }
225
226
32.5M
    uint16_t flags() const {
227
32.5M
        return flags_;
228
32.5M
    }
229
230
11.3M
    FunctionKind kind() const {
231
11.3M
        return static_cast<FunctionKind>((flags_ & FUNCTION_KIND_MASK) >> FUNCTION_KIND_SHIFT);
232
11.3M
    }
233
234
    /* A function can be classified as either native (C++) or interpreted (JS): */
235
21.1M
    bool isInterpreted()            const { return flags() & (INTERPRETED | INTERPRETED_LAZY); }
236
17.8M
    bool isNative()                 const { return !isInterpreted(); }
237
238
26
    bool isConstructor()            const { return flags() & CONSTRUCTOR; }
239
240
    /* Possible attributes of a native function: */
241
4.87M
    bool isAsmJSNative()            const { return kind() == AsmJS; }
242
8.12M
    bool isWasmOptimized()          const { return (flags() & WASM_OPTIMIZED); }
243
4.87M
    bool isBuiltinNative()          const { return isNativeWithCppEntry() && !isAsmJSNative(); }
244
245
    // May be called from the JIT with the wasmJitEntry_ field.
246
195
    bool isNativeWithJitEntry()     const { return isNative() && isWasmOptimized(); }
247
    // Must be called from the JIT with the native_ field.
248
4.87M
    bool isNativeWithCppEntry()     const { return isNative() && !isWasmOptimized(); }
249
250
    /* Possible attributes of an interpreted function: */
251
10
    bool isBoundFunction()          const { return flags() & BOUND_FUN; }
252
4.99k
    bool hasInferredName()          const { return flags() & HAS_INFERRED_NAME; }
253
5.02k
    bool hasGuessedAtom()           const {
254
5.02k
        static_assert(HAS_GUESSED_ATOM == HAS_BOUND_FUNCTION_NAME_PREFIX,
255
5.02k
                      "HAS_GUESSED_ATOM is unused for bound functions");
256
5.02k
        return (flags() & (HAS_GUESSED_ATOM | BOUND_FUN)) == HAS_GUESSED_ATOM;
257
5.02k
    }
258
0
    bool hasBoundFunctionNamePrefix() const {
259
0
        static_assert(HAS_BOUND_FUNCTION_NAME_PREFIX == HAS_GUESSED_ATOM,
260
0
                      "HAS_BOUND_FUNCTION_NAME_PREFIX is only used for bound functions");
261
0
        MOZ_ASSERT(isBoundFunction());
262
0
        return flags() & HAS_BOUND_FUNCTION_NAME_PREFIX;
263
0
    }
264
6.22k
    bool isLambda()                 const { return flags() & LAMBDA; }
265
3.25M
    bool isInterpretedLazy()        const { return flags() & INTERPRETED_LAZY; }
266
267
    // This method doesn't check the non-nullness of u.scripted.s.script_,
268
    // because it's guaranteed to be non-null when this has INTERPRETED flag,
269
    // for live JSFunctions.
270
    //
271
    // When this JSFunction instance is reached via GC iteration, the above
272
    // doesn't hold, and hasUncompletedScript should also be checked.
273
    // (see the comment above hasUncompletedScript for more details).
274
6.34k
    bool hasScript()                const { return flags() & INTERPRETED; }
275
276
    bool infallibleIsDefaultClassConstructor(JSContext* cx) const;
277
278
    // Arrow functions store their lexical new.target in the first extended slot.
279
1.78k
    bool isArrow()                  const { return kind() == Arrow; }
280
    // Every class-constructor is also a method.
281
1.46k
    bool isMethod()                 const { return kind() == Method || kind() == ClassConstructor; }
282
6.48M
    bool isClassConstructor()       const { return kind() == ClassConstructor; }
283
284
1.44k
    bool isGetter()                 const { return kind() == Getter; }
285
1.43k
    bool isSetter()                 const { return kind() == Setter; }
286
287
1.46k
    bool allowSuperProperty() const {
288
1.46k
        return isMethod() || isGetter() || isSetter();
289
1.46k
    }
290
291
0
    bool hasResolvedLength()        const { return flags() & RESOLVED_LENGTH; }
292
0
    bool hasResolvedName()          const { return flags() & RESOLVED_NAME; }
293
294
30
    bool isSelfHostedOrIntrinsic()  const { return flags() & SELF_HOSTED; }
295
30
    bool isSelfHostedBuiltin()      const { return isSelfHostedOrIntrinsic() && !isNative(); }
296
0
    bool isIntrinsic()              const { return isSelfHostedOrIntrinsic() && isNative(); }
297
298
0
    bool hasJITCode() const {
299
0
        if (!hasScript()) {
300
0
            return false;
301
0
        }
302
0
303
0
        return nonLazyScript()->hasBaselineScript() || nonLazyScript()->hasIonScript();
304
0
    }
305
10
    bool hasJitEntry() const {
306
10
        return hasScript() || isNativeWithJitEntry();
307
10
    }
308
309
    /* Compound attributes: */
310
36
    bool isBuiltin() const {
311
36
        return isBuiltinNative() || isNativeWithJitEntry() || isSelfHostedBuiltin();
312
36
    }
313
314
6.22k
    bool isNamedLambda() const {
315
6.22k
        return isLambda() && displayAtom() && !hasInferredName() && !hasGuessedAtom();
316
6.22k
    }
317
318
0
    bool hasLexicalThis() const {
319
0
        return isArrow();
320
0
    }
321
322
    bool isBuiltinFunctionConstructor();
323
    bool needsPrototypeProperty();
324
325
    /* Returns the strictness of this function, which must be interpreted. */
326
0
    bool strict() const {
327
0
        MOZ_ASSERT(isInterpreted());
328
0
        return isInterpretedLazy() ? lazyScript()->strict() : nonLazyScript()->strict();
329
0
    }
330
331
6.50M
    void setFlags(uint16_t flags) {
332
6.50M
        this->flags_ = flags;
333
6.50M
    }
334
0
    void setKind(FunctionKind kind) {
335
0
        this->flags_ &= ~FUNCTION_KIND_MASK;
336
0
        this->flags_ |= static_cast<uint16_t>(kind) << FUNCTION_KIND_SHIFT;
337
0
    }
338
339
    // Make the function constructible.
340
6
    void setIsConstructor() {
341
6
        MOZ_ASSERT(!isConstructor());
342
6
        MOZ_ASSERT(isSelfHostedBuiltin());
343
6
        flags_ |= CONSTRUCTOR;
344
6
    }
345
346
0
    void setIsClassConstructor() {
347
0
        MOZ_ASSERT(!isClassConstructor());
348
0
        MOZ_ASSERT(isConstructor());
349
0
350
0
        setKind(ClassConstructor);
351
0
    }
352
353
    // Can be called multiple times by the parser.
354
3.25M
    void setArgCount(uint16_t nargs) {
355
3.25M
        this->nargs_ = nargs;
356
3.25M
    }
357
358
0
    void setIsBoundFunction() {
359
0
        MOZ_ASSERT(!isBoundFunction());
360
0
        flags_ |= BOUND_FUN;
361
0
    }
362
363
1.54k
    void setIsSelfHostedBuiltin() {
364
1.54k
        MOZ_ASSERT(isInterpreted());
365
1.54k
        MOZ_ASSERT(!isSelfHostedBuiltin());
366
1.54k
        flags_ |= SELF_HOSTED;
367
1.54k
        // Self-hosted functions should not be constructable.
368
1.54k
        flags_ &= ~CONSTRUCTOR;
369
1.54k
    }
370
753
    void setIsIntrinsic() {
371
753
        MOZ_ASSERT(isNative());
372
753
        MOZ_ASSERT(!isIntrinsic());
373
753
        flags_ |= SELF_HOSTED;
374
753
    }
375
376
0
    void setArrow() {
377
0
        setKind(Arrow);
378
0
    }
379
380
0
    void setResolvedLength() {
381
0
        flags_ |= RESOLVED_LENGTH;
382
0
    }
383
384
0
    void setResolvedName() {
385
0
        flags_ |= RESOLVED_NAME;
386
0
    }
387
388
    // Mark a function as having its 'new' script information cleared.
389
10
    bool wasNewScriptCleared() const {
390
10
        return flags_ & NEW_SCRIPT_CLEARED;
391
10
    }
392
0
    void setNewScriptCleared() {
393
0
        flags_ |= NEW_SCRIPT_CLEARED;
394
0
    }
395
396
0
    void setAsyncKind(js::FunctionAsyncKind asyncKind) {
397
0
        if (isInterpretedLazy()) {
398
0
            lazyScript()->setAsyncKind(asyncKind);
399
0
        } else {
400
0
            nonLazyScript()->setAsyncKind(asyncKind);
401
0
        }
402
0
    }
403
404
    static bool getUnresolvedLength(JSContext* cx, js::HandleFunction fun,
405
                                    js::MutableHandleValue v);
406
407
    JSAtom* infallibleGetUnresolvedName(JSContext* cx);
408
409
    static bool getUnresolvedName(JSContext* cx, js::HandleFunction fun,
410
                                  js::MutableHandleString v);
411
412
    static JSLinearString* getBoundFunctionName(JSContext* cx, js::HandleFunction fun);
413
414
4.64k
    JSAtom* explicitName() const {
415
4.64k
        return (hasInferredName() || hasGuessedAtom()) ? nullptr : atom_.get();
416
4.64k
    }
417
0
    JSAtom* explicitOrInferredName() const {
418
0
        return hasGuessedAtom() ? nullptr : atom_.get();
419
0
    }
420
421
3.25M
    void initAtom(JSAtom* atom) {
422
3.25M
        MOZ_ASSERT_IF(atom, js::AtomIsMarked(zone(), atom));
423
3.25M
        atom_.init(atom);
424
3.25M
    }
425
426
156
    void setAtom(JSAtom* atom) {
427
156
        MOZ_ASSERT_IF(atom, js::AtomIsMarked(zone(), atom));
428
156
        atom_ = atom;
429
156
    }
430
431
3.81k
    JSAtom* displayAtom() const {
432
3.81k
        return atom_;
433
3.81k
    }
434
435
79
    void setInferredName(JSAtom* atom) {
436
79
        MOZ_ASSERT(!atom_);
437
79
        MOZ_ASSERT(atom);
438
79
        MOZ_ASSERT(!hasGuessedAtom());
439
79
        setAtom(atom);
440
79
        flags_ |= HAS_INFERRED_NAME;
441
79
    }
442
6
    void clearInferredName() {
443
6
        MOZ_ASSERT(hasInferredName());
444
6
        MOZ_ASSERT(atom_);
445
6
        setAtom(nullptr);
446
6
        flags_ &= ~HAS_INFERRED_NAME;
447
6
    }
448
0
    JSAtom* inferredName() const {
449
0
        MOZ_ASSERT(hasInferredName());
450
0
        MOZ_ASSERT(atom_);
451
0
        return atom_;
452
0
    }
453
454
14
    void setGuessedAtom(JSAtom* atom) {
455
14
        MOZ_ASSERT(!atom_);
456
14
        MOZ_ASSERT(atom);
457
14
        MOZ_ASSERT(!hasInferredName());
458
14
        MOZ_ASSERT(!hasGuessedAtom());
459
14
        MOZ_ASSERT(!isBoundFunction());
460
14
        setAtom(atom);
461
14
        flags_ |= HAS_GUESSED_ATOM;
462
14
    }
463
0
    void clearGuessedAtom() {
464
0
        MOZ_ASSERT(hasGuessedAtom());
465
0
        MOZ_ASSERT(!isBoundFunction());
466
0
        MOZ_ASSERT(atom_);
467
0
        setAtom(nullptr);
468
0
        flags_ &= ~HAS_GUESSED_ATOM;
469
0
    }
470
471
0
    void setPrefixedBoundFunctionName(JSAtom* atom) {
472
0
        MOZ_ASSERT(!hasBoundFunctionNamePrefix());
473
0
        MOZ_ASSERT(atom);
474
0
        flags_ |= HAS_BOUND_FUNCTION_NAME_PREFIX;
475
0
        setAtom(atom);
476
0
    }
477
478
    /* uint16_t representation bounds number of call object dynamic slots. */
479
    enum { MAX_ARGS_AND_VARS = 2 * ((1U << 16) - 1) };
480
481
    /*
482
     * For an interpreted function, accessors for the initial scope object of
483
     * activations (stack frames) of the function.
484
     */
485
161
    JSObject* environment() const {
486
161
        MOZ_ASSERT(isInterpreted());
487
161
        return u.scripted.env_;
488
161
    }
489
490
1.32k
    void setEnvironment(JSObject* obj) {
491
1.32k
        MOZ_ASSERT(isInterpreted());
492
1.32k
        *reinterpret_cast<js::GCPtrObject*>(&u.scripted.env_) = obj;
493
1.32k
    }
494
495
1.76k
    void initEnvironment(JSObject* obj) {
496
1.76k
        MOZ_ASSERT(isInterpreted());
497
1.76k
        reinterpret_cast<js::GCPtrObject*>(&u.scripted.env_)->init(obj);
498
1.76k
    }
499
500
0
    void unsetEnvironment() {
501
0
        setEnvironment(nullptr);
502
0
    }
503
504
  public:
505
131
    static constexpr size_t offsetOfNargs() { return offsetof(JSFunction, nargs_); }
506
0
    static constexpr size_t offsetOfFlags() { return offsetof(JSFunction, flags_); }
507
28
    static size_t offsetOfEnvironment() { return offsetof(JSFunction, u.scripted.env_); }
508
0
    static size_t offsetOfAtom() { return offsetof(JSFunction, atom_); }
509
510
    static bool createScriptForLazilyInterpretedFunction(JSContext* cx, js::HandleFunction fun);
511
    void maybeRelazify(JSRuntime* rt);
512
513
    // Function Scripts
514
    //
515
    // Interpreted functions may either have an explicit JSScript (hasScript())
516
    // or be lazy with sufficient information to construct the JSScript if
517
    // necessary (isInterpretedLazy()).
518
    //
519
    // A lazy function will have a LazyScript if the function came from parsed
520
    // source, or nullptr if the function is a clone of a self hosted function.
521
    //
522
    // There are several methods to get the script of an interpreted function:
523
    //
524
    // - For all interpreted functions, getOrCreateScript() will get the
525
    //   JSScript, delazifying the function if necessary. This is the safest to
526
    //   use, but has extra checks, requires a cx and may trigger a GC.
527
    //
528
    // - For inlined functions which may have a LazyScript but whose JSScript
529
    //   is known to exist, existingScript() will get the script and delazify
530
    //   the function if necessary. If the function should not be delazified,
531
    //   use existingScriptNonDelazifying().
532
    //
533
    // - For functions known to have a JSScript, nonLazyScript() will get it.
534
535
1.62M
    static JSScript* getOrCreateScript(JSContext* cx, js::HandleFunction fun) {
536
1.62M
        MOZ_ASSERT(fun->isInterpreted());
537
1.62M
        MOZ_ASSERT(cx);
538
1.62M
        if (fun->isInterpretedLazy()) {
539
3
            if (!createScriptForLazilyInterpretedFunction(cx, fun)) {
540
0
                return nullptr;
541
0
            }
542
3
            return fun->nonLazyScript();
543
3
        }
544
1.62M
        return fun->nonLazyScript();
545
1.62M
    }
546
547
0
    JSScript* existingScriptNonDelazifying() const {
548
0
        MOZ_ASSERT(isInterpreted());
549
0
        if (isInterpretedLazy()) {
550
0
            // Get the script from the canonical function. Ion used the
551
0
            // canonical function to inline the script and because it has
552
0
            // Baseline code it has not been relazified. Note that we can't
553
0
            // use lazyScript->script_ here as it may be null in some cases,
554
0
            // see bug 976536.
555
0
            js::LazyScript* lazy = lazyScript();
556
0
            JSFunction* fun = lazy->functionNonDelazifying();
557
0
            MOZ_ASSERT(fun);
558
0
            return fun->nonLazyScript();
559
0
        }
560
0
        return nonLazyScript();
561
0
    }
562
563
0
    JSScript* existingScript() {
564
0
        MOZ_ASSERT(isInterpreted());
565
0
        if (isInterpretedLazy()) {
566
0
            if (shadowZone()->needsIncrementalBarrier()) {
567
0
                js::LazyScript::writeBarrierPre(lazyScript());
568
0
            }
569
0
            JSScript* script = existingScriptNonDelazifying();
570
0
            flags_ &= ~INTERPRETED_LAZY;
571
0
            flags_ |= INTERPRETED;
572
0
            initScript(script);
573
0
        }
574
0
        return nonLazyScript();
575
0
    }
576
577
    // The state of a JSFunction whose script errored out during bytecode
578
    // compilation. Such JSFunctions are only reachable via GC iteration and
579
    // not from script.
580
    // If u.scripted.s.script_ is non-null, the pointed JSScript is guaranteed
581
    // to be complete (see the comment above JSScript::initFromFunctionBox
582
    // callsite in JSScript::fullyInitFromEmitter).
583
4.01k
    bool hasUncompletedScript() const {
584
4.01k
        MOZ_ASSERT(hasScript());
585
4.01k
        return !u.scripted.s.script_;
586
4.01k
    }
587
588
3.56M
    JSScript* nonLazyScript() const {
589
3.56M
        MOZ_ASSERT(!hasUncompletedScript());
590
3.56M
        return u.scripted.s.script_;
591
3.56M
    }
592
593
    static bool getLength(JSContext* cx, js::HandleFunction fun, uint16_t* length);
594
595
0
    js::LazyScript* lazyScript() const {
596
0
        MOZ_ASSERT(isInterpretedLazy() && u.scripted.s.lazy_);
597
0
        return u.scripted.s.lazy_;
598
0
    }
599
600
6
    js::LazyScript* lazyScriptOrNull() const {
601
6
        MOZ_ASSERT(isInterpretedLazy());
602
6
        return u.scripted.s.lazy_;
603
6
    }
604
605
371
    js::GeneratorKind generatorKind() const {
606
371
        if (!isInterpreted()) {
607
13
            return js::GeneratorKind::NotGenerator;
608
13
        }
609
358
        if (hasScript()) {
610
358
            return nonLazyScript()->generatorKind();
611
358
        }
612
0
        if (js::LazyScript* lazy = lazyScriptOrNull()) {
613
0
            return lazy->generatorKind();
614
0
        }
615
0
        MOZ_ASSERT(isSelfHostedBuiltin());
616
0
        return js::GeneratorKind::NotGenerator;
617
0
    }
618
619
371
    bool isGenerator() const { return generatorKind() == js::GeneratorKind::Generator; }
620
621
0
    js::FunctionAsyncKind asyncKind() const {
622
0
        return isInterpretedLazy() ? lazyScript()->asyncKind() : nonLazyScript()->asyncKind();
623
0
    }
624
625
369
    bool isAsync() const {
626
369
        if (isInterpretedLazy()) {
627
0
            return lazyScript()->isAsync();
628
0
        }
629
369
        if (hasScript()) {
630
356
            return nonLazyScript()->isAsync();
631
356
        }
632
13
        return false;
633
13
    }
634
635
1.48k
    void setScript(JSScript* script_) {
636
1.48k
        mutableScript() = script_;
637
1.48k
    }
638
639
1.65k
    void initScript(JSScript* script_) {
640
1.65k
        mutableScript().init(script_);
641
1.65k
    }
642
643
3
    void setUnlazifiedScript(JSScript* script) {
644
3
        MOZ_ASSERT(isInterpretedLazy());
645
3
        if (lazyScriptOrNull()) {
646
0
            // Trigger a pre barrier on the lazy script being overwritten.
647
0
            js::LazyScript::writeBarrierPre(lazyScriptOrNull());
648
0
            if (!lazyScript()->maybeScript()) {
649
0
                lazyScript()->initScript(script);
650
0
            }
651
0
        }
652
3
        flags_ &= ~INTERPRETED_LAZY;
653
3
        flags_ |= INTERPRETED;
654
3
        initScript(script);
655
3
    }
656
657
129
    void initLazyScript(js::LazyScript* lazy) {
658
129
        MOZ_ASSERT(isInterpreted());
659
129
        flags_ &= ~INTERPRETED;
660
129
        flags_ |= INTERPRETED_LAZY;
661
129
        u.scripted.s.lazy_ = lazy;
662
129
    }
663
664
4.86M
    JSNative native() const {
665
4.86M
        MOZ_ASSERT(isNative());
666
4.86M
        return u.native.func_;
667
4.86M
    }
668
669
36
    JSNative maybeNative() const {
670
36
        return isInterpreted() ? nullptr : native();
671
36
    }
672
673
3.24M
    void initNative(js::Native native, const JSJitInfo* jitInfo) {
674
3.24M
        MOZ_ASSERT(isNativeWithCppEntry());
675
3.24M
        MOZ_ASSERT_IF(jitInfo, isBuiltinNative());
676
3.24M
        MOZ_ASSERT(native);
677
3.24M
        u.native.func_ = native;
678
3.24M
        u.native.extra.jitInfo_ = jitInfo;
679
3.24M
    }
680
4.87M
    bool hasJitInfo() const {
681
4.87M
        return isBuiltinNative() && u.native.extra.jitInfo_;
682
4.87M
    }
683
62
    const JSJitInfo* jitInfo() const {
684
62
        MOZ_ASSERT(hasJitInfo());
685
62
        return u.native.extra.jitInfo_;
686
62
    }
687
283
    void setJitInfo(const JSJitInfo* data) {
688
283
        MOZ_ASSERT(isBuiltinNative());
689
283
        u.native.extra.jitInfo_ = data;
690
283
    }
691
692
    // Wasm natives are optimized and have a jit entry.
693
0
    void initWasmNative(js::Native native) {
694
0
        MOZ_ASSERT(isNativeWithJitEntry());
695
0
        MOZ_ASSERT(native);
696
0
        u.native.func_ = native;
697
0
        u.native.extra.wasmJitEntry_ = nullptr;
698
0
    }
699
0
    void setWasmJitEntry(void** entry) {
700
0
        MOZ_ASSERT(isNativeWithJitEntry());
701
0
        MOZ_ASSERT(entry);
702
0
        MOZ_ASSERT(!u.native.extra.wasmJitEntry_);
703
0
        u.native.extra.wasmJitEntry_ = entry;
704
0
    }
705
0
    void** wasmJitEntry() const {
706
0
        MOZ_ASSERT(isNativeWithJitEntry());
707
0
        MOZ_ASSERT(u.native.extra.wasmJitEntry_);
708
0
        return u.native.extra.wasmJitEntry_;
709
0
    }
710
711
    // AsmJS functions store the func index in the jitinfo slot, since these
712
    // don't have a jit info associated.
713
0
    void setAsmJSIndex(uint32_t funcIndex) {
714
0
        MOZ_ASSERT(isAsmJSNative());
715
0
        MOZ_ASSERT(!isWasmOptimized());
716
0
        MOZ_ASSERT(!u.native.extra.asmJSFuncIndex_);
717
0
        u.native.extra.asmJSFuncIndex_ = funcIndex;
718
0
    }
719
0
    uint32_t asmJSFuncIndex() const {
720
0
        MOZ_ASSERT(isAsmJSNative());
721
0
        MOZ_ASSERT(!isWasmOptimized());
722
0
        return u.native.extra.asmJSFuncIndex_;
723
0
    }
724
725
    bool isDerivedClassConstructor();
726
727
1
    static unsigned offsetOfNative() {
728
1
        return offsetof(JSFunction, u.native.func_);
729
1
    }
730
46
    static unsigned offsetOfScript() {
731
46
        static_assert(offsetof(U, scripted.s.script_) == offsetof(U, native.extra.wasmJitEntry_),
732
46
                      "scripted.s.script_ must be at the same offset as native.extra.wasmJitEntry_");
733
46
        return offsetof(JSFunction, u.scripted.s.script_);
734
46
    }
735
0
    static unsigned offsetOfNativeOrEnv() {
736
0
        static_assert(offsetof(U, native.func_) == offsetof(U, scripted.env_),
737
0
                      "U.native.func_ must be at the same offset as U.scripted.env_");
738
0
        return offsetOfNative();
739
0
    }
740
0
    static unsigned offsetOfScriptOrLazyScript() {
741
0
        static_assert(offsetof(U, scripted.s.script_) == offsetof(U, scripted.s.lazy_),
742
0
                      "U.scripted.s.script_ must be at the same offset as lazy_");
743
0
        return offsetof(JSFunction, u.scripted.s.script_);
744
0
    }
745
746
0
    static unsigned offsetOfJitInfo() {
747
0
        return offsetof(JSFunction, u.native.extra.jitInfo_);
748
0
    }
749
750
    inline void trace(JSTracer* trc);
751
752
    /* Bound function accessors. */
753
754
    JSObject* getBoundFunctionTarget() const;
755
    const js::Value& getBoundFunctionThis() const;
756
    const js::Value& getBoundFunctionArgument(unsigned which) const;
757
    size_t getBoundFunctionArgumentCount() const;
758
759
    /*
760
     * Used to mark bound functions as such and make them constructible if the
761
     * target is. Also assigns the prototype and sets the name and correct length.
762
     */
763
    static bool finishBoundFunctionInit(JSContext* cx, js::HandleFunction bound,
764
                                        js::HandleObject targetObj, int32_t argCount);
765
766
  private:
767
3.13k
    js::GCPtrScript& mutableScript() {
768
3.13k
        MOZ_ASSERT(hasScript());
769
3.13k
        return *(js::GCPtrScript*)&u.scripted.s.script_;
770
3.13k
    }
771
772
    inline js::FunctionExtended* toExtended();
773
    inline const js::FunctionExtended* toExtended() const;
774
775
  public:
776
8.40k
    inline bool isExtended() const {
777
8.40k
        bool extended = !!(flags() & EXTENDED);
778
8.40k
        MOZ_ASSERT_IF(isTenured(),
779
8.40k
                      extended == (asTenured().getAllocKind() == js::gc::AllocKind::FUNCTION_EXTENDED));
780
8.40k
        return extended;
781
8.40k
    }
782
783
    /*
784
     * Accessors for data stored in extended functions. Use setExtendedSlot if
785
     * the function has already been initialized. Otherwise use
786
     * initExtendedSlot.
787
     */
788
    inline void initializeExtended();
789
    inline void initExtendedSlot(size_t which, const js::Value& val);
790
    inline void setExtendedSlot(size_t which, const js::Value& val);
791
    inline const js::Value& getExtendedSlot(size_t which) const;
792
793
    /* Constructs a new type for the function if necessary. */
794
    static bool setTypeForScriptedFunction(JSContext* cx, js::HandleFunction fun,
795
                                           bool singleton = false);
796
797
    /* GC support. */
798
142
    js::gc::AllocKind getAllocKind() const {
799
142
        static_assert(js::gc::AllocKind::FUNCTION != js::gc::AllocKind::FUNCTION_EXTENDED,
800
142
                      "extended/non-extended AllocKinds have to be different "
801
142
                      "for getAllocKind() to have a reason to exist");
802
142
803
142
        js::gc::AllocKind kind = js::gc::AllocKind::FUNCTION;
804
142
        if (isExtended()) {
805
27
            kind = js::gc::AllocKind::FUNCTION_EXTENDED;
806
27
        }
807
142
        MOZ_ASSERT_IF(isTenured(), kind == asTenured().getAllocKind());
808
142
        return kind;
809
142
    }
810
};
811
812
static_assert(sizeof(JSFunction) == sizeof(js::shadow::Function),
813
              "shadow interface must match actual interface");
814
815
extern JSString*
816
fun_toStringHelper(JSContext* cx, js::HandleObject obj, bool isToSource);
817
818
namespace js {
819
820
extern bool
821
Function(JSContext* cx, unsigned argc, Value* vp);
822
823
extern bool
824
Generator(JSContext* cx, unsigned argc, Value* vp);
825
826
extern bool
827
AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp);
828
829
extern bool
830
AsyncGeneratorConstructor(JSContext* cx, unsigned argc, Value* vp);
831
832
// If enclosingEnv is null, the function will have a null environment()
833
// (yes, null, not the global).  In all cases, the global will be used as the
834
// parent.
835
836
extern JSFunction*
837
NewFunctionWithProto(JSContext* cx, JSNative native, unsigned nargs,
838
                     JSFunction::Flags flags, HandleObject enclosingEnv, HandleAtom atom,
839
                     HandleObject proto, gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
840
                     NewObjectKind newKind = GenericObject);
841
842
// Allocate a new function backed by a JSNative.  Note that by default this
843
// creates a singleton object.
844
inline JSFunction*
845
NewNativeFunction(JSContext* cx, JSNative native, unsigned nargs, HandleAtom atom,
846
                  gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
847
                  NewObjectKind newKind = SingletonObject,
848
                  JSFunction::Flags flags = JSFunction::NATIVE_FUN)
849
3.24M
{
850
3.24M
    MOZ_ASSERT(native);
851
3.24M
    return NewFunctionWithProto(cx, native, nargs, flags, nullptr, atom, nullptr, allocKind,
852
3.24M
                                newKind);
853
3.24M
}
854
855
// Allocate a new constructor backed by a JSNative.  Note that by default this
856
// creates a singleton object.
857
inline JSFunction*
858
NewNativeConstructor(JSContext* cx, JSNative native, unsigned nargs, HandleAtom atom,
859
                     gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
860
                     NewObjectKind newKind = SingletonObject,
861
                     JSFunction::Flags flags = JSFunction::NATIVE_CTOR)
862
25
{
863
25
    MOZ_ASSERT(native);
864
25
    MOZ_ASSERT(flags & JSFunction::NATIVE_CTOR);
865
25
    return NewFunctionWithProto(cx, native, nargs, flags, nullptr, atom, nullptr, allocKind,
866
25
                                newKind);
867
25
}
868
869
// Allocate a new scripted function.  If enclosingEnv is null, the
870
// global will be used.  In all cases the parent of the resulting object will be
871
// the global.
872
extern JSFunction*
873
NewScriptedFunction(JSContext* cx, unsigned nargs, JSFunction::Flags flags,
874
                    HandleAtom atom, HandleObject proto = nullptr,
875
                    gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
876
                    NewObjectKind newKind = GenericObject,
877
                    HandleObject enclosingEnv = nullptr);
878
extern JSAtom*
879
IdToFunctionName(JSContext* cx, HandleId id,
880
                 FunctionPrefixKind prefixKind = FunctionPrefixKind::None);
881
882
extern bool
883
SetFunctionNameIfNoOwnName(JSContext* cx, HandleFunction fun, HandleValue name,
884
                           FunctionPrefixKind prefixKind);
885
886
extern JSFunction*
887
DefineFunction(JSContext* cx, HandleObject obj, HandleId id, JSNative native,
888
               unsigned nargs, unsigned flags,
889
               gc::AllocKind allocKind = gc::AllocKind::FUNCTION);
890
891
extern bool
892
fun_toString(JSContext* cx, unsigned argc, Value* vp);
893
894
struct WellKnownSymbols;
895
896
extern bool
897
FunctionHasDefaultHasInstance(JSFunction* fun, const WellKnownSymbols& symbols);
898
899
extern bool
900
fun_symbolHasInstance(JSContext* cx, unsigned argc, Value* vp);
901
902
extern void
903
ThrowTypeErrorBehavior(JSContext* cx);
904
905
/*
906
 * Function extended with reserved slots for use by various kinds of functions.
907
 * Most functions do not have these extensions, but enough do that efficient
908
 * storage is required (no malloc'ed reserved slots).
909
 */
910
class FunctionExtended : public JSFunction
911
{
912
  public:
913
    static const unsigned NUM_EXTENDED_SLOTS = 2;
914
915
    /* Arrow functions store their lexical new.target in the first extended slot. */
916
    static const unsigned ARROW_NEWTARGET_SLOT = 0;
917
918
    static const unsigned METHOD_HOMEOBJECT_SLOT = 0;
919
920
    /*
921
     * Exported asm.js/wasm functions store their WasmInstanceObject in the
922
     * first slot.
923
     */
924
    static const unsigned WASM_INSTANCE_SLOT = 0;
925
926
    /*
927
     * wasm/asm.js exported functions store the wasm::TlsData pointer of their
928
     * instance.
929
     */
930
    static const unsigned WASM_TLSDATA_SLOT = 1;
931
932
    /*
933
     * asm.js module functions store their WasmModuleObject in the first slot.
934
     */
935
    static const unsigned ASMJS_MODULE_SLOT = 0;
936
937
938
0
    static inline size_t offsetOfExtendedSlot(unsigned which) {
939
0
        MOZ_ASSERT(which < NUM_EXTENDED_SLOTS);
940
0
        return offsetof(FunctionExtended, extendedSlots) + which * sizeof(GCPtrValue);
941
0
    }
942
0
    static inline size_t offsetOfArrowNewTargetSlot() {
943
0
        return offsetOfExtendedSlot(ARROW_NEWTARGET_SLOT);
944
0
    }
945
0
    static inline size_t offsetOfMethodHomeObjectSlot() {
946
0
        return offsetOfExtendedSlot(METHOD_HOMEOBJECT_SLOT);
947
0
    }
948
949
  private:
950
    friend class JSFunction;
951
952
    /* Reserved slots available for storage by particular native functions. */
953
    GCPtrValue extendedSlots[NUM_EXTENDED_SLOTS];
954
};
955
956
extern bool
957
CanReuseScriptForClone(JS::Realm* realm, HandleFunction fun, HandleObject newParent);
958
959
extern JSFunction*
960
CloneFunctionReuseScript(JSContext* cx, HandleFunction fun, HandleObject parent,
961
                         gc::AllocKind kind = gc::AllocKind::FUNCTION,
962
                         NewObjectKind newKindArg = GenericObject,
963
                         HandleObject proto = nullptr);
964
965
// Functions whose scripts are cloned are always given singleton types.
966
extern JSFunction*
967
CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject parent,
968
                       HandleScope newScope,
969
                       gc::AllocKind kind = gc::AllocKind::FUNCTION,
970
                       HandleObject proto = nullptr);
971
972
extern JSFunction*
973
CloneAsmJSModuleFunction(JSContext* cx, HandleFunction fun);
974
975
extern JSFunction*
976
CloneSelfHostingIntrinsic(JSContext* cx, HandleFunction fun);
977
978
} // namespace js
979
980
inline js::FunctionExtended*
981
JSFunction::toExtended()
982
16.2M
{
983
16.2M
    MOZ_ASSERT(isExtended());
984
16.2M
    return static_cast<js::FunctionExtended*>(this);
985
16.2M
}
986
987
inline const js::FunctionExtended*
988
JSFunction::toExtended() const
989
12.9M
{
990
12.9M
    MOZ_ASSERT(isExtended());
991
12.9M
    return static_cast<const js::FunctionExtended*>(this);
992
12.9M
}
993
994
inline void
995
JSFunction::initializeExtended()
996
3.24M
{
997
3.24M
    MOZ_ASSERT(isExtended());
998
3.24M
999
3.24M
    MOZ_ASSERT(mozilla::ArrayLength(toExtended()->extendedSlots) == 2);
1000
3.24M
    toExtended()->extendedSlots[0].init(js::UndefinedValue());
1001
3.24M
    toExtended()->extendedSlots[1].init(js::UndefinedValue());
1002
3.24M
}
1003
1004
inline void
1005
JSFunction::initExtendedSlot(size_t which, const js::Value& val)
1006
54
{
1007
54
    MOZ_ASSERT(which < mozilla::ArrayLength(toExtended()->extendedSlots));
1008
54
    MOZ_ASSERT(js::IsObjectValueInCompartment(val, compartment()));
1009
54
    toExtended()->extendedSlots[which].init(val);
1010
54
}
1011
1012
inline void
1013
JSFunction::setExtendedSlot(size_t which, const js::Value& val)
1014
6.49M
{
1015
6.49M
    MOZ_ASSERT(which < mozilla::ArrayLength(toExtended()->extendedSlots));
1016
6.49M
    MOZ_ASSERT(js::IsObjectValueInCompartment(val, compartment()));
1017
6.49M
    toExtended()->extendedSlots[which] = val;
1018
6.49M
}
1019
1020
inline const js::Value&
1021
JSFunction::getExtendedSlot(size_t which) const
1022
12.9M
{
1023
12.9M
    MOZ_ASSERT(which < mozilla::ArrayLength(toExtended()->extendedSlots));
1024
12.9M
    return toExtended()->extendedSlots[which];
1025
12.9M
}
1026
1027
namespace js {
1028
1029
JSString* FunctionToString(JSContext* cx, HandleFunction fun, bool isToSource);
1030
1031
template<XDRMode mode>
1032
XDRResult
1033
XDRInterpretedFunction(XDRState<mode>* xdr, HandleScope enclosingScope,
1034
                       HandleScriptSourceObject sourceObject, MutableHandleFunction objp);
1035
1036
/*
1037
 * Report an error that call.thisv is not compatible with the specified class,
1038
 * assuming that the method (clasp->name).prototype.<name of callee function>
1039
 * is what was called.
1040
 */
1041
extern void
1042
ReportIncompatibleMethod(JSContext* cx, const CallArgs& args, const Class* clasp);
1043
1044
/*
1045
 * Report an error that call.thisv is not an acceptable this for the callee
1046
 * function.
1047
 */
1048
extern void
1049
ReportIncompatible(JSContext* cx, const CallArgs& args);
1050
1051
extern const JSFunctionSpec function_methods[];
1052
extern const JSFunctionSpec function_selfhosted_methods[];
1053
1054
extern bool
1055
fun_apply(JSContext* cx, unsigned argc, Value* vp);
1056
1057
extern bool
1058
fun_call(JSContext* cx, unsigned argc, Value* vp);
1059
1060
} /* namespace js */
1061
1062
#ifdef DEBUG
1063
namespace JS {
1064
namespace detail {
1065
1066
JS_PUBLIC_API(void)
1067
CheckIsValidConstructible(const Value& calleev);
1068
1069
} // namespace detail
1070
} // namespace JS
1071
#endif
1072
1073
#endif /* vm_JSFunction_h */