summaryrefslogtreecommitdiffstats
path: root/js/public/CallAndConstruct.h
blob: cd3007cbb901ee813a72517277e9a66e803d9465 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* Call and construct API. */

#ifndef js_CallAndConstruct_h
#define js_CallAndConstruct_h

#include "mozilla/Assertions.h"  // MOZ_ASSERT

#include "jstypes.h"  // JS_PUBLIC_API

#include "js/RootingAPI.h"  // JS::Handle, JS::MutableHandle
#include "js/Value.h"       // JS::Value, JS::ObjectValue
#include "js/ValueArray.h"  // JS::HandleValueArray

struct JSContext;
class JSObject;
class JSFunction;

/*
 * API for determining callability and constructability. [[Call]] and
 * [[Construct]] are internal methods that aren't present on all objects, so it
 * is useful to ask if they are there or not. The standard itself asks these
 * questions routinely.
 */
namespace JS {

/**
 * Return true if the given object is callable. In ES6 terms, an object is
 * callable if it has a [[Call]] internal method.
 *
 * Implements: ES6 7.2.3 IsCallable(argument).
 *
 * Functions are callable. A scripted proxy or wrapper is callable if its
 * target is callable. Most other objects aren't callable.
 */
extern JS_PUBLIC_API bool IsCallable(JSObject* obj);

/**
 * Return true if the given object is a constructor. In ES6 terms, an object is
 * a constructor if it has a [[Construct]] internal method. The expression
 * `new obj()` throws a TypeError if obj is not a constructor.
 *
 * Implements: ES6 7.2.4 IsConstructor(argument).
 *
 * JS functions and classes are constructors. Arrow functions and most builtin
 * functions are not. A scripted proxy or wrapper is a constructor if its
 * target is a constructor.
 */
extern JS_PUBLIC_API bool IsConstructor(JSObject* obj);

} /* namespace JS */

/**
 * Call a function, passing a this-value and arguments. This is the C++
 * equivalent of `rval = Reflect.apply(fun, obj, args)`.
 *
 * Implements: ES6 7.3.12 Call(F, V, [argumentsList]).
 * Use this function to invoke the [[Call]] internal method.
 */
extern JS_PUBLIC_API bool JS_CallFunctionValue(
    JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<JS::Value> fval,
    const JS::HandleValueArray& args, JS::MutableHandle<JS::Value> rval);

extern JS_PUBLIC_API bool JS_CallFunction(JSContext* cx,
                                          JS::Handle<JSObject*> obj,
                                          JS::Handle<JSFunction*> fun,
                                          const JS::HandleValueArray& args,
                                          JS::MutableHandle<JS::Value> rval);

/**
 * Perform the method call `rval = obj[name](args)`.
 */
extern JS_PUBLIC_API bool JS_CallFunctionName(
    JSContext* cx, JS::Handle<JSObject*> obj, const char* name,
    const JS::HandleValueArray& args, JS::MutableHandle<JS::Value> rval);

namespace JS {

static inline bool Call(JSContext* cx, Handle<JSObject*> thisObj,
                        Handle<JSFunction*> fun, const HandleValueArray& args,
                        MutableHandle<Value> rval) {
  return !!JS_CallFunction(cx, thisObj, fun, args, rval);
}

static inline bool Call(JSContext* cx, Handle<JSObject*> thisObj,
                        Handle<Value> fun, const HandleValueArray& args,
                        MutableHandle<Value> rval) {
  return !!JS_CallFunctionValue(cx, thisObj, fun, args, rval);
}

static inline bool Call(JSContext* cx, Handle<JSObject*> thisObj,
                        const char* name, const HandleValueArray& args,
                        MutableHandle<Value> rval) {
  return !!JS_CallFunctionName(cx, thisObj, name, args, rval);
}

extern JS_PUBLIC_API bool Call(JSContext* cx, Handle<Value> thisv,
                               Handle<Value> fun, const HandleValueArray& args,
                               MutableHandle<Value> rval);

static inline bool Call(JSContext* cx, Handle<Value> thisv,
                        Handle<JSObject*> funObj, const HandleValueArray& args,
                        MutableHandle<Value> rval) {
  MOZ_ASSERT(funObj);
  Rooted<Value> fun(cx, ObjectValue(*funObj));
  return Call(cx, thisv, fun, args, rval);
}

/**
 * Invoke a constructor. This is the C++ equivalent of
 * `rval = Reflect.construct(fun, args, newTarget)`.
 *
 * Construct() takes a `newTarget` argument that most callers don't need.
 * Consider using the four-argument Construct signature instead. (But if you're
 * implementing a subclass or a proxy handler's construct() method, this is the
 * right function to call.)
 *
 * Implements: ES6 7.3.13 Construct(F, [argumentsList], [newTarget]).
 * Use this function to invoke the [[Construct]] internal method.
 */
extern JS_PUBLIC_API bool Construct(JSContext* cx, Handle<Value> fun,
                                    Handle<JSObject*> newTarget,
                                    const HandleValueArray& args,
                                    MutableHandle<JSObject*> objp);

/**
 * Invoke a constructor. This is the C++ equivalent of
 * `rval = new fun(...args)`.
 *
 * Implements: ES6 7.3.13 Construct(F, [argumentsList], [newTarget]), when
 * newTarget is omitted.
 */
extern JS_PUBLIC_API bool Construct(JSContext* cx, Handle<Value> fun,
                                    const HandleValueArray& args,
                                    MutableHandle<JSObject*> objp);

} /* namespace JS */

#endif /* js_CallAndConstruct_h */