Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2
* vim: set ts=8 sts=2 et sw=2 tw=80:
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
#include "builtin/Reflect.h"
8
9
#include "builtin/Array.h"
10
11
#include "jit/InlinableNatives.h"
12
#include "js/PropertySpec.h"
13
#include "vm/ArgumentsObject.h"
14
#include "vm/JSContext.h"
15
#include "vm/Stack.h"
16
17
#include "vm/Interpreter-inl.h"
18
19
using namespace js;
20
21
/*** Reflect methods ********************************************************/
22
23
/* ES6 26.1.4 Reflect.deleteProperty (target, propertyKey) */
24
static bool Reflect_deleteProperty(JSContext* cx, unsigned argc, Value* vp) {
25
CallArgs args = CallArgsFromVp(argc, vp);
26
27
// Step 1.
28
RootedObject target(
29
cx,
30
RequireObjectArg(cx, "`target`", "Reflect.deleteProperty", args.get(0)));
31
if (!target) {
32
return false;
33
}
34
35
// Steps 2-3.
36
RootedValue propertyKey(cx, args.get(1));
37
RootedId key(cx);
38
if (!ToPropertyKey(cx, propertyKey, &key)) {
39
return false;
40
}
41
42
// Step 4.
43
ObjectOpResult result;
44
if (!DeleteProperty(cx, target, key, result)) {
45
return false;
46
}
47
args.rval().setBoolean(result.reallyOk());
48
return true;
49
}
50
51
/* ES6 26.1.8 Reflect.getPrototypeOf(target) */
52
bool js::Reflect_getPrototypeOf(JSContext* cx, unsigned argc, Value* vp) {
53
CallArgs args = CallArgsFromVp(argc, vp);
54
55
// Step 1.
56
RootedObject target(
57
cx,
58
RequireObjectArg(cx, "`target`", "Reflect.getPrototypeOf", args.get(0)));
59
if (!target) {
60
return false;
61
}
62
63
// Step 2.
64
RootedObject proto(cx);
65
if (!GetPrototype(cx, target, &proto)) {
66
return false;
67
}
68
args.rval().setObjectOrNull(proto);
69
return true;
70
}
71
72
/* ES6 draft 26.1.10 Reflect.isExtensible(target) */
73
bool js::Reflect_isExtensible(JSContext* cx, unsigned argc, Value* vp) {
74
CallArgs args = CallArgsFromVp(argc, vp);
75
76
// Step 1.
77
RootedObject target(
78
cx,
79
RequireObjectArg(cx, "`target`", "Reflect.isExtensible", args.get(0)));
80
if (!target) {
81
return false;
82
}
83
84
// Step 2.
85
bool extensible;
86
if (!IsExtensible(cx, target, &extensible)) {
87
return false;
88
}
89
args.rval().setBoolean(extensible);
90
return true;
91
}
92
93
// ES2018 draft rev c164be80f7ea91de5526b33d54e5c9321ed03d3f
94
// 26.1.10 Reflect.ownKeys ( target )
95
bool js::Reflect_ownKeys(JSContext* cx, unsigned argc, Value* vp) {
96
CallArgs args = CallArgsFromVp(argc, vp);
97
98
// Step 1.
99
RootedObject target(
100
cx, RequireObjectArg(cx, "`target`", "Reflect.ownKeys", args.get(0)));
101
if (!target) {
102
return false;
103
}
104
105
// Steps 2-3.
106
return GetOwnPropertyKeys(
107
cx, target, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, args.rval());
108
}
109
110
/* ES6 26.1.12 Reflect.preventExtensions(target) */
111
static bool Reflect_preventExtensions(JSContext* cx, unsigned argc, Value* vp) {
112
CallArgs args = CallArgsFromVp(argc, vp);
113
114
// Step 1.
115
RootedObject target(
116
cx, RequireObjectArg(cx, "`target`", "Reflect.preventExtensions",
117
args.get(0)));
118
if (!target) {
119
return false;
120
}
121
122
// Step 2.
123
ObjectOpResult result;
124
if (!PreventExtensions(cx, target, result)) {
125
return false;
126
}
127
args.rval().setBoolean(result.reallyOk());
128
return true;
129
}
130
131
/* ES6 26.1.13 Reflect.set(target, propertyKey, V [, receiver]) */
132
static bool Reflect_set(JSContext* cx, unsigned argc, Value* vp) {
133
CallArgs args = CallArgsFromVp(argc, vp);
134
135
// Step 1.
136
RootedObject target(
137
cx, RequireObjectArg(cx, "`target`", "Reflect.set", args.get(0)));
138
if (!target) {
139
return false;
140
}
141
142
// Steps 2-3.
143
RootedValue propertyKey(cx, args.get(1));
144
RootedId key(cx);
145
if (!ToPropertyKey(cx, propertyKey, &key)) {
146
return false;
147
}
148
149
// Step 4.
150
RootedValue receiver(cx, args.length() > 3 ? args[3] : args.get(0));
151
152
// Step 5.
153
ObjectOpResult result;
154
RootedValue value(cx, args.get(2));
155
if (!SetProperty(cx, target, key, value, receiver, result)) {
156
return false;
157
}
158
args.rval().setBoolean(result.reallyOk());
159
return true;
160
}
161
162
/*
163
* ES6 26.1.3 Reflect.setPrototypeOf(target, proto)
164
*
165
* The specification is not quite similar enough to Object.setPrototypeOf to
166
* share code.
167
*/
168
static bool Reflect_setPrototypeOf(JSContext* cx, unsigned argc, Value* vp) {
169
CallArgs args = CallArgsFromVp(argc, vp);
170
171
// Step 1.
172
RootedObject obj(cx, RequireObjectArg(cx, "`target`",
173
"Reflect.setPrototypeOf", args.get(0)));
174
if (!obj) {
175
return false;
176
}
177
178
// Step 2.
179
if (!args.get(1).isObjectOrNull()) {
180
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
181
JSMSG_NOT_EXPECTED_TYPE, "Reflect.setPrototypeOf",
182
"an object or null",
183
InformalValueTypeName(args.get(1)));
184
return false;
185
}
186
RootedObject proto(cx, args.get(1).toObjectOrNull());
187
188
// Step 4.
189
ObjectOpResult result;
190
if (!SetPrototype(cx, obj, proto, result)) {
191
return false;
192
}
193
args.rval().setBoolean(result.reallyOk());
194
return true;
195
}
196
197
static const JSFunctionSpec methods[] = {
198
JS_SELF_HOSTED_FN("apply", "Reflect_apply", 3, 0),
199
JS_SELF_HOSTED_FN("construct", "Reflect_construct", 2, 0),
200
JS_SELF_HOSTED_FN("defineProperty", "Reflect_defineProperty", 3, 0),
201
JS_FN("deleteProperty", Reflect_deleteProperty, 2, 0),
202
JS_SELF_HOSTED_FN("get", "Reflect_get", 2, 0),
203
JS_SELF_HOSTED_FN("getOwnPropertyDescriptor",
204
"Reflect_getOwnPropertyDescriptor", 2, 0),
205
JS_INLINABLE_FN("getPrototypeOf", Reflect_getPrototypeOf, 1, 0,
206
ReflectGetPrototypeOf),
207
JS_SELF_HOSTED_FN("has", "Reflect_has", 2, 0),
208
JS_FN("isExtensible", Reflect_isExtensible, 1, 0),
209
JS_FN("ownKeys", Reflect_ownKeys, 1, 0),
210
JS_FN("preventExtensions", Reflect_preventExtensions, 1, 0),
211
JS_FN("set", Reflect_set, 3, 0),
212
JS_FN("setPrototypeOf", Reflect_setPrototypeOf, 2, 0),
213
JS_FS_END};
214
215
/*** Setup ******************************************************************/
216
217
JSObject* js::InitReflect(JSContext* cx, Handle<GlobalObject*> global) {
218
RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
219
if (!proto) {
220
return nullptr;
221
}
222
223
RootedObject reflect(
224
cx, NewObjectWithGivenProto<PlainObject>(cx, proto, SingletonObject));
225
if (!reflect) {
226
return nullptr;
227
}
228
if (!JS_DefineFunctions(cx, reflect, methods)) {
229
return nullptr;
230
}
231
232
RootedValue value(cx, ObjectValue(*reflect));
233
if (!DefineDataProperty(cx, global, cx->names().Reflect, value,
234
JSPROP_RESOLVING)) {
235
return nullptr;
236
}
237
238
global->setConstructor(JSProto_Reflect, value);
239
240
return reflect;
241
}