Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7639 views
1
#include "jsi.h"
2
#include "jsvalue.h"
3
#include "jsbuiltin.h"
4
5
static void jsB_new_Object(js_State *J)
6
{
7
if (js_gettop(J) == 1 || js_isundefined(J, 1) || js_isnull(J, 1))
8
js_newobject(J);
9
else
10
js_pushobject(J, js_toobject(J, 1));
11
}
12
13
static void jsB_Object(js_State *J)
14
{
15
if (js_gettop(J) == 1 || js_isundefined(J, 1) || js_isnull(J, 1))
16
js_newobject(J);
17
else
18
js_pushobject(J, js_toobject(J, 1));
19
}
20
21
static void Op_toString(js_State *J)
22
{
23
js_Object *self = js_toobject(J, 0);
24
switch (self->type) {
25
case JS_COBJECT: js_pushliteral(J, "[object Object]"); break;
26
case JS_CARRAY: js_pushliteral(J, "[object Array]"); break;
27
case JS_CFUNCTION: js_pushliteral(J, "[object Function]"); break;
28
case JS_CSCRIPT: js_pushliteral(J, "[object Function]"); break;
29
case JS_CCFUNCTION: js_pushliteral(J, "[object Function]"); break;
30
case JS_CERROR: js_pushliteral(J, "[object Error]"); break;
31
case JS_CBOOLEAN: js_pushliteral(J, "[object Boolean]"); break;
32
case JS_CNUMBER: js_pushliteral(J, "[object Number]"); break;
33
case JS_CSTRING: js_pushliteral(J, "[object String]"); break;
34
case JS_CREGEXP: js_pushliteral(J, "[object RegExp]"); break;
35
case JS_CDATE: js_pushliteral(J, "[object Date]"); break;
36
case JS_CMATH: js_pushliteral(J, "[object Math]"); break;
37
case JS_CJSON: js_pushliteral(J, "[object JSON]"); break;
38
case JS_CITERATOR: js_pushliteral(J, "[Iterator]"); break;
39
case JS_CUSERDATA:
40
js_pushliteral(J, "[object ");
41
js_pushliteral(J, self->u.user.tag);
42
js_concat(J);
43
js_pushliteral(J, "]");
44
js_concat(J);
45
break;
46
}
47
}
48
49
static void Op_valueOf(js_State *J)
50
{
51
js_copy(J, 0);
52
}
53
54
static void Op_hasOwnProperty(js_State *J)
55
{
56
js_Object *self = js_toobject(J, 0);
57
const char *name = js_tostring(J, 1);
58
js_Property *ref = jsV_getownproperty(J, self, name);
59
js_pushboolean(J, ref != NULL);
60
}
61
62
static void Op_isPrototypeOf(js_State *J)
63
{
64
js_Object *self = js_toobject(J, 0);
65
if (js_isobject(J, 1)) {
66
js_Object *V = js_toobject(J, 1);
67
do {
68
V = V->prototype;
69
if (V == self) {
70
js_pushboolean(J, 1);
71
return;
72
}
73
} while (V);
74
}
75
js_pushboolean(J, 0);
76
}
77
78
static void Op_propertyIsEnumerable(js_State *J)
79
{
80
js_Object *self = js_toobject(J, 0);
81
const char *name = js_tostring(J, 1);
82
js_Property *ref = jsV_getownproperty(J, self, name);
83
js_pushboolean(J, ref && !(ref->atts & JS_DONTENUM));
84
}
85
86
static void O_getPrototypeOf(js_State *J)
87
{
88
js_Object *obj;
89
if (!js_isobject(J, 1))
90
js_typeerror(J, "not an object");
91
obj = js_toobject(J, 1);
92
if (obj->prototype)
93
js_pushobject(J, obj->prototype);
94
else
95
js_pushnull(J);
96
}
97
98
static void O_getOwnPropertyDescriptor(js_State *J)
99
{
100
js_Object *obj;
101
js_Property *ref;
102
if (!js_isobject(J, 1))
103
js_typeerror(J, "not an object");
104
obj = js_toobject(J, 1);
105
ref = jsV_getproperty(J, obj, js_tostring(J, 2));
106
if (!ref)
107
js_pushundefined(J);
108
else {
109
js_newobject(J);
110
if (!ref->getter && !ref->setter) {
111
js_pushvalue(J, ref->value);
112
js_setproperty(J, -2, "value");
113
js_pushboolean(J, !(ref->atts & JS_READONLY));
114
js_setproperty(J, -2, "writable");
115
} else {
116
if (ref->getter)
117
js_pushobject(J, ref->getter);
118
else
119
js_pushundefined(J);
120
js_setproperty(J, -2, "get");
121
if (ref->setter)
122
js_pushobject(J, ref->setter);
123
else
124
js_pushundefined(J);
125
js_setproperty(J, -2, "set");
126
}
127
js_pushboolean(J, !(ref->atts & JS_DONTENUM));
128
js_setproperty(J, -2, "enumerable");
129
js_pushboolean(J, !(ref->atts & JS_DONTCONF));
130
js_setproperty(J, -2, "configurable");
131
}
132
}
133
134
static void O_getOwnPropertyNames(js_State *J)
135
{
136
js_Object *obj;
137
js_Property *ref;
138
unsigned int k;
139
int i;
140
141
if (!js_isobject(J, 1))
142
js_typeerror(J, "not an object");
143
obj = js_toobject(J, 1);
144
145
js_newarray(J);
146
147
i = 0;
148
for (ref = obj->head; ref; ref = ref->next) {
149
js_pushliteral(J, ref->name);
150
js_setindex(J, -2, i++);
151
}
152
153
if (obj->type == JS_CARRAY) {
154
js_pushliteral(J, "length");
155
js_setindex(J, -2, i++);
156
}
157
158
if (obj->type == JS_CSTRING) {
159
js_pushliteral(J, "length");
160
js_setindex(J, -2, i++);
161
for (k = 0; k < obj->u.s.length; ++k) {
162
js_pushnumber(J, k);
163
js_setindex(J, -2, i++);
164
}
165
}
166
167
if (obj->type == JS_CREGEXP) {
168
js_pushliteral(J, "source");
169
js_setindex(J, -2, i++);
170
js_pushliteral(J, "global");
171
js_setindex(J, -2, i++);
172
js_pushliteral(J, "ignoreCase");
173
js_setindex(J, -2, i++);
174
js_pushliteral(J, "multiline");
175
js_setindex(J, -2, i++);
176
js_pushliteral(J, "lastIndex");
177
js_setindex(J, -2, i++);
178
}
179
}
180
181
static void ToPropertyDescriptor(js_State *J, js_Object *obj, const char *name, js_Object *desc)
182
{
183
int haswritable = 0;
184
int hasvalue = 0;
185
int enumerable = 0;
186
int configurable = 0;
187
int writable = 0;
188
int atts = 0;
189
190
js_pushobject(J, obj);
191
js_pushobject(J, desc);
192
193
if (js_hasproperty(J, -1, "writable")) {
194
haswritable = 1;
195
writable = js_toboolean(J, -1);
196
js_pop(J, 1);
197
}
198
if (js_hasproperty(J, -1, "enumerable")) {
199
enumerable = js_toboolean(J, -1);
200
js_pop(J, 1);
201
}
202
if (js_hasproperty(J, -1, "configurable")) {
203
configurable = js_toboolean(J, -1);
204
js_pop(J, 1);
205
}
206
if (js_hasproperty(J, -1, "value")) {
207
hasvalue = 1;
208
js_setproperty(J, -3, name);
209
}
210
211
if (!writable) atts |= JS_READONLY;
212
if (!enumerable) atts |= JS_DONTENUM;
213
if (!configurable) atts |= JS_DONTCONF;
214
215
if (js_hasproperty(J, -1, "get")) {
216
if (haswritable || hasvalue)
217
js_typeerror(J, "value/writable and get/set attributes are exclusive");
218
} else {
219
js_pushundefined(J);
220
}
221
222
if (js_hasproperty(J, -2, "set")) {
223
if (haswritable || hasvalue)
224
js_typeerror(J, "value/writable and get/set attributes are exclusive");
225
} else {
226
js_pushundefined(J);
227
}
228
229
js_defaccessor(J, -4, name, atts);
230
231
js_pop(J, 2);
232
}
233
234
static void O_defineProperty(js_State *J)
235
{
236
if (!js_isobject(J, 1)) js_typeerror(J, "not an object");
237
if (!js_isobject(J, 3)) js_typeerror(J, "not an object");
238
ToPropertyDescriptor(J, js_toobject(J, 1), js_tostring(J, 2), js_toobject(J, 3));
239
js_copy(J, 1);
240
}
241
242
static void O_defineProperties(js_State *J)
243
{
244
js_Object *props;
245
js_Property *ref;
246
247
if (!js_isobject(J, 1)) js_typeerror(J, "not an object");
248
if (!js_isobject(J, 2)) js_typeerror(J, "not an object");
249
250
props = js_toobject(J, 2);
251
for (ref = props->head; ref; ref = ref->next) {
252
if (!(ref->atts & JS_DONTENUM)) {
253
js_pushvalue(J, ref->value);
254
ToPropertyDescriptor(J, js_toobject(J, 1), ref->name, js_toobject(J, -1));
255
js_pop(J, 1);
256
}
257
}
258
259
js_copy(J, 1);
260
}
261
262
static void O_create(js_State *J)
263
{
264
js_Object *obj;
265
js_Object *proto;
266
js_Object *props;
267
js_Property *ref;
268
269
if (js_isobject(J, 1))
270
proto = js_toobject(J, 1);
271
else if (js_isnull(J, 1))
272
proto = NULL;
273
else
274
js_typeerror(J, "not an object or null");
275
276
obj = jsV_newobject(J, JS_COBJECT, proto);
277
js_pushobject(J, obj);
278
279
if (js_isdefined(J, 2)) {
280
if (!js_isobject(J, 2)) js_typeerror(J, "not an object");
281
props = js_toobject(J, 2);
282
for (ref = props->head; ref; ref = ref->next) {
283
if (!(ref->atts & JS_DONTENUM)) {
284
if (ref->value.type != JS_TOBJECT) js_typeerror(J, "not an object");
285
ToPropertyDescriptor(J, obj, ref->name, ref->value.u.object);
286
}
287
}
288
}
289
}
290
291
static void O_keys(js_State *J)
292
{
293
js_Object *obj;
294
js_Property *ref;
295
unsigned int k;
296
int i;
297
298
if (!js_isobject(J, 1))
299
js_typeerror(J, "not an object");
300
obj = js_toobject(J, 1);
301
302
js_newarray(J);
303
304
i = 0;
305
for (ref = obj->head; ref; ref = ref->next) {
306
if (!(ref->atts & JS_DONTENUM)) {
307
js_pushliteral(J, ref->name);
308
js_setindex(J, -2, i++);
309
}
310
}
311
312
if (obj->type == JS_CSTRING) {
313
for (k = 0; k < obj->u.s.length; ++k) {
314
js_pushnumber(J, k);
315
js_setindex(J, -2, i++);
316
}
317
}
318
}
319
320
static void O_preventExtensions(js_State *J)
321
{
322
if (!js_isobject(J, 1))
323
js_typeerror(J, "not an object");
324
js_toobject(J, 1)->extensible = 0;
325
js_copy(J, 1);
326
}
327
328
static void O_isExtensible(js_State *J)
329
{
330
if (!js_isobject(J, 1))
331
js_typeerror(J, "not an object");
332
js_pushboolean(J, js_toobject(J, 1)->extensible);
333
}
334
335
static void O_seal(js_State *J)
336
{
337
js_Object *obj;
338
js_Property *ref;
339
340
if (!js_isobject(J, 1))
341
js_typeerror(J, "not an object");
342
343
obj = js_toobject(J, 1);
344
obj->extensible = 0;
345
346
for (ref = obj->head; ref; ref = ref->next)
347
ref->atts |= JS_DONTCONF;
348
349
js_copy(J, 1);
350
}
351
352
static void O_isSealed(js_State *J)
353
{
354
js_Object *obj;
355
js_Property *ref;
356
357
if (!js_isobject(J, 1))
358
js_typeerror(J, "not an object");
359
360
obj = js_toobject(J, 1);
361
if (obj->extensible) {
362
js_pushboolean(J, 0);
363
return;
364
}
365
366
for (ref = obj->head; ref; ref = ref->next) {
367
if (!(ref->atts & JS_DONTCONF)) {
368
js_pushboolean(J, 0);
369
return;
370
}
371
}
372
373
js_pushboolean(J, 1);
374
}
375
376
static void O_freeze(js_State *J)
377
{
378
js_Object *obj;
379
js_Property *ref;
380
381
if (!js_isobject(J, 1))
382
js_typeerror(J, "not an object");
383
384
obj = js_toobject(J, 1);
385
obj->extensible = 0;
386
387
for (ref = obj->head; ref; ref = ref->next)
388
ref->atts |= JS_READONLY | JS_DONTCONF;
389
390
js_copy(J, 1);
391
}
392
393
static void O_isFrozen(js_State *J)
394
{
395
js_Object *obj;
396
js_Property *ref;
397
398
if (!js_isobject(J, 1))
399
js_typeerror(J, "not an object");
400
401
obj = js_toobject(J, 1);
402
if (obj->extensible) {
403
js_pushboolean(J, 0);
404
return;
405
}
406
407
for (ref = obj->head; ref; ref = ref->next) {
408
if (!(ref->atts & (JS_READONLY | JS_DONTCONF))) {
409
js_pushboolean(J, 0);
410
return;
411
}
412
}
413
414
js_pushboolean(J, 1);
415
}
416
417
void jsB_initobject(js_State *J)
418
{
419
js_pushobject(J, J->Object_prototype);
420
{
421
jsB_propf(J, "toString", Op_toString, 0);
422
jsB_propf(J, "toLocaleString", Op_toString, 0);
423
jsB_propf(J, "valueOf", Op_valueOf, 0);
424
jsB_propf(J, "hasOwnProperty", Op_hasOwnProperty, 1);
425
jsB_propf(J, "isPrototypeOf", Op_isPrototypeOf, 1);
426
jsB_propf(J, "propertyIsEnumerable", Op_propertyIsEnumerable, 1);
427
}
428
js_newcconstructor(J, jsB_Object, jsB_new_Object, "Object", 1);
429
{
430
/* ES5 */
431
jsB_propf(J, "getPrototypeOf", O_getPrototypeOf, 1);
432
jsB_propf(J, "getOwnPropertyDescriptor", O_getOwnPropertyDescriptor, 2);
433
jsB_propf(J, "getOwnPropertyNames", O_getOwnPropertyNames, 1);
434
jsB_propf(J, "create", O_create, 2);
435
jsB_propf(J, "defineProperty", O_defineProperty, 3);
436
jsB_propf(J, "defineProperties", O_defineProperties, 2);
437
jsB_propf(J, "seal", O_seal, 1);
438
jsB_propf(J, "freeze", O_freeze, 1);
439
jsB_propf(J, "preventExtensions", O_preventExtensions, 1);
440
jsB_propf(J, "isSealed", O_isSealed, 1);
441
jsB_propf(J, "isFrozen", O_isFrozen, 1);
442
jsB_propf(J, "isExtensible", O_isExtensible, 1);
443
jsB_propf(J, "keys", O_keys, 1);
444
}
445
js_defglobal(J, "Object", JS_DONTENUM);
446
}
447
448