1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 *
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * The Original Code is Mozilla Communicator client code, released
17 * March 31, 1998.
18 *
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1998
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
37 *
38 * ***** END LICENSE BLOCK ***** */
39
40 /*
41 * JavaScript API.
42 */
43 #include "jsstddef.h"
44 #include <ctype.h>
45 #include <stdarg.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include "jstypes.h"
49 #include "jsarena.h" /* Added by JSIFY */
50 #include "jsutil.h" /* Added by JSIFY */
51 #include "jsclist.h"
52 #include "jsdhash.h"
53 #include "jsprf.h"
54 #include "jsapi.h"
55 #include "jsarray.h"
56 #include "jsatom.h"
57 #include "jsbool.h"
58 #include "jscntxt.h"
59 #include "jsconfig.h"
60 #include "jsdate.h"
61 #include "jsdtoa.h"
62 #include "jsemit.h"
63 #include "jsexn.h"
64 #include "jsfun.h"
65 #include "jsgc.h"
66 #include "jsinterp.h"
67 #include "jslock.h"
68 #include "jsmath.h"
69 #include "jsnum.h"
70 #include "jsobj.h"
71 #include "jsopcode.h"
72 #include "jsparse.h"
73 #include "jsregexp.h"
74 #include "jsscan.h"
75 #include "jsscope.h"
76 #include "jsscript.h"
77 #include "jsstr.h"
78 #include "prmjtime.h"
79
80 #if JS_HAS_FILE_OBJECT
81 #include "jsfile.h"
82 #endif
83
84 #ifdef HAVE_VA_LIST_AS_ARRAY
85 #define JS_ADDRESSOF_VA_LIST(ap) (ap)
86 #else
87 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
88 #endif
89
90 #if defined(JS_PARANOID_REQUEST) && defined(JS_THREADSAFE)
91 #define CHECK_REQUEST(cx) JS_ASSERT(cx->requestDepth)
92 #else
93 #define CHECK_REQUEST(cx) ((void)0)
94 #endif
95
96 JS_PUBLIC_API(int64)
JS_Now()97 JS_Now()
98 {
99 return PRMJ_Now();
100 }
101
102 JS_PUBLIC_API(jsval)
JS_GetNaNValue(JSContext * cx)103 JS_GetNaNValue(JSContext *cx)
104 {
105 return DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
106 }
107
108 JS_PUBLIC_API(jsval)
JS_GetNegativeInfinityValue(JSContext * cx)109 JS_GetNegativeInfinityValue(JSContext *cx)
110 {
111 return DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
112 }
113
114 JS_PUBLIC_API(jsval)
JS_GetPositiveInfinityValue(JSContext * cx)115 JS_GetPositiveInfinityValue(JSContext *cx)
116 {
117 return DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
118 }
119
120 JS_PUBLIC_API(jsval)
JS_GetEmptyStringValue(JSContext * cx)121 JS_GetEmptyStringValue(JSContext *cx)
122 {
123 return STRING_TO_JSVAL(cx->runtime->emptyString);
124 }
125
126 static JSBool
TryArgumentFormatter(JSContext * cx,const char ** formatp,JSBool fromJS,jsval ** vpp,va_list * app)127 TryArgumentFormatter(JSContext *cx, const char **formatp, JSBool fromJS,
128 jsval **vpp, va_list *app)
129 {
130 const char *format;
131 JSArgumentFormatMap *map;
132
133 format = *formatp;
134 for (map = cx->argumentFormatMap; map; map = map->next) {
135 if (!strncmp(format, map->format, map->length)) {
136 *formatp = format + map->length;
137 return map->formatter(cx, format, fromJS, vpp, app);
138 }
139 }
140 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR, format);
141 return JS_FALSE;
142 }
143
144 JS_PUBLIC_API(JSBool)
JS_ConvertArguments(JSContext * cx,uintN argc,jsval * argv,const char * format,...)145 JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
146 ...)
147 {
148 va_list ap;
149 JSBool ok;
150
151 va_start(ap, format);
152 ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap);
153 va_end(ap);
154 return ok;
155 }
156
157 JS_PUBLIC_API(JSBool)
JS_ConvertArgumentsVA(JSContext * cx,uintN argc,jsval * argv,const char * format,va_list ap)158 JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
159 const char *format, va_list ap)
160 {
161 jsval *sp;
162 JSBool required;
163 char c;
164 JSFunction *fun;
165 jsdouble d;
166 JSString *str;
167 JSObject *obj;
168
169 CHECK_REQUEST(cx);
170 sp = argv;
171 required = JS_TRUE;
172 while ((c = *format++) != '\0') {
173 if (isspace(c))
174 continue;
175 if (c == '/') {
176 required = JS_FALSE;
177 continue;
178 }
179 if (sp == argv + argc) {
180 if (required) {
181 fun = js_ValueToFunction(cx, &argv[-2], 0);
182 if (fun) {
183 char numBuf[12];
184 JS_snprintf(numBuf, sizeof numBuf, "%u", argc);
185 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
186 JSMSG_MORE_ARGS_NEEDED,
187 JS_GetFunctionName(fun), numBuf,
188 (argc == 1) ? "" : "s");
189 }
190 return JS_FALSE;
191 }
192 break;
193 }
194 switch (c) {
195 case 'b':
196 if (!js_ValueToBoolean(cx, *sp, va_arg(ap, JSBool *)))
197 return JS_FALSE;
198 break;
199 case 'c':
200 if (!js_ValueToUint16(cx, *sp, va_arg(ap, uint16 *)))
201 return JS_FALSE;
202 break;
203 case 'i':
204 if (!js_ValueToECMAInt32(cx, *sp, va_arg(ap, int32 *)))
205 return JS_FALSE;
206 break;
207 case 'u':
208 if (!js_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32 *)))
209 return JS_FALSE;
210 break;
211 case 'j':
212 if (!js_ValueToInt32(cx, *sp, va_arg(ap, int32 *)))
213 return JS_FALSE;
214 break;
215 case 'd':
216 if (!js_ValueToNumber(cx, *sp, va_arg(ap, jsdouble *)))
217 return JS_FALSE;
218 break;
219 case 'I':
220 if (!js_ValueToNumber(cx, *sp, &d))
221 return JS_FALSE;
222 *va_arg(ap, jsdouble *) = js_DoubleToInteger(d);
223 break;
224 case 's':
225 case 'S':
226 case 'W':
227 str = js_ValueToString(cx, *sp);
228 if (!str)
229 return JS_FALSE;
230 *sp = STRING_TO_JSVAL(str);
231 if (c == 's')
232 *va_arg(ap, char **) = JS_GetStringBytes(str);
233 else if (c == 'W')
234 *va_arg(ap, jschar **) = JS_GetStringChars(str);
235 else
236 *va_arg(ap, JSString **) = str;
237 break;
238 case 'o':
239 if (!js_ValueToObject(cx, *sp, &obj))
240 return JS_FALSE;
241 *sp = OBJECT_TO_JSVAL(obj);
242 *va_arg(ap, JSObject **) = obj;
243 break;
244 case 'f':
245 /*
246 * Don't convert a cloned function object to its shared private
247 * data, then follow fun->object back to the clone-parent.
248 */
249 if (JSVAL_IS_FUNCTION(cx, *sp)) {
250 fun = (JSFunction *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(*sp));
251 } else {
252 fun = js_ValueToFunction(cx, sp, 0);
253 if (!fun)
254 return JS_FALSE;
255 *sp = OBJECT_TO_JSVAL(fun->object);
256 }
257 *va_arg(ap, JSFunction **) = fun;
258 break;
259 case 'v':
260 *va_arg(ap, jsval *) = *sp;
261 break;
262 case '*':
263 break;
264 default:
265 format--;
266 if (!TryArgumentFormatter(cx, &format, JS_TRUE, &sp,
267 JS_ADDRESSOF_VA_LIST(ap))) {
268 return JS_FALSE;
269 }
270 /* NB: the formatter already updated sp, so we continue here. */
271 continue;
272 }
273 sp++;
274 }
275 return JS_TRUE;
276 }
277
278 JS_PUBLIC_API(jsval *)
JS_PushArguments(JSContext * cx,void ** markp,const char * format,...)279 JS_PushArguments(JSContext *cx, void **markp, const char *format, ...)
280 {
281 va_list ap;
282 jsval *argv;
283
284 va_start(ap, format);
285 argv = JS_PushArgumentsVA(cx, markp, format, ap);
286 va_end(ap);
287 return argv;
288 }
289
290 JS_PUBLIC_API(jsval *)
JS_PushArgumentsVA(JSContext * cx,void ** markp,const char * format,va_list ap)291 JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
292 {
293 uintN argc;
294 jsval *argv, *sp;
295 char c;
296 const char *cp;
297 JSString *str;
298 JSFunction *fun;
299 JSStackHeader *sh;
300
301 CHECK_REQUEST(cx);
302 *markp = NULL;
303 argc = 0;
304 for (cp = format; (c = *cp) != '\0'; cp++) {
305 /*
306 * Count non-space non-star characters as individual jsval arguments.
307 * This may over-allocate stack, but we'll fix below.
308 */
309 if (isspace(c) || c == '*')
310 continue;
311 argc++;
312 }
313 sp = js_AllocStack(cx, argc, markp);
314 if (!sp)
315 return NULL;
316 argv = sp;
317 while ((c = *format++) != '\0') {
318 if (isspace(c) || c == '*')
319 continue;
320 switch (c) {
321 case 'b':
322 *sp = BOOLEAN_TO_JSVAL((JSBool) va_arg(ap, int));
323 break;
324 case 'c':
325 *sp = INT_TO_JSVAL((uint16) va_arg(ap, unsigned int));
326 break;
327 case 'i':
328 case 'j':
329 if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, int32), sp))
330 goto bad;
331 break;
332 case 'u':
333 if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, uint32), sp))
334 goto bad;
335 break;
336 case 'd':
337 case 'I':
338 if (!js_NewDoubleValue(cx, va_arg(ap, jsdouble), sp))
339 goto bad;
340 break;
341 case 's':
342 str = JS_NewStringCopyZ(cx, va_arg(ap, char *));
343 if (!str)
344 goto bad;
345 *sp = STRING_TO_JSVAL(str);
346 break;
347 case 'W':
348 str = JS_NewUCStringCopyZ(cx, va_arg(ap, jschar *));
349 if (!str)
350 goto bad;
351 *sp = STRING_TO_JSVAL(str);
352 break;
353 case 'S':
354 str = va_arg(ap, JSString *);
355 *sp = STRING_TO_JSVAL(str);
356 break;
357 case 'o':
358 *sp = OBJECT_TO_JSVAL(va_arg(ap, JSObject *));
359 break;
360 case 'f':
361 fun = va_arg(ap, JSFunction *);
362 *sp = fun ? OBJECT_TO_JSVAL(fun->object) : JSVAL_NULL;
363 break;
364 case 'v':
365 *sp = va_arg(ap, jsval);
366 break;
367 default:
368 format--;
369 if (!TryArgumentFormatter(cx, &format, JS_FALSE, &sp,
370 JS_ADDRESSOF_VA_LIST(ap))) {
371 goto bad;
372 }
373 /* NB: the formatter already updated sp, so we continue here. */
374 continue;
375 }
376 sp++;
377 }
378
379 /*
380 * We may have overallocated stack due to a multi-character format code
381 * handled by a JSArgumentFormatter. Give back that stack space!
382 */
383 JS_ASSERT(sp <= argv + argc);
384 if (sp < argv + argc) {
385 /* Return slots not pushed to the current stack arena. */
386 cx->stackPool.current->avail = (jsuword)sp;
387
388 /* Reduce the count of slots the GC will scan in this stack segment. */
389 sh = cx->stackHeaders;
390 JS_ASSERT(JS_STACK_SEGMENT(sh) + sh->nslots == argv + argc);
391 sh->nslots -= argc - (sp - argv);
392 }
393 return argv;
394
395 bad:
396 js_FreeStack(cx, *markp);
397 return NULL;
398 }
399
400 JS_PUBLIC_API(void)
JS_PopArguments(JSContext * cx,void * mark)401 JS_PopArguments(JSContext *cx, void *mark)
402 {
403 CHECK_REQUEST(cx);
404 js_FreeStack(cx, mark);
405 }
406
407 JS_PUBLIC_API(JSBool)
JS_AddArgumentFormatter(JSContext * cx,const char * format,JSArgumentFormatter formatter)408 JS_AddArgumentFormatter(JSContext *cx, const char *format,
409 JSArgumentFormatter formatter)
410 {
411 size_t length;
412 JSArgumentFormatMap **mpp, *map;
413
414 length = strlen(format);
415 mpp = &cx->argumentFormatMap;
416 while ((map = *mpp) != NULL) {
417 /* Insert before any shorter string to match before prefixes. */
418 if (map->length < length)
419 break;
420 if (map->length == length && !strcmp(map->format, format))
421 goto out;
422 mpp = &map->next;
423 }
424 map = (JSArgumentFormatMap *) JS_malloc(cx, sizeof *map);
425 if (!map)
426 return JS_FALSE;
427 map->format = format;
428 map->length = length;
429 map->next = *mpp;
430 *mpp = map;
431 out:
432 map->formatter = formatter;
433 return JS_TRUE;
434 }
435
436 JS_PUBLIC_API(void)
JS_RemoveArgumentFormatter(JSContext * cx,const char * format)437 JS_RemoveArgumentFormatter(JSContext *cx, const char *format)
438 {
439 size_t length;
440 JSArgumentFormatMap **mpp, *map;
441
442 length = strlen(format);
443 mpp = &cx->argumentFormatMap;
444 while ((map = *mpp) != NULL) {
445 if (map->length == length && !strcmp(map->format, format)) {
446 *mpp = map->next;
447 JS_free(cx, map);
448 return;
449 }
450 mpp = &map->next;
451 }
452 }
453
454 JS_PUBLIC_API(JSBool)
JS_ConvertValue(JSContext * cx,jsval v,JSType type,jsval * vp)455 JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
456 {
457 JSBool ok, b;
458 JSObject *obj;
459 JSFunction *fun;
460 JSString *str;
461 jsdouble d, *dp;
462
463 CHECK_REQUEST(cx);
464 switch (type) {
465 case JSTYPE_VOID:
466 *vp = JSVAL_VOID;
467 ok = JS_TRUE;
468 break;
469 case JSTYPE_OBJECT:
470 ok = js_ValueToObject(cx, v, &obj);
471 if (ok)
472 *vp = OBJECT_TO_JSVAL(obj);
473 break;
474 case JSTYPE_FUNCTION:
475 /*
476 * Don't convert a cloned function object to its shared private data,
477 * then follow fun->object back to the clone-parent.
478 */
479 if (JSVAL_IS_FUNCTION(cx, v)) {
480 ok = JS_TRUE;
481 *vp = v;
482 } else {
483 fun = js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
484 ok = (fun != NULL);
485 if (ok)
486 *vp = OBJECT_TO_JSVAL(fun->object);
487 }
488 break;
489 case JSTYPE_STRING:
490 str = js_ValueToString(cx, v);
491 ok = (str != NULL);
492 if (ok)
493 *vp = STRING_TO_JSVAL(str);
494 break;
495 case JSTYPE_NUMBER:
496 ok = js_ValueToNumber(cx, v, &d);
497 if (ok) {
498 dp = js_NewDouble(cx, d);
499 ok = (dp != NULL);
500 if (ok)
501 *vp = DOUBLE_TO_JSVAL(dp);
502 }
503 break;
504 case JSTYPE_BOOLEAN:
505 ok = js_ValueToBoolean(cx, v, &b);
506 if (ok)
507 *vp = BOOLEAN_TO_JSVAL(b);
508 break;
509 default: {
510 char numBuf[12];
511 JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
512 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE,
513 numBuf);
514 ok = JS_FALSE;
515 break;
516 }
517 }
518 return ok;
519 }
520
521 JS_PUBLIC_API(JSBool)
JS_ValueToObject(JSContext * cx,jsval v,JSObject ** objp)522 JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
523 {
524 CHECK_REQUEST(cx);
525 return js_ValueToObject(cx, v, objp);
526 }
527
528 JS_PUBLIC_API(JSFunction *)
JS_ValueToFunction(JSContext * cx,jsval v)529 JS_ValueToFunction(JSContext *cx, jsval v)
530 {
531 CHECK_REQUEST(cx);
532 return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
533 }
534
535 JS_PUBLIC_API(JSFunction *)
JS_ValueToConstructor(JSContext * cx,jsval v)536 JS_ValueToConstructor(JSContext *cx, jsval v)
537 {
538 CHECK_REQUEST(cx);
539 return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
540 }
541
542 JS_PUBLIC_API(JSString *)
JS_ValueToString(JSContext * cx,jsval v)543 JS_ValueToString(JSContext *cx, jsval v)
544 {
545 CHECK_REQUEST(cx);
546 return js_ValueToString(cx, v);
547 }
548
549 JS_PUBLIC_API(JSBool)
JS_ValueToNumber(JSContext * cx,jsval v,jsdouble * dp)550 JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
551 {
552 CHECK_REQUEST(cx);
553 return js_ValueToNumber(cx, v, dp);
554 }
555
556 JS_PUBLIC_API(JSBool)
JS_ValueToECMAInt32(JSContext * cx,jsval v,int32 * ip)557 JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip)
558 {
559 CHECK_REQUEST(cx);
560 return js_ValueToECMAInt32(cx, v, ip);
561 }
562
563 JS_PUBLIC_API(JSBool)
JS_ValueToECMAUint32(JSContext * cx,jsval v,uint32 * ip)564 JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip)
565 {
566 CHECK_REQUEST(cx);
567 return js_ValueToECMAUint32(cx, v, ip);
568 }
569
570 JS_PUBLIC_API(JSBool)
JS_ValueToInt32(JSContext * cx,jsval v,int32 * ip)571 JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip)
572 {
573 CHECK_REQUEST(cx);
574 return js_ValueToInt32(cx, v, ip);
575 }
576
577 JS_PUBLIC_API(JSBool)
JS_ValueToUint16(JSContext * cx,jsval v,uint16 * ip)578 JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip)
579 {
580 CHECK_REQUEST(cx);
581 return js_ValueToUint16(cx, v, ip);
582 }
583
584 JS_PUBLIC_API(JSBool)
JS_ValueToBoolean(JSContext * cx,jsval v,JSBool * bp)585 JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp)
586 {
587 CHECK_REQUEST(cx);
588 return js_ValueToBoolean(cx, v, bp);
589 }
590
591 JS_PUBLIC_API(JSType)
JS_TypeOfValue(JSContext * cx,jsval v)592 JS_TypeOfValue(JSContext *cx, jsval v)
593 {
594 JSType type;
595 JSObject *obj;
596 JSObjectOps *ops;
597 JSClass *clasp;
598
599 CHECK_REQUEST(cx);
600 if (JSVAL_IS_OBJECT(v)) {
601 /* XXX JSVAL_IS_OBJECT(v) is true for null too! Can we change ECMA? */
602 obj = JSVAL_TO_OBJECT(v);
603 if (obj &&
604 (ops = obj->map->ops,
605 ops == &js_ObjectOps
606 ? (clasp = OBJ_GET_CLASS(cx, obj),
607 clasp->call || clasp == &js_FunctionClass)
608 : ops->call != NULL)) {
609 type = JSTYPE_FUNCTION;
610 } else {
611 #ifdef NARCISSUS
612 if (obj) {
613 /* XXX suppress errors/exceptions */
614 OBJ_GET_PROPERTY(cx, obj,
615 (jsid)cx->runtime->atomState.callAtom,
616 &v);
617 if (JSVAL_IS_FUNCTION(cx, v))
618 return JSTYPE_FUNCTION;
619 }
620 #endif
621 type = JSTYPE_OBJECT;
622 }
623 } else if (JSVAL_IS_NUMBER(v)) {
624 type = JSTYPE_NUMBER;
625 } else if (JSVAL_IS_STRING(v)) {
626 type = JSTYPE_STRING;
627 } else if (JSVAL_IS_BOOLEAN(v)) {
628 type = JSTYPE_BOOLEAN;
629 } else {
630 type = JSTYPE_VOID;
631 }
632 return type;
633 }
634
635 JS_PUBLIC_API(const char *)
JS_GetTypeName(JSContext * cx,JSType type)636 JS_GetTypeName(JSContext *cx, JSType type)
637 {
638 if ((uintN)type >= (uintN)JSTYPE_LIMIT)
639 return NULL;
640 return js_type_str[type];
641 }
642
643 /************************************************************************/
644
645 JS_PUBLIC_API(JSRuntime *)
JS_NewRuntime(uint32 maxbytes)646 JS_NewRuntime(uint32 maxbytes)
647 {
648 JSRuntime *rt;
649
650 #ifdef DEBUG
651 JS_BEGIN_MACRO
652 /*
653 * This code asserts that the numbers associated with the error names in
654 * jsmsg.def are monotonically increasing. It uses values for the error
655 * names enumerated in jscntxt.c. It's not a compiletime check, but it's
656 * better than nothing.
657 */
658 int errorNumber = 0;
659 #define MSG_DEF(name, number, count, exception, format) \
660 JS_ASSERT(name == errorNumber++);
661 #include "js.msg"
662 #undef MSG_DEF
663 JS_END_MACRO;
664 #endif /* DEBUG */
665
666 if (!js_InitStringGlobals())
667 return NULL;
668 rt = (JSRuntime *) malloc(sizeof(JSRuntime));
669 if (!rt)
670 return NULL;
671
672 /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
673 memset(rt, 0, sizeof(JSRuntime));
674 JS_INIT_CLIST(&rt->contextList);
675 JS_INIT_CLIST(&rt->trapList);
676 JS_INIT_CLIST(&rt->watchPointList);
677
678 if (!js_InitGC(rt, maxbytes))
679 goto bad;
680 #ifdef JS_THREADSAFE
681 rt->gcLock = JS_NEW_LOCK();
682 if (!rt->gcLock)
683 goto bad;
684 rt->gcDone = JS_NEW_CONDVAR(rt->gcLock);
685 if (!rt->gcDone)
686 goto bad;
687 rt->requestDone = JS_NEW_CONDVAR(rt->gcLock);
688 if (!rt->requestDone)
689 goto bad;
690 js_SetupLocks(8, 16); /* this is asymmetric with JS_ShutDown. */
691 rt->rtLock = JS_NEW_LOCK();
692 if (!rt->rtLock)
693 goto bad;
694 rt->stateChange = JS_NEW_CONDVAR(rt->gcLock);
695 if (!rt->stateChange)
696 goto bad;
697 rt->setSlotLock = JS_NEW_LOCK();
698 if (!rt->setSlotLock)
699 goto bad;
700 rt->setSlotDone = JS_NEW_CONDVAR(rt->setSlotLock);
701 if (!rt->setSlotDone)
702 goto bad;
703 rt->scopeSharingDone = JS_NEW_CONDVAR(rt->gcLock);
704 if (!rt->scopeSharingDone)
705 goto bad;
706 rt->scopeSharingTodo = NO_SCOPE_SHARING_TODO;
707 #endif
708 rt->propertyCache.empty = JS_TRUE;
709 if (!js_InitPropertyTree(rt))
710 goto bad;
711 return rt;
712
713 bad:
714 JS_DestroyRuntime(rt);
715 return NULL;
716 }
717
718 JS_PUBLIC_API(void)
JS_DestroyRuntime(JSRuntime * rt)719 JS_DestroyRuntime(JSRuntime *rt)
720 {
721 #ifdef DEBUG
722 /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
723 if (!JS_CLIST_IS_EMPTY(&rt->contextList)) {
724 JSContext *cx, *iter = NULL;
725 uintN cxcount = 0;
726 while ((cx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL)
727 cxcount++;
728 fprintf(stderr,
729 "JS API usage error: %u contexts left in runtime upon JS_DestroyRuntime.\n",
730 cxcount);
731 }
732 #endif
733
734 js_FinishAtomState(&rt->atomState);
735 js_FinishGC(rt);
736 #ifdef JS_THREADSAFE
737 if (rt->gcLock)
738 JS_DESTROY_LOCK(rt->gcLock);
739 if (rt->gcDone)
740 JS_DESTROY_CONDVAR(rt->gcDone);
741 if (rt->requestDone)
742 JS_DESTROY_CONDVAR(rt->requestDone);
743 if (rt->rtLock)
744 JS_DESTROY_LOCK(rt->rtLock);
745 if (rt->stateChange)
746 JS_DESTROY_CONDVAR(rt->stateChange);
747 if (rt->setSlotLock)
748 JS_DESTROY_LOCK(rt->setSlotLock);
749 if (rt->setSlotDone)
750 JS_DESTROY_CONDVAR(rt->setSlotDone);
751 if (rt->scopeSharingDone)
752 JS_DESTROY_CONDVAR(rt->scopeSharingDone);
753 #endif
754 js_FinishPropertyTree(rt);
755 free(rt);
756 }
757
758 JS_PUBLIC_API(void)
JS_ShutDown(void)759 JS_ShutDown(void)
760 {
761 JS_ArenaShutDown();
762 js_FinishDtoa();
763 js_FreeStringGlobals();
764 #ifdef JS_THREADSAFE
765 js_CleanupLocks();
766 #endif
767 }
768
769 JS_PUBLIC_API(void *)
JS_GetRuntimePrivate(JSRuntime * rt)770 JS_GetRuntimePrivate(JSRuntime *rt)
771 {
772 return rt->data;
773 }
774
775 JS_PUBLIC_API(void)
JS_SetRuntimePrivate(JSRuntime * rt,void * data)776 JS_SetRuntimePrivate(JSRuntime *rt, void *data)
777 {
778 rt->data = data;
779 }
780
781 #ifdef JS_THREADSAFE
782
783 JS_PUBLIC_API(void)
JS_BeginRequest(JSContext * cx)784 JS_BeginRequest(JSContext *cx)
785 {
786 JSRuntime *rt;
787
788 JS_ASSERT(cx->thread);
789 if (!cx->requestDepth) {
790 /* Wait until the GC is finished. */
791 rt = cx->runtime;
792 JS_LOCK_GC(rt);
793
794 /* NB: we use cx->thread here, not js_CurrentThreadId(). */
795 if (rt->gcThread != cx->thread) {
796 while (rt->gcLevel > 0)
797 JS_AWAIT_GC_DONE(rt);
798 }
799
800 /* Indicate that a request is running. */
801 rt->requestCount++;
802 cx->requestDepth = 1;
803 JS_UNLOCK_GC(rt);
804 return;
805 }
806 cx->requestDepth++;
807 }
808
809 JS_PUBLIC_API(void)
JS_EndRequest(JSContext * cx)810 JS_EndRequest(JSContext *cx)
811 {
812 JSRuntime *rt;
813 JSScope *scope, **todop;
814 uintN nshares;
815
816 CHECK_REQUEST(cx);
817 JS_ASSERT(cx->requestDepth > 0);
818 if (cx->requestDepth == 1) {
819 /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
820 rt = cx->runtime;
821 JS_LOCK_GC(rt);
822 cx->requestDepth = 0;
823
824 /* See whether cx has any single-threaded scopes to start sharing. */
825 todop = &rt->scopeSharingTodo;
826 nshares = 0;
827 while ((scope = *todop) != NO_SCOPE_SHARING_TODO) {
828 if (scope->ownercx != cx) {
829 todop = &scope->u.link;
830 continue;
831 }
832 *todop = scope->u.link;
833 scope->u.link = NULL; /* null u.link for sanity ASAP */
834
835 /*
836 * If js_DropObjectMap returns null, we held the last ref to scope.
837 * The waiting thread(s) must have been killed, after which the GC
838 * collected the object that held this scope. Unlikely, because it
839 * requires that the GC ran (e.g., from a branch callback) during
840 * this request, but possible.
841 */
842 if (js_DropObjectMap(cx, &scope->map, NULL)) {
843 js_InitLock(&scope->lock);
844 scope->u.count = 0; /* NULL may not pun as 0 */
845 js_FinishSharingScope(rt, scope); /* set ownercx = NULL */
846 nshares++;
847 }
848 }
849 if (nshares)
850 JS_NOTIFY_ALL_CONDVAR(rt->scopeSharingDone);
851
852 /* Give the GC a chance to run if this was the last request running. */
853 JS_ASSERT(rt->requestCount > 0);
854 rt->requestCount--;
855 if (rt->requestCount == 0)
856 JS_NOTIFY_REQUEST_DONE(rt);
857
858 JS_UNLOCK_GC(rt);
859 return;
860 }
861
862 cx->requestDepth--;
863 }
864
865 /* Yield to pending GC operations, regardless of request depth */
866 JS_PUBLIC_API(void)
JS_YieldRequest(JSContext * cx)867 JS_YieldRequest(JSContext *cx)
868 {
869 JSRuntime *rt;
870
871 JS_ASSERT(cx->thread);
872 CHECK_REQUEST(cx);
873
874 rt = cx->runtime;
875 JS_LOCK_GC(rt);
876 JS_ASSERT(rt->requestCount > 0);
877 rt->requestCount--;
878 if (rt->requestCount == 0)
879 JS_NOTIFY_REQUEST_DONE(rt);
880 JS_UNLOCK_GC(rt);
881 /* XXXbe give the GC or another request calling it a chance to run here?
882 Assumes FIFO scheduling */
883 JS_LOCK_GC(rt);
884 rt->requestCount++;
885 JS_UNLOCK_GC(rt);
886 }
887
888 JS_PUBLIC_API(jsrefcount)
JS_SuspendRequest(JSContext * cx)889 JS_SuspendRequest(JSContext *cx)
890 {
891 jsrefcount saveDepth = cx->requestDepth;
892
893 while (cx->requestDepth)
894 JS_EndRequest(cx);
895 return saveDepth;
896 }
897
898 JS_PUBLIC_API(void)
JS_ResumeRequest(JSContext * cx,jsrefcount saveDepth)899 JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth)
900 {
901 JS_ASSERT(!cx->requestDepth);
902 while (--saveDepth >= 0)
903 JS_BeginRequest(cx);
904 }
905
906 #endif /* JS_THREADSAFE */
907
908 JS_PUBLIC_API(void)
JS_Lock(JSRuntime * rt)909 JS_Lock(JSRuntime *rt)
910 {
911 JS_LOCK_RUNTIME(rt);
912 }
913
914 JS_PUBLIC_API(void)
JS_Unlock(JSRuntime * rt)915 JS_Unlock(JSRuntime *rt)
916 {
917 JS_UNLOCK_RUNTIME(rt);
918 }
919
920 JS_PUBLIC_API(JSContext *)
JS_NewContext(JSRuntime * rt,size_t stackChunkSize)921 JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
922 {
923 return js_NewContext(rt, stackChunkSize);
924 }
925
926 JS_PUBLIC_API(void)
JS_DestroyContext(JSContext * cx)927 JS_DestroyContext(JSContext *cx)
928 {
929 js_DestroyContext(cx, JS_FORCE_GC);
930 }
931
932 JS_PUBLIC_API(void)
JS_DestroyContextNoGC(JSContext * cx)933 JS_DestroyContextNoGC(JSContext *cx)
934 {
935 js_DestroyContext(cx, JS_NO_GC);
936 }
937
938 JS_PUBLIC_API(void)
JS_DestroyContextMaybeGC(JSContext * cx)939 JS_DestroyContextMaybeGC(JSContext *cx)
940 {
941 js_DestroyContext(cx, JS_MAYBE_GC);
942 }
943
944 JS_PUBLIC_API(void *)
JS_GetContextPrivate(JSContext * cx)945 JS_GetContextPrivate(JSContext *cx)
946 {
947 return cx->data;
948 }
949
950 JS_PUBLIC_API(void)
JS_SetContextPrivate(JSContext * cx,void * data)951 JS_SetContextPrivate(JSContext *cx, void *data)
952 {
953 cx->data = data;
954 }
955
956 JS_PUBLIC_API(JSRuntime *)
JS_GetRuntime(JSContext * cx)957 JS_GetRuntime(JSContext *cx)
958 {
959 return cx->runtime;
960 }
961
962 JS_PUBLIC_API(JSContext *)
JS_ContextIterator(JSRuntime * rt,JSContext ** iterp)963 JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
964 {
965 return js_ContextIterator(rt, JS_TRUE, iterp);
966 }
967
968 JS_PUBLIC_API(JSVersion)
JS_GetVersion(JSContext * cx)969 JS_GetVersion(JSContext *cx)
970 {
971 return cx->version;
972 }
973
974 JS_PUBLIC_API(JSVersion)
JS_SetVersion(JSContext * cx,JSVersion version)975 JS_SetVersion(JSContext *cx, JSVersion version)
976 {
977 JSVersion oldVersion;
978
979 oldVersion = cx->version;
980 if (version == oldVersion)
981 return oldVersion;
982
983 cx->version = version;
984
985 #if !JS_BUG_FALLIBLE_EQOPS
986 if (cx->version == JSVERSION_1_2) {
987 cx->jsop_eq = JSOP_NEW_EQ;
988 cx->jsop_ne = JSOP_NEW_NE;
989 } else {
990 cx->jsop_eq = JSOP_EQ;
991 cx->jsop_ne = JSOP_NE;
992 }
993 #endif /* !JS_BUG_FALLIBLE_EQOPS */
994
995 return oldVersion;
996 }
997
998 static struct v2smap {
999 JSVersion version;
1000 const char *string;
1001 } v2smap[] = {
1002 {JSVERSION_1_0, "1.0"},
1003 {JSVERSION_1_1, "1.1"},
1004 {JSVERSION_1_2, "1.2"},
1005 {JSVERSION_1_3, "1.3"},
1006 {JSVERSION_1_4, "1.4"},
1007 {JSVERSION_ECMA_3, "ECMAv3"},
1008 {JSVERSION_1_5, "1.5"},
1009 {JSVERSION_DEFAULT, "default"},
1010 {JSVERSION_UNKNOWN, NULL}, /* must be last, NULL is sentinel */
1011 };
1012
1013 JS_PUBLIC_API(const char *)
JS_VersionToString(JSVersion version)1014 JS_VersionToString(JSVersion version)
1015 {
1016 int i;
1017
1018 for (i = 0; v2smap[i].string; i++)
1019 if (v2smap[i].version == version)
1020 return v2smap[i].string;
1021 return "unknown";
1022 }
1023
1024 JS_PUBLIC_API(JSVersion)
JS_StringToVersion(const char * string)1025 JS_StringToVersion(const char *string)
1026 {
1027 int i;
1028
1029 for (i = 0; v2smap[i].string; i++)
1030 if (strcmp(v2smap[i].string, string) == 0)
1031 return v2smap[i].version;
1032 return JSVERSION_UNKNOWN;
1033 }
1034
1035 JS_PUBLIC_API(uint32)
JS_GetOptions(JSContext * cx)1036 JS_GetOptions(JSContext *cx)
1037 {
1038 return cx->options;
1039 }
1040
1041 JS_PUBLIC_API(uint32)
JS_SetOptions(JSContext * cx,uint32 options)1042 JS_SetOptions(JSContext *cx, uint32 options)
1043 {
1044 uint32 oldopts = cx->options;
1045 cx->options = options;
1046 return oldopts;
1047 }
1048
1049 JS_PUBLIC_API(uint32)
JS_ToggleOptions(JSContext * cx,uint32 options)1050 JS_ToggleOptions(JSContext *cx, uint32 options)
1051 {
1052 uint32 oldopts = cx->options;
1053 cx->options ^= options;
1054 return oldopts;
1055 }
1056
1057 JS_PUBLIC_API(const char *)
JS_GetImplementationVersion(void)1058 JS_GetImplementationVersion(void)
1059 {
1060 return "JavaScript-C 1.5 2004-09-24";
1061 }
1062
1063
1064 JS_PUBLIC_API(JSObject *)
JS_GetGlobalObject(JSContext * cx)1065 JS_GetGlobalObject(JSContext *cx)
1066 {
1067 return cx->globalObject;
1068 }
1069
1070 JS_PUBLIC_API(void)
JS_SetGlobalObject(JSContext * cx,JSObject * obj)1071 JS_SetGlobalObject(JSContext *cx, JSObject *obj)
1072 {
1073 cx->globalObject = obj;
1074 }
1075
1076 JS_PUBLIC_API(JSBool)
JS_IsValidIdentifier(const char * identifier)1077 JS_IsValidIdentifier(const char *identifier)
1078 {
1079 const char *identifierPos;
1080
1081 if (!*identifier || !JS_ISIDENT_START(*identifier))
1082 return JS_FALSE;
1083
1084 identifierPos = identifier+1;
1085 while (*identifierPos) {
1086 if (!JS_ISIDENT(*identifierPos))
1087 return JS_FALSE;
1088 identifierPos++;
1089 }
1090
1091 return JS_TRUE;
1092 }
1093
1094 JS_PUBLIC_API(JSBool)
JS_PushLintIdentifers(JSContext * cx,JSObject * curScriptIdentifiers,JSLObjectList * dependencyIdentifiers,JSBool alwaysUseOptionExplicit,JSBool lambdaAssignRequiresSemicolon,JSBool enableLegacyControlComments,JSBool enableJScriptFunctionExtensions,JSLImportCallback importCallback,void * parms)1095 JS_PushLintIdentifers(JSContext *cx, JSObject *curScriptIdentifiers, JSLObjectList *dependencyIdentifiers,
1096 JSBool alwaysUseOptionExplicit, JSBool lambdaAssignRequiresSemicolon,
1097 JSBool enableLegacyControlComments, JSBool enableJScriptFunctionExtensions,
1098 JSLImportCallback importCallback, void *parms)
1099 {
1100 JSLint *newLint;
1101 newLint = JS_malloc(cx, sizeof(JSLint));
1102 if (!newLint)
1103 return JS_FALSE;
1104 memset(newLint, 0, sizeof(JSLint));
1105
1106 if (importCallback) {
1107 newLint->importCallback = importCallback;
1108 newLint->importCallbackParms = parms;
1109
1110 newLint->importPaths = JS_malloc(cx, sizeof(JSLImportPathList));
1111 JS_INIT_CLIST(&newLint->importPaths->links);
1112 newLint->importPaths->importPath = 0;
1113 }
1114
1115 newLint->scriptIdentifiers = curScriptIdentifiers;
1116 newLint->dependencyList = dependencyIdentifiers;
1117 newLint->alwaysUseOptionExplicit = alwaysUseOptionExplicit;
1118 newLint->lambdaAssignRequiresSemicolon = lambdaAssignRequiresSemicolon;
1119 newLint->enableLegacyControlComments = enableLegacyControlComments;
1120 newLint->enableJScriptFunctionExtensions = enableJScriptFunctionExtensions;
1121 newLint->down = cx->lint;
1122 cx->lint = newLint;
1123 return JS_TRUE;
1124 }
1125
1126 JS_PUBLIC_API(void)
JS_PopLintIdentifers(JSContext * cx)1127 JS_PopLintIdentifers(JSContext *cx)
1128 {
1129 JSLint *prevLint;
1130
1131 if (cx->lint) {
1132 prevLint = cx->lint->down;
1133
1134 /* free import paths */
1135 if (cx->lint->importPaths) {
1136 while (!JS_CLIST_IS_EMPTY(&cx->lint->importPaths->links)) {
1137 JSLImportPathList *curPath;
1138 curPath = (JSLImportPathList*)JS_LIST_HEAD(&cx->lint->importPaths->links);
1139 JS_REMOVE_LINK(&curPath->links);
1140 JS_free(cx, curPath->importPath);
1141 JS_free(cx, curPath);
1142 }
1143 JS_free(cx, cx->lint->importPaths);
1144 }
1145
1146 JS_free(cx, cx->lint);
1147 cx->lint = prevLint;
1148 }
1149 }
1150
1151 static JSObject *
InitFunctionAndObjectClasses(JSContext * cx,JSObject * obj)1152 InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
1153 {
1154 JSDHashTable *table;
1155 JSBool resolving;
1156 JSRuntime *rt;
1157 JSResolvingKey key;
1158 JSResolvingEntry *entry;
1159 JSObject *fun_proto, *obj_proto;
1160
1161 /* If cx has no global object, use obj so prototypes can be found. */
1162 if (!cx->globalObject)
1163 cx->globalObject = obj;
1164
1165 /* Record Function and Object in cx->resolvingTable, if we are resolving. */
1166 table = cx->resolvingTable;
1167 resolving = (table && table->entryCount);
1168 if (resolving) {
1169 rt = cx->runtime;
1170 key.obj = obj;
1171 key.id = (jsid) rt->atomState.FunctionAtom;
1172 entry = (JSResolvingEntry *)
1173 JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
1174 if (entry && entry->key.obj && (entry->flags & JSRESFLAG_LOOKUP)) {
1175 /* Already resolving Function, record Object too. */
1176 JS_ASSERT(entry->key.obj == obj);
1177 key.id = (jsid) rt->atomState.ObjectAtom;
1178 entry = (JSResolvingEntry *)
1179 JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
1180 }
1181 if (!entry) {
1182 JS_ReportOutOfMemory(cx);
1183 return NULL;
1184 }
1185 JS_ASSERT(!entry->key.obj && entry->flags == 0);
1186 entry->key = key;
1187 entry->flags = JSRESFLAG_LOOKUP;
1188 }
1189
1190 /* Initialize the function class first so constructors can be made. */
1191 fun_proto = js_InitFunctionClass(cx, obj);
1192 if (!fun_proto)
1193 goto out;
1194
1195 /* Initialize the object class next so Object.prototype works. */
1196 obj_proto = js_InitObjectClass(cx, obj);
1197 if (!obj_proto) {
1198 fun_proto = NULL;
1199 goto out;
1200 }
1201
1202 /* Function.prototype and the global object delegate to Object.prototype. */
1203 OBJ_SET_PROTO(cx, fun_proto, obj_proto);
1204 if (!OBJ_GET_PROTO(cx, obj))
1205 OBJ_SET_PROTO(cx, obj, obj_proto);
1206
1207 out:
1208 /* If resolving, remove the other entry (Object or Function) from table. */
1209 if (resolving)
1210 JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE);
1211 return fun_proto;
1212 }
1213
1214 JS_PUBLIC_API(JSBool)
JS_InitStandardClasses(JSContext * cx,JSObject * obj)1215 JS_InitStandardClasses(JSContext *cx, JSObject *obj)
1216 {
1217 CHECK_REQUEST(cx);
1218
1219 #if JS_HAS_UNDEFINED
1220 {
1221 /* Define a top-level property 'undefined' with the undefined value. */
1222 JSAtom *atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
1223 if (!OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL, NULL,
1224 JSPROP_PERMANENT, NULL)) {
1225 return JS_FALSE;
1226 }
1227 }
1228 #endif
1229
1230 /* Function and Object require cooperative bootstrapping magic. */
1231 if (!InitFunctionAndObjectClasses(cx, obj))
1232 return JS_FALSE;
1233
1234 /* Initialize the rest of the standard objects and functions. */
1235 return js_InitArrayClass(cx, obj) &&
1236 js_InitBooleanClass(cx, obj) &&
1237 js_InitMathClass(cx, obj) &&
1238 js_InitNumberClass(cx, obj) &&
1239 js_InitStringClass(cx, obj) &&
1240 #if JS_HAS_CALL_OBJECT
1241 js_InitCallClass(cx, obj) &&
1242 #endif
1243 #if JS_HAS_REGEXPS
1244 js_InitRegExpClass(cx, obj) &&
1245 #endif
1246 #if JS_HAS_SCRIPT_OBJECT
1247 js_InitScriptClass(cx, obj) &&
1248 #endif
1249 #if JS_HAS_ERROR_EXCEPTIONS
1250 js_InitExceptionClasses(cx, obj) &&
1251 #endif
1252 #if JS_HAS_FILE_OBJECT
1253 js_InitFileClass(cx, obj, JS_TRUE) &&
1254 #endif
1255 js_InitDateClass(cx, obj);
1256 }
1257
1258 #define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom)
1259 #define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off)))
1260
1261 /*
1262 * Table of class initializers and their atom offsets in rt->atomState.
1263 * If you add a "standard" class, remember to update this table.
1264 */
1265 static struct {
1266 JSObjectOp init;
1267 size_t atomOffset;
1268 } standard_class_atoms[] = {
1269 {InitFunctionAndObjectClasses, ATOM_OFFSET(Function)},
1270 {InitFunctionAndObjectClasses, ATOM_OFFSET(Object)},
1271 {js_InitArrayClass, ATOM_OFFSET(Array)},
1272 {js_InitBooleanClass, ATOM_OFFSET(Boolean)},
1273 {js_InitDateClass, ATOM_OFFSET(Date)},
1274 {js_InitMathClass, ATOM_OFFSET(Math)},
1275 {js_InitNumberClass, ATOM_OFFSET(Number)},
1276 {js_InitStringClass, ATOM_OFFSET(String)},
1277 #if JS_HAS_CALL_OBJECT
1278 {js_InitCallClass, ATOM_OFFSET(Call)},
1279 #endif
1280 #if JS_HAS_ERROR_EXCEPTIONS
1281 {js_InitExceptionClasses, ATOM_OFFSET(Error)},
1282 #endif
1283 #if JS_HAS_REGEXPS
1284 {js_InitRegExpClass, ATOM_OFFSET(RegExp)},
1285 #endif
1286 #if JS_HAS_SCRIPT_OBJECT
1287 {js_InitScriptClass, ATOM_OFFSET(Script)},
1288 #endif
1289 {NULL, 0}
1290 };
1291
1292 /*
1293 * Table of top-level function and constant names and their init functions.
1294 * If you add a "standard" global function or property, remember to update
1295 * this table.
1296 */
1297 typedef struct JSStdName {
1298 JSObjectOp init;
1299 size_t atomOffset; /* offset of atom pointer in JSAtomState */
1300 const char *name; /* null if atom is pre-pinned, else name */
1301 } JSStdName;
1302
1303 static JSAtom *
StdNameToAtom(JSContext * cx,JSStdName * stdn)1304 StdNameToAtom(JSContext *cx, JSStdName *stdn)
1305 {
1306 size_t offset;
1307 JSAtom *atom;
1308 const char *name;
1309
1310 offset = stdn->atomOffset;
1311 atom = OFFSET_TO_ATOM(cx->runtime, offset);
1312 if (!atom) {
1313 name = stdn->name;
1314 if (name) {
1315 atom = js_Atomize(cx, name, strlen(name), ATOM_PINNED);
1316 OFFSET_TO_ATOM(cx->runtime, offset) = atom;
1317 }
1318 }
1319 return atom;
1320 }
1321
1322 #define EAGERLY_PINNED_ATOM(name) ATOM_OFFSET(name), NULL
1323 #define LAZILY_PINNED_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
1324
1325 static JSStdName standard_class_names[] = {
1326 /* ECMA requires that eval be a direct property of the global object. */
1327 {js_InitObjectClass, EAGERLY_PINNED_ATOM(eval)},
1328
1329 /* Global properties and functions defined by the Number class. */
1330 {js_InitNumberClass, LAZILY_PINNED_ATOM(NaN)},
1331 {js_InitNumberClass, LAZILY_PINNED_ATOM(Infinity)},
1332 {js_InitNumberClass, LAZILY_PINNED_ATOM(isNaN)},
1333 {js_InitNumberClass, LAZILY_PINNED_ATOM(isFinite)},
1334 {js_InitNumberClass, LAZILY_PINNED_ATOM(parseFloat)},
1335 {js_InitNumberClass, LAZILY_PINNED_ATOM(parseInt)},
1336
1337 /* String global functions. */
1338 {js_InitStringClass, LAZILY_PINNED_ATOM(escape)},
1339 {js_InitStringClass, LAZILY_PINNED_ATOM(unescape)},
1340 {js_InitStringClass, LAZILY_PINNED_ATOM(decodeURI)},
1341 {js_InitStringClass, LAZILY_PINNED_ATOM(encodeURI)},
1342 {js_InitStringClass, LAZILY_PINNED_ATOM(decodeURIComponent)},
1343 {js_InitStringClass, LAZILY_PINNED_ATOM(encodeURIComponent)},
1344 #if JS_HAS_UNEVAL
1345 {js_InitStringClass, LAZILY_PINNED_ATOM(uneval)},
1346 #endif
1347
1348 /* Exception constructors. */
1349 #if JS_HAS_ERROR_EXCEPTIONS
1350 {js_InitExceptionClasses, EAGERLY_PINNED_ATOM(Error)},
1351 {js_InitExceptionClasses, LAZILY_PINNED_ATOM(InternalError)},
1352 {js_InitExceptionClasses, LAZILY_PINNED_ATOM(EvalError)},
1353 {js_InitExceptionClasses, LAZILY_PINNED_ATOM(RangeError)},
1354 {js_InitExceptionClasses, LAZILY_PINNED_ATOM(ReferenceError)},
1355 {js_InitExceptionClasses, LAZILY_PINNED_ATOM(SyntaxError)},
1356 {js_InitExceptionClasses, LAZILY_PINNED_ATOM(TypeError)},
1357 {js_InitExceptionClasses, LAZILY_PINNED_ATOM(URIError)},
1358 #endif
1359
1360 {NULL, 0, NULL}
1361 };
1362
1363 static JSStdName object_prototype_names[] = {
1364 /* Object.prototype properties (global delegates to Object.prototype). */
1365 {js_InitObjectClass, EAGERLY_PINNED_ATOM(proto)},
1366 {js_InitObjectClass, EAGERLY_PINNED_ATOM(parent)},
1367 {js_InitObjectClass, EAGERLY_PINNED_ATOM(count)},
1368 #if JS_HAS_TOSOURCE
1369 {js_InitObjectClass, EAGERLY_PINNED_ATOM(toSource)},
1370 #endif
1371 {js_InitObjectClass, EAGERLY_PINNED_ATOM(toString)},
1372 {js_InitObjectClass, EAGERLY_PINNED_ATOM(toLocaleString)},
1373 {js_InitObjectClass, EAGERLY_PINNED_ATOM(valueOf)},
1374 #if JS_HAS_OBJ_WATCHPOINT
1375 {js_InitObjectClass, LAZILY_PINNED_ATOM(watch)},
1376 {js_InitObjectClass, LAZILY_PINNED_ATOM(unwatch)},
1377 #endif
1378 #if JS_HAS_NEW_OBJ_METHODS
1379 {js_InitObjectClass, LAZILY_PINNED_ATOM(hasOwnProperty)},
1380 {js_InitObjectClass, LAZILY_PINNED_ATOM(isPrototypeOf)},
1381 {js_InitObjectClass, LAZILY_PINNED_ATOM(propertyIsEnumerable)},
1382 #endif
1383 #if JS_HAS_GETTER_SETTER
1384 {js_InitObjectClass, LAZILY_PINNED_ATOM(defineGetter)},
1385 {js_InitObjectClass, LAZILY_PINNED_ATOM(defineSetter)},
1386 {js_InitObjectClass, LAZILY_PINNED_ATOM(lookupGetter)},
1387 {js_InitObjectClass, LAZILY_PINNED_ATOM(lookupSetter)},
1388 #endif
1389
1390 {NULL, 0, NULL}
1391 };
1392
1393 #undef EAGERLY_PINNED_ATOM
1394 #undef LAZILY_PINNED_ATOM
1395
1396 JS_PUBLIC_API(JSBool)
JS_ResolveStandardClass(JSContext * cx,JSObject * obj,jsval id,JSBool * resolved)1397 JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
1398 JSBool *resolved)
1399 {
1400 JSString *idstr;
1401 JSRuntime *rt;
1402 JSAtom *atom;
1403 JSObjectOp init;
1404 uintN i;
1405
1406 CHECK_REQUEST(cx);
1407 *resolved = JS_FALSE;
1408
1409 if (!JSVAL_IS_STRING(id))
1410 return JS_TRUE;
1411 idstr = JSVAL_TO_STRING(id);
1412 rt = cx->runtime;
1413
1414 #if JS_HAS_UNDEFINED
1415 /* See if we're resolving 'undefined', and define it if so. */
1416 atom = rt->atomState.typeAtoms[JSTYPE_VOID];
1417 if (idstr == ATOM_TO_STRING(atom)) {
1418 *resolved = JS_TRUE;
1419 return OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL, NULL,
1420 JSPROP_PERMANENT, NULL);
1421 }
1422 #endif
1423
1424 /* Try for class constructors/prototypes named by well-known atoms. */
1425 init = NULL;
1426 for (i = 0; standard_class_atoms[i].init; i++) {
1427 atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
1428 if (idstr == ATOM_TO_STRING(atom)) {
1429 init = standard_class_atoms[i].init;
1430 break;
1431 }
1432 }
1433
1434 if (!init) {
1435 /* Try less frequently used top-level functions and constants. */
1436 for (i = 0; standard_class_names[i].init; i++) {
1437 atom = StdNameToAtom(cx, &standard_class_names[i]);
1438 if (!atom)
1439 return JS_FALSE;
1440 if (idstr == ATOM_TO_STRING(atom)) {
1441 init = standard_class_names[i].init;
1442 break;
1443 }
1444 }
1445
1446 if (!init && !OBJ_GET_PROTO(cx, obj)) {
1447 /*
1448 * Try even less frequently used names delegated from the global
1449 * object to Object.prototype, but only if the Object class hasn't
1450 * yet been initialized.
1451 */
1452 for (i = 0; object_prototype_names[i].init; i++) {
1453 atom = StdNameToAtom(cx, &object_prototype_names[i]);
1454 if (!atom)
1455 return JS_FALSE;
1456 if (idstr == ATOM_TO_STRING(atom)) {
1457 init = standard_class_names[i].init;
1458 break;
1459 }
1460 }
1461 }
1462 }
1463
1464 if (init) {
1465 if (!init(cx, obj))
1466 return JS_FALSE;
1467 *resolved = JS_TRUE;
1468 }
1469 return JS_TRUE;
1470 }
1471
1472 static JSBool
HasOwnProperty(JSContext * cx,JSObject * obj,JSAtom * atom,JSBool * ownp)1473 HasOwnProperty(JSContext *cx, JSObject *obj, JSAtom *atom, JSBool *ownp)
1474 {
1475 JSObject *pobj;
1476 JSProperty *prop;
1477
1478 if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &pobj, &prop))
1479 return JS_FALSE;
1480 if (prop)
1481 OBJ_DROP_PROPERTY(cx, pobj, prop);
1482 *ownp = (pobj == obj && prop);
1483 return JS_TRUE;
1484 }
1485
1486 JS_PUBLIC_API(JSBool)
JS_EnumerateStandardClasses(JSContext * cx,JSObject * obj)1487 JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
1488 {
1489 JSRuntime *rt;
1490 JSAtom *atom;
1491 JSBool found;
1492 uintN i;
1493
1494 CHECK_REQUEST(cx);
1495 rt = cx->runtime;
1496
1497 #if JS_HAS_UNDEFINED
1498 /* See if we need to bind 'undefined' and define it if so. */
1499 atom = rt->atomState.typeAtoms[JSTYPE_VOID];
1500 if (!HasOwnProperty(cx, obj, atom, &found))
1501 return JS_FALSE;
1502 if (!found &&
1503 !OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL, NULL,
1504 JSPROP_PERMANENT, NULL)) {
1505 return JS_FALSE;
1506 }
1507 #endif
1508
1509 /* Initialize any classes that have not been resolved yet. */
1510 for (i = 0; standard_class_atoms[i].init; i++) {
1511 atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
1512 if (!HasOwnProperty(cx, obj, atom, &found))
1513 return JS_FALSE;
1514 if (!found && !standard_class_atoms[i].init(cx, obj))
1515 return JS_FALSE;
1516 }
1517
1518 return JS_TRUE;
1519 }
1520
1521 #undef ATOM_OFFSET
1522 #undef OFFSET_TO_ATOM
1523
1524 JS_PUBLIC_API(JSObject *)
JS_GetScopeChain(JSContext * cx)1525 JS_GetScopeChain(JSContext *cx)
1526 {
1527 return cx->fp ? cx->fp->scopeChain : NULL;
1528 }
1529
1530 JS_PUBLIC_API(void *)
JS_malloc(JSContext * cx,size_t nbytes)1531 JS_malloc(JSContext *cx, size_t nbytes)
1532 {
1533 void *p;
1534
1535 JS_ASSERT(nbytes != 0);
1536 if (nbytes == 0)
1537 nbytes = 1;
1538 cx->runtime->gcMallocBytes += nbytes;
1539 p = malloc(nbytes);
1540 if (!p)
1541 JS_ReportOutOfMemory(cx);
1542 return p;
1543 }
1544
1545 JS_PUBLIC_API(void *)
JS_realloc(JSContext * cx,void * p,size_t nbytes)1546 JS_realloc(JSContext *cx, void *p, size_t nbytes)
1547 {
1548 p = realloc(p, nbytes);
1549 if (!p)
1550 JS_ReportOutOfMemory(cx);
1551 return p;
1552 }
1553
1554 JS_PUBLIC_API(void)
JS_free(JSContext * cx,void * p)1555 JS_free(JSContext *cx, void *p)
1556 {
1557 if (p)
1558 free(p);
1559 }
1560
1561 JS_PUBLIC_API(char *)
JS_strdup(JSContext * cx,const char * s)1562 JS_strdup(JSContext *cx, const char *s)
1563 {
1564 size_t n;
1565 void *p;
1566
1567 n = strlen(s) + 1;
1568 p = JS_malloc(cx, n);
1569 if (!p)
1570 return NULL;
1571 return (char *)memcpy(p, s, n);
1572 }
1573
1574 JS_PUBLIC_API(jsdouble *)
JS_NewDouble(JSContext * cx,jsdouble d)1575 JS_NewDouble(JSContext *cx, jsdouble d)
1576 {
1577 CHECK_REQUEST(cx);
1578 return js_NewDouble(cx, d);
1579 }
1580
1581 JS_PUBLIC_API(JSBool)
JS_NewDoubleValue(JSContext * cx,jsdouble d,jsval * rval)1582 JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval)
1583 {
1584 CHECK_REQUEST(cx);
1585 return js_NewDoubleValue(cx, d, rval);
1586 }
1587
1588 JS_PUBLIC_API(JSBool)
JS_NewNumberValue(JSContext * cx,jsdouble d,jsval * rval)1589 JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
1590 {
1591 CHECK_REQUEST(cx);
1592 return js_NewNumberValue(cx, d, rval);
1593 }
1594
1595 #undef JS_AddRoot
1596 JS_PUBLIC_API(JSBool)
JS_AddRoot(JSContext * cx,void * rp)1597 JS_AddRoot(JSContext *cx, void *rp)
1598 {
1599 CHECK_REQUEST(cx);
1600 return js_AddRoot(cx, rp, NULL);
1601 }
1602
1603 JS_PUBLIC_API(JSBool)
JS_AddNamedRootRT(JSRuntime * rt,void * rp,const char * name)1604 JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name)
1605 {
1606 return js_AddRootRT(rt, rp, name);
1607 }
1608
1609 JS_PUBLIC_API(JSBool)
JS_RemoveRoot(JSContext * cx,void * rp)1610 JS_RemoveRoot(JSContext *cx, void *rp)
1611 {
1612 CHECK_REQUEST(cx);
1613 return js_RemoveRoot(cx->runtime, rp);
1614 }
1615
1616 JS_PUBLIC_API(JSBool)
JS_RemoveRootRT(JSRuntime * rt,void * rp)1617 JS_RemoveRootRT(JSRuntime *rt, void *rp)
1618 {
1619 return js_RemoveRoot(rt, rp);
1620 }
1621
1622 JS_PUBLIC_API(JSBool)
JS_AddNamedRoot(JSContext * cx,void * rp,const char * name)1623 JS_AddNamedRoot(JSContext *cx, void *rp, const char *name)
1624 {
1625 CHECK_REQUEST(cx);
1626 return js_AddRoot(cx, rp, name);
1627 }
1628
1629 JS_PUBLIC_API(void)
JS_ClearNewbornRoots(JSContext * cx)1630 JS_ClearNewbornRoots(JSContext *cx)
1631 {
1632 uintN i;
1633
1634 for (i = 0; i < GCX_NTYPES; i++)
1635 cx->newborn[i] = NULL;
1636 cx->lastAtom = NULL;
1637 }
1638
1639 JS_PUBLIC_API(JSBool)
JS_EnterLocalRootScope(JSContext * cx)1640 JS_EnterLocalRootScope(JSContext *cx)
1641 {
1642 CHECK_REQUEST(cx);
1643 return js_EnterLocalRootScope(cx);
1644 }
1645
1646 JS_PUBLIC_API(void)
JS_LeaveLocalRootScope(JSContext * cx)1647 JS_LeaveLocalRootScope(JSContext *cx)
1648 {
1649 CHECK_REQUEST(cx);
1650 js_LeaveLocalRootScope(cx);
1651 }
1652
1653 JS_PUBLIC_API(void)
JS_ForgetLocalRoot(JSContext * cx,void * thing)1654 JS_ForgetLocalRoot(JSContext *cx, void *thing)
1655 {
1656 CHECK_REQUEST(cx);
1657 js_ForgetLocalRoot(cx, (jsval) thing);
1658 }
1659
1660 #include "jshash.h" /* Added by JSIFY */
1661
1662 #ifdef DEBUG
1663
1664 typedef struct NamedRootDumpArgs {
1665 void (*dump)(const char *name, void *rp, void *data);
1666 void *data;
1667 } NamedRootDumpArgs;
1668
1669 JS_STATIC_DLL_CALLBACK(JSDHashOperator)
js_named_root_dumper(JSDHashTable * table,JSDHashEntryHdr * hdr,uint32 number,void * arg)1670 js_named_root_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
1671 void *arg)
1672 {
1673 NamedRootDumpArgs *args = (NamedRootDumpArgs *) arg;
1674 JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
1675
1676 if (rhe->name)
1677 args->dump(rhe->name, rhe->root, args->data);
1678 return JS_DHASH_NEXT;
1679 }
1680
1681 JS_PUBLIC_API(void)
JS_DumpNamedRoots(JSRuntime * rt,void (* dump)(const char * name,void * rp,void * data),void * data)1682 JS_DumpNamedRoots(JSRuntime *rt,
1683 void (*dump)(const char *name, void *rp, void *data),
1684 void *data)
1685 {
1686 NamedRootDumpArgs args;
1687
1688 args.dump = dump;
1689 args.data = data;
1690 JS_DHashTableEnumerate(&rt->gcRootsHash, js_named_root_dumper, &args);
1691 }
1692
1693 #endif /* DEBUG */
1694
1695 typedef struct GCRootMapArgs {
1696 JSGCRootMapFun map;
1697 void *data;
1698 } GCRootMapArgs;
1699
1700 JS_STATIC_DLL_CALLBACK(JSDHashOperator)
js_gcroot_mapper(JSDHashTable * table,JSDHashEntryHdr * hdr,uint32 number,void * arg)1701 js_gcroot_mapper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
1702 void *arg)
1703 {
1704 GCRootMapArgs *args = (GCRootMapArgs *) arg;
1705 JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
1706 intN mapflags;
1707 JSDHashOperator op;
1708
1709 mapflags = args->map(rhe->root, rhe->name, args->data);
1710
1711 #if JS_MAP_GCROOT_NEXT == JS_DHASH_NEXT && \
1712 JS_MAP_GCROOT_STOP == JS_DHASH_STOP && \
1713 JS_MAP_GCROOT_REMOVE == JS_DHASH_REMOVE
1714 op = (JSDHashOperator)mapflags;
1715 #else
1716 op = JS_DHASH_NEXT;
1717 if (mapflags & JS_MAP_GCROOT_STOP)
1718 op |= JS_DHASH_STOP;
1719 if (mapflags & JS_MAP_GCROOT_REMOVE)
1720 op |= JS_DHASH_REMOVE;
1721 #endif
1722
1723 return op;
1724 }
1725
1726 JS_PUBLIC_API(uint32)
JS_MapGCRoots(JSRuntime * rt,JSGCRootMapFun map,void * data)1727 JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
1728 {
1729 GCRootMapArgs args;
1730 uint32 rv;
1731
1732 args.map = map;
1733 args.data = data;
1734 JS_LOCK_GC(rt);
1735 rv = JS_DHashTableEnumerate(&rt->gcRootsHash, js_gcroot_mapper, &args);
1736 JS_UNLOCK_GC(rt);
1737 return rv;
1738 }
1739
1740 JS_PUBLIC_API(JSBool)
JS_LockGCThing(JSContext * cx,void * thing)1741 JS_LockGCThing(JSContext *cx, void *thing)
1742 {
1743 JSBool ok;
1744
1745 CHECK_REQUEST(cx);
1746 ok = js_LockGCThing(cx, thing);
1747 if (!ok)
1748 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_LOCK);
1749 return ok;
1750 }
1751
1752 JS_PUBLIC_API(JSBool)
JS_LockGCThingRT(JSRuntime * rt,void * thing)1753 JS_LockGCThingRT(JSRuntime *rt, void *thing)
1754 {
1755 return js_LockGCThingRT(rt, thing);
1756 }
1757
1758 JS_PUBLIC_API(JSBool)
JS_UnlockGCThing(JSContext * cx,void * thing)1759 JS_UnlockGCThing(JSContext *cx, void *thing)
1760 {
1761 JSBool ok;
1762
1763 CHECK_REQUEST(cx);
1764 ok = js_UnlockGCThingRT(cx->runtime, thing);
1765 if (!ok)
1766 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_UNLOCK);
1767 return ok;
1768 }
1769
1770 JS_PUBLIC_API(JSBool)
JS_UnlockGCThingRT(JSRuntime * rt,void * thing)1771 JS_UnlockGCThingRT(JSRuntime *rt, void *thing)
1772 {
1773 return js_UnlockGCThingRT(rt, thing);
1774 }
1775
1776 JS_PUBLIC_API(void)
JS_MarkGCThing(JSContext * cx,void * thing,const char * name,void * arg)1777 JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg)
1778 {
1779 JS_ASSERT(cx->runtime->gcLevel > 0);
1780 #ifdef JS_THREADSAFE
1781 JS_ASSERT(cx->runtime->gcThread == js_CurrentThreadId());
1782 #endif
1783
1784 GC_MARK(cx, thing, name, arg);
1785 }
1786
1787 JS_PUBLIC_API(void)
JS_GC(JSContext * cx)1788 JS_GC(JSContext *cx)
1789 {
1790 /* Don't nuke active arenas if executing or compiling. */
1791 if (cx->stackPool.current == &cx->stackPool.first)
1792 JS_FinishArenaPool(&cx->stackPool);
1793 if (cx->tempPool.current == &cx->tempPool.first)
1794 JS_FinishArenaPool(&cx->tempPool);
1795 js_ForceGC(cx, 0);
1796 }
1797
1798 JS_PUBLIC_API(void)
JS_MaybeGC(JSContext * cx)1799 JS_MaybeGC(JSContext *cx)
1800 {
1801 JSRuntime *rt;
1802 uint32 bytes, lastBytes;
1803
1804 rt = cx->runtime;
1805 bytes = rt->gcBytes;
1806 lastBytes = rt->gcLastBytes;
1807 if ((bytes > 8192 && bytes > lastBytes + lastBytes / 2) ||
1808 rt->gcMallocBytes > rt->gcMaxBytes) {
1809 /*
1810 * Run the GC if we have half again as many bytes of GC-things as
1811 * the last time we GC'd, or if we have malloc'd more bytes through
1812 * JS_malloc than we were told to allocate by JS_NewRuntime.
1813 */
1814 JS_GC(cx);
1815 }
1816 }
1817
1818 JS_PUBLIC_API(JSGCCallback)
JS_SetGCCallback(JSContext * cx,JSGCCallback cb)1819 JS_SetGCCallback(JSContext *cx, JSGCCallback cb)
1820 {
1821 return JS_SetGCCallbackRT(cx->runtime, cb);
1822 }
1823
1824 JS_PUBLIC_API(JSGCCallback)
JS_SetGCCallbackRT(JSRuntime * rt,JSGCCallback cb)1825 JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb)
1826 {
1827 JSGCCallback oldcb;
1828
1829 oldcb = rt->gcCallback;
1830 rt->gcCallback = cb;
1831 return oldcb;
1832 }
1833
1834 JS_PUBLIC_API(JSBool)
JS_IsAboutToBeFinalized(JSContext * cx,void * thing)1835 JS_IsAboutToBeFinalized(JSContext *cx, void *thing)
1836 {
1837 JS_ASSERT(thing);
1838 return js_IsAboutToBeFinalized(cx, thing);
1839 }
1840
1841 JS_PUBLIC_API(intN)
JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)1842 JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)
1843 {
1844 return js_ChangeExternalStringFinalizer(NULL, finalizer);
1845 }
1846
1847 JS_PUBLIC_API(intN)
JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer)1848 JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer)
1849 {
1850 return js_ChangeExternalStringFinalizer(finalizer, NULL);
1851 }
1852
1853 JS_PUBLIC_API(JSString *)
JS_NewExternalString(JSContext * cx,jschar * chars,size_t length,intN type)1854 JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type)
1855 {
1856 JSString *str;
1857
1858 CHECK_REQUEST(cx);
1859 JS_ASSERT(GCX_EXTERNAL_STRING <= type && type < (intN) GCX_NTYPES);
1860
1861 str = (JSString *) js_AllocGCThing(cx, (uintN) type);
1862 if (!str)
1863 return NULL;
1864 str->length = length;
1865 str->chars = chars;
1866 return str;
1867 }
1868
1869 JS_PUBLIC_API(intN)
JS_GetExternalStringGCType(JSRuntime * rt,JSString * str)1870 JS_GetExternalStringGCType(JSRuntime *rt, JSString *str)
1871 {
1872 uint8 type = (uint8) (*js_GetGCThingFlags(str) & GCF_TYPEMASK);
1873
1874 if (type >= GCX_EXTERNAL_STRING)
1875 return (intN)type;
1876 JS_ASSERT(type == GCX_STRING || type == GCX_MUTABLE_STRING);
1877 return -1;
1878 }
1879
1880 #ifdef DEBUG
1881 /* FIXME: 242518 static */ void
CheckStackGrowthDirection(int * dummy1addr,jsuword limitAddr)1882 CheckStackGrowthDirection(int *dummy1addr, jsuword limitAddr)
1883 {
1884 int dummy2;
1885
1886 #if JS_STACK_GROWTH_DIRECTION > 0
1887 JS_ASSERT(dummy1addr < &dummy2);
1888 JS_ASSERT((jsuword)&dummy2 < limitAddr);
1889 #else
1890 /* Stack grows downward, the common case on modern architectures. */
1891 JS_ASSERT(&dummy2 < dummy1addr);
1892 JS_ASSERT(limitAddr < (jsuword)&dummy2);
1893 #endif
1894 }
1895 #endif
1896
1897 JS_PUBLIC_API(void)
JS_SetThreadStackLimit(JSContext * cx,jsuword limitAddr)1898 JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr)
1899 {
1900 #ifdef DEBUG
1901 int dummy1;
1902
1903 CheckStackGrowthDirection(&dummy1, limitAddr);
1904 #endif
1905
1906 #if JS_STACK_GROWTH_DIRECTION > 0
1907 if (limitAddr == 0)
1908 limitAddr = (jsuword)-1;
1909 #endif
1910 cx->stackLimit = limitAddr;
1911 }
1912
1913 /************************************************************************/
1914
1915 JS_PUBLIC_API(void)
JS_DestroyIdArray(JSContext * cx,JSIdArray * ida)1916 JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
1917 {
1918 JS_free(cx, ida);
1919 }
1920
1921 JS_PUBLIC_API(JSBool)
JS_ValueToId(JSContext * cx,jsval v,jsid * idp)1922 JS_ValueToId(JSContext *cx, jsval v, jsid *idp)
1923 {
1924 JSAtom *atom;
1925
1926 CHECK_REQUEST(cx);
1927 if (JSVAL_IS_INT(v)) {
1928 *idp = v;
1929 } else {
1930 atom = js_ValueToStringAtom(cx, v);
1931 if (!atom)
1932 return JS_FALSE;
1933 *idp = (jsid)atom;
1934 }
1935 return JS_TRUE;
1936 }
1937
1938 JS_PUBLIC_API(JSBool)
JS_IdToValue(JSContext * cx,jsid id,jsval * vp)1939 JS_IdToValue(JSContext *cx, jsid id, jsval *vp)
1940 {
1941 CHECK_REQUEST(cx);
1942 *vp = ID_TO_VALUE(id);
1943 return JS_TRUE;
1944 }
1945
1946 JS_PUBLIC_API(JSBool)
JS_PropertyStub(JSContext * cx,JSObject * obj,jsval id,jsval * vp)1947 JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
1948 {
1949 return JS_TRUE;
1950 }
1951
1952 JS_PUBLIC_API(JSBool)
JS_EnumerateStub(JSContext * cx,JSObject * obj)1953 JS_EnumerateStub(JSContext *cx, JSObject *obj)
1954 {
1955 return JS_TRUE;
1956 }
1957
1958 JS_PUBLIC_API(JSBool)
JS_ResolveStub(JSContext * cx,JSObject * obj,jsval id)1959 JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id)
1960 {
1961 return JS_TRUE;
1962 }
1963
1964 JS_PUBLIC_API(JSBool)
JS_ConvertStub(JSContext * cx,JSObject * obj,JSType type,jsval * vp)1965 JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
1966 {
1967 #if JS_BUG_EAGER_TOSTRING
1968 if (type == JSTYPE_STRING)
1969 return JS_TRUE;
1970 #endif
1971 return js_TryValueOf(cx, obj, type, vp);
1972 }
1973
1974 JS_PUBLIC_API(void)
JS_FinalizeStub(JSContext * cx,JSObject * obj)1975 JS_FinalizeStub(JSContext *cx, JSObject *obj)
1976 {
1977 }
1978
1979 JS_PUBLIC_API(JSObject *)
JS_InitClass(JSContext * cx,JSObject * obj,JSObject * parent_proto,JSClass * clasp,JSNative constructor,uintN nargs,JSPropertySpec * ps,JSFunctionSpec * fs,JSPropertySpec * static_ps,JSFunctionSpec * static_fs)1980 JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
1981 JSClass *clasp, JSNative constructor, uintN nargs,
1982 JSPropertySpec *ps, JSFunctionSpec *fs,
1983 JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
1984 {
1985 JSAtom *atom;
1986 JSObject *proto, *ctor;
1987 JSBool named;
1988 JSFunction *fun;
1989 jsval junk;
1990
1991 CHECK_REQUEST(cx);
1992 atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
1993 if (!atom)
1994 return NULL;
1995
1996 /* Create a prototype object for this class. */
1997 proto = js_NewObject(cx, clasp, parent_proto, obj);
1998 if (!proto)
1999 return NULL;
2000
2001 if (!constructor) {
2002 /* Lacking a constructor, name the prototype (e.g., Math). */
2003 named = OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, OBJECT_TO_JSVAL(proto),
2004 NULL, NULL, 0, NULL);
2005 if (!named)
2006 goto bad;
2007 ctor = proto;
2008 } else {
2009 /* Define the constructor function in obj's scope. */
2010 fun = js_DefineFunction(cx, obj, atom, constructor, nargs, 0);
2011 named = (fun != NULL);
2012 if (!fun)
2013 goto bad;
2014
2015 /*
2016 * Remember the class this function is a constructor for so that
2017 * we know to create an object of this class when we call the
2018 * constructor.
2019 */
2020 fun->clasp = clasp;
2021
2022 /* Connect constructor and prototype by named properties. */
2023 ctor = fun->object;
2024 if (!js_SetClassPrototype(cx, ctor, proto,
2025 JSPROP_READONLY | JSPROP_PERMANENT)) {
2026 goto bad;
2027 }
2028
2029 /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */
2030 if (OBJ_GET_CLASS(cx, ctor) == clasp) {
2031 /* XXXMLM - this fails in framesets that are writing over
2032 * themselves!
2033 * JS_ASSERT(!OBJ_GET_PROTO(cx, ctor));
2034 */
2035 OBJ_SET_PROTO(cx, ctor, proto);
2036 }
2037 }
2038
2039 /* Add properties and methods to the prototype and the constructor. */
2040 if ((ps && !JS_DefineProperties(cx, proto, ps)) ||
2041 (fs && !JS_DefineFunctions(cx, proto, fs)) ||
2042 (static_ps && !JS_DefineProperties(cx, ctor, static_ps)) ||
2043 (static_fs && !JS_DefineFunctions(cx, ctor, static_fs))) {
2044 goto bad;
2045 }
2046 return proto;
2047
2048 bad:
2049 if (named)
2050 (void) OBJ_DELETE_PROPERTY(cx, obj, (jsid)atom, &junk);
2051 cx->newborn[GCX_OBJECT] = NULL;
2052 return NULL;
2053 }
2054
2055 #ifdef JS_THREADSAFE
2056 JS_PUBLIC_API(JSClass *)
JS_GetClass(JSContext * cx,JSObject * obj)2057 JS_GetClass(JSContext *cx, JSObject *obj)
2058 {
2059 return (JSClass *)
2060 JSVAL_TO_PRIVATE(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_CLASS));
2061 }
2062 #else
2063 JS_PUBLIC_API(JSClass *)
JS_GetClass(JSObject * obj)2064 JS_GetClass(JSObject *obj)
2065 {
2066 return LOCKED_OBJ_GET_CLASS(obj);
2067 }
2068 #endif
2069
2070 JS_PUBLIC_API(JSBool)
JS_InstanceOf(JSContext * cx,JSObject * obj,JSClass * clasp,jsval * argv)2071 JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
2072 {
2073 JSFunction *fun;
2074
2075 CHECK_REQUEST(cx);
2076 if (OBJ_GET_CLASS(cx, obj) == clasp)
2077 return JS_TRUE;
2078 if (argv) {
2079 fun = js_ValueToFunction(cx, &argv[-2], 0);
2080 if (fun) {
2081 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
2082 JSMSG_INCOMPATIBLE_PROTO,
2083 clasp->name, JS_GetFunctionName(fun),
2084 OBJ_GET_CLASS(cx, obj)->name);
2085 }
2086 }
2087 return JS_FALSE;
2088 }
2089
2090 JS_PUBLIC_API(void *)
JS_GetPrivate(JSContext * cx,JSObject * obj)2091 JS_GetPrivate(JSContext *cx, JSObject *obj)
2092 {
2093 jsval v;
2094
2095 JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
2096 v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
2097 if (!JSVAL_IS_INT(v))
2098 return NULL;
2099 return JSVAL_TO_PRIVATE(v);
2100 }
2101
2102 JS_PUBLIC_API(JSBool)
JS_SetPrivate(JSContext * cx,JSObject * obj,void * data)2103 JS_SetPrivate(JSContext *cx, JSObject *obj, void *data)
2104 {
2105 JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
2106 OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(data));
2107 return JS_TRUE;
2108 }
2109
2110 JS_PUBLIC_API(void *)
JS_GetInstancePrivate(JSContext * cx,JSObject * obj,JSClass * clasp,jsval * argv)2111 JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
2112 jsval *argv)
2113 {
2114 if (!JS_InstanceOf(cx, obj, clasp, argv))
2115 return NULL;
2116 return JS_GetPrivate(cx, obj);
2117 }
2118
2119 JS_PUBLIC_API(JSObject *)
JS_GetPrototype(JSContext * cx,JSObject * obj)2120 JS_GetPrototype(JSContext *cx, JSObject *obj)
2121 {
2122 JSObject *proto;
2123
2124 CHECK_REQUEST(cx);
2125 proto = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PROTO));
2126
2127 /* Beware ref to dead object (we may be called from obj's finalizer). */
2128 return proto && proto->map ? proto : NULL;
2129 }
2130
2131 JS_PUBLIC_API(JSBool)
JS_SetPrototype(JSContext * cx,JSObject * obj,JSObject * proto)2132 JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
2133 {
2134 CHECK_REQUEST(cx);
2135 if (obj->map->ops->setProto)
2136 return obj->map->ops->setProto(cx, obj, JSSLOT_PROTO, proto);
2137 OBJ_SET_SLOT(cx, obj, JSSLOT_PROTO, OBJECT_TO_JSVAL(proto));
2138 return JS_TRUE;
2139 }
2140
2141 JS_PUBLIC_API(JSObject *)
JS_GetParent(JSContext * cx,JSObject * obj)2142 JS_GetParent(JSContext *cx, JSObject *obj)
2143 {
2144 JSObject *parent;
2145
2146 parent = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PARENT));
2147
2148 /* Beware ref to dead object (we may be called from obj's finalizer). */
2149 return parent && parent->map ? parent : NULL;
2150 }
2151
2152 JS_PUBLIC_API(JSBool)
JS_SetParent(JSContext * cx,JSObject * obj,JSObject * parent)2153 JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
2154 {
2155 CHECK_REQUEST(cx);
2156 if (obj->map->ops->setParent)
2157 return obj->map->ops->setParent(cx, obj, JSSLOT_PARENT, parent);
2158 OBJ_SET_SLOT(cx, obj, JSSLOT_PARENT, OBJECT_TO_JSVAL(parent));
2159 return JS_TRUE;
2160 }
2161
2162 JS_PUBLIC_API(JSObject *)
JS_GetConstructor(JSContext * cx,JSObject * proto)2163 JS_GetConstructor(JSContext *cx, JSObject *proto)
2164 {
2165 jsval cval;
2166
2167 CHECK_REQUEST(cx);
2168 if (!OBJ_GET_PROPERTY(cx, proto,
2169 (jsid)cx->runtime->atomState.constructorAtom,
2170 &cval)) {
2171 return NULL;
2172 }
2173 if (!JSVAL_IS_FUNCTION(cx, cval)) {
2174 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR,
2175 OBJ_GET_CLASS(cx, proto)->name);
2176 return NULL;
2177 }
2178 return JSVAL_TO_OBJECT(cval);
2179 }
2180
2181 JS_PUBLIC_API(JSBool)
JS_GetObjectId(JSContext * cx,JSObject * obj,jsid * idp)2182 JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
2183 {
2184 JS_ASSERT(((jsid)obj & JSVAL_TAGMASK) == 0);
2185 *idp = (jsid) obj | JSVAL_INT;
2186 return JS_TRUE;
2187 }
2188
2189 JS_PUBLIC_API(JSObject *)
JS_NewObject(JSContext * cx,JSClass * clasp,JSObject * proto,JSObject * parent)2190 JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
2191 {
2192 CHECK_REQUEST(cx);
2193 if (!clasp)
2194 clasp = &js_ObjectClass; /* default class is Object */
2195 return js_NewObject(cx, clasp, proto, parent);
2196 }
2197
2198 JS_PUBLIC_API(JSBool)
JS_SealObject(JSContext * cx,JSObject * obj,JSBool deep)2199 JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep)
2200 {
2201 JSScope *scope;
2202 JSIdArray *ida;
2203 uint32 nslots;
2204 jsval v, *vp, *end;
2205
2206 if (!OBJ_IS_NATIVE(obj)) {
2207 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
2208 JSMSG_CANT_SEAL_OBJECT,
2209 OBJ_GET_CLASS(cx, obj)->name);
2210 return JS_FALSE;
2211 }
2212
2213 scope = OBJ_SCOPE(obj);
2214
2215 #if defined JS_THREADSAFE && defined DEBUG
2216 /* Insist on scope being used exclusively by cx's thread. */
2217 if (scope->ownercx != cx) {
2218 JS_LOCK_OBJ(cx, obj);
2219 JS_ASSERT(OBJ_SCOPE(obj) == scope);
2220 JS_ASSERT(scope->ownercx == cx);
2221 JS_UNLOCK_SCOPE(cx, scope);
2222 }
2223 #endif
2224
2225 /* Nothing to do if obj's scope is already sealed. */
2226 if (SCOPE_IS_SEALED(scope))
2227 return JS_TRUE;
2228
2229 /* XXX Enumerate lazy properties now, as they can't be added later. */
2230 ida = JS_Enumerate(cx, obj);
2231 if (!ida)
2232 return JS_FALSE;
2233 JS_DestroyIdArray(cx, ida);
2234
2235 /* Ensure that obj has its own, mutable scope, and seal that scope. */
2236 JS_LOCK_OBJ(cx, obj);
2237 scope = js_GetMutableScope(cx, obj);
2238 if (scope)
2239 SCOPE_SET_SEALED(scope);
2240 JS_UNLOCK_SCOPE(cx, scope);
2241 if (!scope)
2242 return JS_FALSE;
2243
2244 /* If we are not sealing an entire object graph, we're done. */
2245 if (!deep)
2246 return JS_TRUE;
2247
2248 /* Walk obj->slots and if any value is a non-null object, seal it. */
2249 nslots = JS_MIN(scope->map.freeslot, scope->map.nslots);
2250 for (vp = obj->slots, end = vp + nslots; vp < end; vp++) {
2251 v = *vp;
2252 if (JSVAL_IS_PRIMITIVE(v))
2253 continue;
2254 if (!JS_SealObject(cx, JSVAL_TO_OBJECT(v), deep))
2255 return JS_FALSE;
2256 }
2257 return JS_TRUE;
2258 }
2259
2260 JS_PUBLIC_API(JSObject *)
JS_ConstructObject(JSContext * cx,JSClass * clasp,JSObject * proto,JSObject * parent)2261 JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
2262 JSObject *parent)
2263 {
2264 CHECK_REQUEST(cx);
2265 if (!clasp)
2266 clasp = &js_ObjectClass; /* default class is Object */
2267 return js_ConstructObject(cx, clasp, proto, parent, 0, NULL);
2268 }
2269
2270 JS_PUBLIC_API(JSObject *)
JS_ConstructObjectWithArguments(JSContext * cx,JSClass * clasp,JSObject * proto,JSObject * parent,uintN argc,jsval * argv)2271 JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto,
2272 JSObject *parent, uintN argc, jsval *argv)
2273 {
2274 CHECK_REQUEST(cx);
2275 if (!clasp)
2276 clasp = &js_ObjectClass; /* default class is Object */
2277 return js_ConstructObject(cx, clasp, proto, parent, argc, argv);
2278 }
2279
2280 static JSBool
DefineProperty(JSContext * cx,JSObject * obj,const char * name,jsval value,JSPropertyOp getter,JSPropertyOp setter,uintN attrs,uintN flags,intN tinyid)2281 DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
2282 JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
2283 uintN flags, intN tinyid)
2284 {
2285 jsid id;
2286 JSAtom *atom;
2287
2288 if (attrs & JSPROP_INDEX) {
2289 id = INT_TO_JSVAL((jsint)name);
2290 atom = NULL;
2291 attrs &= ~JSPROP_INDEX;
2292 } else {
2293 atom = js_Atomize(cx, name, strlen(name), 0);
2294 if (!atom)
2295 return JS_FALSE;
2296 id = (jsid)atom;
2297 }
2298 if (flags != 0 && OBJ_IS_NATIVE(obj)) {
2299 return js_DefineNativeProperty(cx, obj, id, value, getter, setter,
2300 attrs, flags, tinyid, NULL);
2301 }
2302 return OBJ_DEFINE_PROPERTY(cx, obj, id, value, getter, setter, attrs,
2303 NULL);
2304 }
2305
2306 #define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
2307
2308 static JSBool
DefineUCProperty(JSContext * cx,JSObject * obj,const jschar * name,size_t namelen,jsval value,JSPropertyOp getter,JSPropertyOp setter,uintN attrs,uintN flags,intN tinyid)2309 DefineUCProperty(JSContext *cx, JSObject *obj,
2310 const jschar *name, size_t namelen, jsval value,
2311 JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
2312 uintN flags, intN tinyid)
2313 {
2314 JSAtom *atom;
2315
2316 atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
2317 if (!atom)
2318 return JS_FALSE;
2319 if (flags != 0 && OBJ_IS_NATIVE(obj)) {
2320 return js_DefineNativeProperty(cx, obj, (jsid)atom, value,
2321 getter, setter, attrs, flags, tinyid,
2322 NULL);
2323 }
2324 return OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, value, getter, setter,
2325 attrs, NULL);
2326 }
2327
2328 JS_PUBLIC_API(JSObject *)
JS_DefineObject(JSContext * cx,JSObject * obj,const char * name,JSClass * clasp,JSObject * proto,uintN attrs)2329 JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
2330 JSObject *proto, uintN attrs)
2331 {
2332 JSObject *nobj;
2333
2334 CHECK_REQUEST(cx);
2335 if (!clasp)
2336 clasp = &js_ObjectClass; /* default class is Object */
2337 nobj = js_NewObject(cx, clasp, proto, obj);
2338 if (!nobj)
2339 return NULL;
2340 if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs,
2341 0, 0)) {
2342 cx->newborn[GCX_OBJECT] = NULL;
2343 return NULL;
2344 }
2345 return nobj;
2346 }
2347
2348 JS_PUBLIC_API(JSBool)
JS_DefineConstDoubles(JSContext * cx,JSObject * obj,JSConstDoubleSpec * cds)2349 JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds)
2350 {
2351 JSBool ok;
2352 jsval value;
2353 uintN flags;
2354
2355 CHECK_REQUEST(cx);
2356 for (ok = JS_TRUE; cds->name; cds++) {
2357 ok = js_NewNumberValue(cx, cds->dval, &value);
2358 if (!ok)
2359 break;
2360 flags = cds->flags;
2361 if (!flags)
2362 flags = JSPROP_READONLY | JSPROP_PERMANENT;
2363 ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, flags, 0, 0);
2364 if (!ok)
2365 break;
2366 }
2367 return ok;
2368 }
2369
2370 JS_PUBLIC_API(JSBool)
JS_DefineProperties(JSContext * cx,JSObject * obj,JSPropertySpec * ps)2371 JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
2372 {
2373 JSBool ok;
2374
2375 CHECK_REQUEST(cx);
2376 for (ok = JS_TRUE; ps->name; ps++) {
2377 ok = DefineProperty(cx, obj, ps->name, JSVAL_VOID,
2378 ps->getter, ps->setter, ps->flags,
2379 SPROP_HAS_SHORTID, ps->tinyid);
2380 if (!ok)
2381 break;
2382 }
2383 return ok;
2384 }
2385
2386 JS_PUBLIC_API(JSBool)
JS_DefineProperty(JSContext * cx,JSObject * obj,const char * name,jsval value,JSPropertyOp getter,JSPropertyOp setter,uintN attrs)2387 JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
2388 JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
2389 {
2390 CHECK_REQUEST(cx);
2391 return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0);
2392 }
2393
2394 JS_PUBLIC_API(JSBool)
JS_DefinePropertyWithTinyId(JSContext * cx,JSObject * obj,const char * name,int8 tinyid,jsval value,JSPropertyOp getter,JSPropertyOp setter,uintN attrs)2395 JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
2396 int8 tinyid, jsval value,
2397 JSPropertyOp getter, JSPropertyOp setter,
2398 uintN attrs)
2399 {
2400 CHECK_REQUEST(cx);
2401 return DefineProperty(cx, obj, name, value, getter, setter, attrs,
2402 SPROP_HAS_SHORTID, tinyid);
2403 }
2404
2405 static JSBool
LookupProperty(JSContext * cx,JSObject * obj,const char * name,JSObject ** objp,JSProperty ** propp)2406 LookupProperty(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
2407 JSProperty **propp)
2408 {
2409 JSAtom *atom;
2410
2411 atom = js_Atomize(cx, name, strlen(name), 0);
2412 if (!atom)
2413 return JS_FALSE;
2414 return OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, objp, propp);
2415 }
2416
2417 static JSBool
LookupUCProperty(JSContext * cx,JSObject * obj,const jschar * name,size_t namelen,JSObject ** objp,JSProperty ** propp)2418 LookupUCProperty(JSContext *cx, JSObject *obj,
2419 const jschar *name, size_t namelen,
2420 JSObject **objp, JSProperty **propp)
2421 {
2422 JSAtom *atom;
2423
2424 atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
2425 if (!atom)
2426 return JS_FALSE;
2427 return OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, objp, propp);
2428 }
2429
2430 JS_PUBLIC_API(JSBool)
JS_AliasProperty(JSContext * cx,JSObject * obj,const char * name,const char * alias)2431 JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
2432 const char *alias)
2433 {
2434 JSObject *obj2;
2435 JSProperty *prop;
2436 JSAtom *atom;
2437 JSBool ok;
2438 JSScopeProperty *sprop;
2439
2440 CHECK_REQUEST(cx);
2441 if (!LookupProperty(cx, obj, name, &obj2, &prop))
2442 return JS_FALSE;
2443 if (!prop) {
2444 js_ReportIsNotDefined(cx, name);
2445 return JS_FALSE;
2446 }
2447 if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
2448 OBJ_DROP_PROPERTY(cx, obj2, prop);
2449 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
2450 alias, name, OBJ_GET_CLASS(cx, obj2)->name);
2451 return JS_FALSE;
2452 }
2453 atom = js_Atomize(cx, alias, strlen(alias), 0);
2454 if (!atom) {
2455 ok = JS_FALSE;
2456 } else {
2457 sprop = (JSScopeProperty *)prop;
2458 ok = (js_AddNativeProperty(cx, obj, (jsid)atom,
2459 sprop->getter, sprop->setter, sprop->slot,
2460 sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
2461 sprop->shortid)
2462 != NULL);
2463 }
2464 OBJ_DROP_PROPERTY(cx, obj, prop);
2465 return ok;
2466 }
2467
2468 static jsval
LookupResult(JSContext * cx,JSObject * obj,JSObject * obj2,JSProperty * prop)2469 LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop)
2470 {
2471 JSScopeProperty *sprop;
2472 jsval rval;
2473
2474 if (!prop) {
2475 /* XXX bad API: no way to tell "not defined" from "void value" */
2476 return JSVAL_VOID;
2477 }
2478 if (OBJ_IS_NATIVE(obj2)) {
2479 /* Peek at the native property's slot value, without doing a Get. */
2480 sprop = (JSScopeProperty *)prop;
2481 rval = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2))
2482 ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot)
2483 : JSVAL_TRUE;
2484 } else {
2485 /* XXX bad API: no way to return "defined but value unknown" */
2486 rval = JSVAL_TRUE;
2487 }
2488 OBJ_DROP_PROPERTY(cx, obj2, prop);
2489 return rval;
2490 }
2491
2492 static JSBool
GetPropertyAttributes(JSContext * cx,JSObject * obj,JSAtom * atom,uintN * attrsp,JSBool * foundp)2493 GetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
2494 uintN *attrsp, JSBool *foundp)
2495 {
2496 JSObject *obj2;
2497 JSProperty *prop;
2498 JSBool ok;
2499
2500 if (!atom)
2501 return JS_FALSE;
2502 if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &obj2, &prop))
2503 return JS_FALSE;
2504 if (!prop || obj != obj2) {
2505 *foundp = JS_FALSE;
2506 if (prop)
2507 OBJ_DROP_PROPERTY(cx, obj2, prop);
2508 return JS_TRUE;
2509 }
2510
2511 *foundp = JS_TRUE;
2512 ok = OBJ_GET_ATTRIBUTES(cx, obj, (jsid)atom, prop, attrsp);
2513 OBJ_DROP_PROPERTY(cx, obj, prop);
2514 return ok;
2515 }
2516
2517 static JSBool
SetPropertyAttributes(JSContext * cx,JSObject * obj,JSAtom * atom,uintN attrs,JSBool * foundp)2518 SetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
2519 uintN attrs, JSBool *foundp)
2520 {
2521 JSObject *obj2;
2522 JSProperty *prop;
2523 JSBool ok;
2524
2525 if (!atom)
2526 return JS_FALSE;
2527 if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &obj2, &prop))
2528 return JS_FALSE;
2529 if (!prop || obj != obj2) {
2530 *foundp = JS_FALSE;
2531 if (prop)
2532 OBJ_DROP_PROPERTY(cx, obj2, prop);
2533 return JS_TRUE;
2534 }
2535
2536 *foundp = JS_TRUE;
2537 ok = OBJ_SET_ATTRIBUTES(cx, obj, (jsid)atom, prop, &attrs);
2538 OBJ_DROP_PROPERTY(cx, obj, prop);
2539 return ok;
2540 }
2541
2542
2543 JS_PUBLIC_API(JSBool)
JS_GetPropertyAttributes(JSContext * cx,JSObject * obj,const char * name,uintN * attrsp,JSBool * foundp)2544 JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
2545 uintN *attrsp, JSBool *foundp)
2546 {
2547 CHECK_REQUEST(cx);
2548 return GetPropertyAttributes(cx, obj,
2549 js_Atomize(cx, name, strlen(name), 0),
2550 attrsp, foundp);
2551 }
2552
2553 JS_PUBLIC_API(JSBool)
JS_SetPropertyAttributes(JSContext * cx,JSObject * obj,const char * name,uintN attrs,JSBool * foundp)2554 JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
2555 uintN attrs, JSBool *foundp)
2556 {
2557 CHECK_REQUEST(cx);
2558 return SetPropertyAttributes(cx, obj,
2559 js_Atomize(cx, name, strlen(name), 0),
2560 attrs, foundp);
2561 }
2562
2563 JS_PUBLIC_API(JSBool)
JS_HasProperty(JSContext * cx,JSObject * obj,const char * name,JSBool * foundp)2564 JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
2565 {
2566 JSBool ok;
2567 JSObject *obj2;
2568 JSProperty *prop;
2569
2570 CHECK_REQUEST(cx);
2571 ok = LookupProperty(cx, obj, name, &obj2, &prop);
2572 if (ok) {
2573 *foundp = (prop != NULL);
2574 if (prop)
2575 OBJ_DROP_PROPERTY(cx, obj2, prop);
2576 }
2577 return ok;
2578 }
2579
2580 JS_PUBLIC_API(JSBool)
JS_LookupProperty(JSContext * cx,JSObject * obj,const char * name,jsval * vp)2581 JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
2582 {
2583 JSBool ok;
2584 JSObject *obj2;
2585 JSProperty *prop;
2586
2587 CHECK_REQUEST(cx);
2588 ok = LookupProperty(cx, obj, name, &obj2, &prop);
2589 if (ok)
2590 *vp = LookupResult(cx, obj, obj2, prop);
2591 return ok;
2592 }
2593
2594 JS_PUBLIC_API(JSBool)
JS_LookupPropertyWithFlags(JSContext * cx,JSObject * obj,const char * name,uintN flags,jsval * vp)2595 JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name,
2596 uintN flags, jsval *vp)
2597 {
2598 JSAtom *atom;
2599 JSBool ok;
2600 JSObject *obj2;
2601 JSProperty *prop;
2602
2603 CHECK_REQUEST(cx);
2604 atom = js_Atomize(cx, name, strlen(name), 0);
2605 if (!atom)
2606 return JS_FALSE;
2607 ok = OBJ_IS_NATIVE(obj)
2608 ? js_LookupPropertyWithFlags(cx, obj, (jsid)atom, flags, &obj2, &prop
2609 #if defined JS_THREADSAFE && defined DEBUG
2610 , __FILE__, __LINE__
2611 #endif
2612 )
2613 : OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &obj2, &prop);
2614 if (ok)
2615 *vp = LookupResult(cx, obj, obj2, prop);
2616 return ok;
2617 }
2618
2619 JS_PUBLIC_API(JSBool)
JS_GetProperty(JSContext * cx,JSObject * obj,const char * name,jsval * vp)2620 JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
2621 {
2622 JSAtom *atom;
2623
2624 CHECK_REQUEST(cx);
2625 atom = js_Atomize(cx, name, strlen(name), 0);
2626 if (!atom)
2627 return JS_FALSE;
2628 return OBJ_GET_PROPERTY(cx, obj, (jsid)atom, vp);
2629 }
2630
2631 JS_PUBLIC_API(JSBool)
JS_SetProperty(JSContext * cx,JSObject * obj,const char * name,jsval * vp)2632 JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
2633 {
2634 JSAtom *atom;
2635
2636 CHECK_REQUEST(cx);
2637 atom = js_Atomize(cx, name, strlen(name), 0);
2638 if (!atom)
2639 return JS_FALSE;
2640 return OBJ_SET_PROPERTY(cx, obj, (jsid)atom, vp);
2641 }
2642
2643 JS_PUBLIC_API(JSBool)
JS_DeleteProperty(JSContext * cx,JSObject * obj,const char * name)2644 JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
2645 {
2646 jsval junk;
2647
2648 CHECK_REQUEST(cx);
2649 return JS_DeleteProperty2(cx, obj, name, &junk);
2650 }
2651
2652 JS_PUBLIC_API(JSBool)
JS_DeleteProperty2(JSContext * cx,JSObject * obj,const char * name,jsval * rval)2653 JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name,
2654 jsval *rval)
2655 {
2656 JSAtom *atom;
2657
2658 CHECK_REQUEST(cx);
2659 atom = js_Atomize(cx, name, strlen(name), 0);
2660 if (!atom)
2661 return JS_FALSE;
2662 return OBJ_DELETE_PROPERTY(cx, obj, (jsid)atom, rval);
2663 }
2664
2665 JS_PUBLIC_API(JSBool)
JS_DefineUCProperty(JSContext * cx,JSObject * obj,const jschar * name,size_t namelen,jsval value,JSPropertyOp getter,JSPropertyOp setter,uintN attrs)2666 JS_DefineUCProperty(JSContext *cx, JSObject *obj,
2667 const jschar *name, size_t namelen, jsval value,
2668 JSPropertyOp getter, JSPropertyOp setter,
2669 uintN attrs)
2670 {
2671 CHECK_REQUEST(cx);
2672 return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
2673 attrs, 0, 0);
2674 }
2675
2676 JS_PUBLIC_API(JSBool)
JS_GetUCPropertyAttributes(JSContext * cx,JSObject * obj,const jschar * name,size_t namelen,uintN * attrsp,JSBool * foundp)2677 JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
2678 const jschar *name, size_t namelen,
2679 uintN *attrsp, JSBool *foundp)
2680 {
2681 CHECK_REQUEST(cx);
2682 return GetPropertyAttributes(cx, obj,
2683 js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
2684 attrsp, foundp);
2685 }
2686
2687 JS_PUBLIC_API(JSBool)
JS_SetUCPropertyAttributes(JSContext * cx,JSObject * obj,const jschar * name,size_t namelen,uintN attrs,JSBool * foundp)2688 JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
2689 const jschar *name, size_t namelen,
2690 uintN attrs, JSBool *foundp)
2691 {
2692 CHECK_REQUEST(cx);
2693 return SetPropertyAttributes(cx, obj,
2694 js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
2695 attrs, foundp);
2696 }
2697
2698 JS_PUBLIC_API(JSBool)
JS_DefineUCPropertyWithTinyId(JSContext * cx,JSObject * obj,const jschar * name,size_t namelen,int8 tinyid,jsval value,JSPropertyOp getter,JSPropertyOp setter,uintN attrs)2699 JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
2700 const jschar *name, size_t namelen,
2701 int8 tinyid, jsval value,
2702 JSPropertyOp getter, JSPropertyOp setter,
2703 uintN attrs)
2704 {
2705 CHECK_REQUEST(cx);
2706 return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
2707 attrs, SPROP_HAS_SHORTID, tinyid);
2708 }
2709
2710 JS_PUBLIC_API(JSBool)
JS_HasUCProperty(JSContext * cx,JSObject * obj,const jschar * name,size_t namelen,JSBool * vp)2711 JS_HasUCProperty(JSContext *cx, JSObject *obj,
2712 const jschar *name, size_t namelen,
2713 JSBool *vp)
2714 {
2715 JSBool ok;
2716 JSObject *obj2;
2717 JSProperty *prop;
2718
2719 CHECK_REQUEST(cx);
2720 ok = LookupUCProperty(cx, obj, name, namelen, &obj2, &prop);
2721 if (ok) {
2722 *vp = (prop != NULL);
2723 if (prop)
2724 OBJ_DROP_PROPERTY(cx, obj2, prop);
2725 }
2726 return ok;
2727 }
2728
2729 JS_PUBLIC_API(JSBool)
JS_LookupUCProperty(JSContext * cx,JSObject * obj,const jschar * name,size_t namelen,jsval * vp)2730 JS_LookupUCProperty(JSContext *cx, JSObject *obj,
2731 const jschar *name, size_t namelen,
2732 jsval *vp)
2733 {
2734 JSBool ok;
2735 JSObject *obj2;
2736 JSProperty *prop;
2737
2738 CHECK_REQUEST(cx);
2739 ok = LookupUCProperty(cx, obj, name, namelen, &obj2, &prop);
2740 if (ok)
2741 *vp = LookupResult(cx, obj, obj2, prop);
2742 return ok;
2743 }
2744
2745 JS_PUBLIC_API(JSBool)
JS_GetUCProperty(JSContext * cx,JSObject * obj,const jschar * name,size_t namelen,jsval * vp)2746 JS_GetUCProperty(JSContext *cx, JSObject *obj,
2747 const jschar *name, size_t namelen,
2748 jsval *vp)
2749 {
2750 JSAtom *atom;
2751
2752 CHECK_REQUEST(cx);
2753 atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
2754 if (!atom)
2755 return JS_FALSE;
2756 return OBJ_GET_PROPERTY(cx, obj, (jsid)atom, vp);
2757 }
2758
2759 JS_PUBLIC_API(JSBool)
JS_SetUCProperty(JSContext * cx,JSObject * obj,const jschar * name,size_t namelen,jsval * vp)2760 JS_SetUCProperty(JSContext *cx, JSObject *obj,
2761 const jschar *name, size_t namelen,
2762 jsval *vp)
2763 {
2764 JSAtom *atom;
2765
2766 CHECK_REQUEST(cx);
2767 atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
2768 if (!atom)
2769 return JS_FALSE;
2770 return OBJ_SET_PROPERTY(cx, obj, (jsid)atom, vp);
2771 }
2772
2773 JS_PUBLIC_API(JSBool)
JS_DeleteUCProperty2(JSContext * cx,JSObject * obj,const jschar * name,size_t namelen,jsval * rval)2774 JS_DeleteUCProperty2(JSContext *cx, JSObject *obj,
2775 const jschar *name, size_t namelen,
2776 jsval *rval)
2777 {
2778 JSAtom *atom;
2779
2780 CHECK_REQUEST(cx);
2781 atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
2782 if (!atom)
2783 return JS_FALSE;
2784 return OBJ_DELETE_PROPERTY(cx, obj, (jsid)atom, rval);
2785 }
2786
2787 JS_PUBLIC_API(JSObject *)
JS_NewArrayObject(JSContext * cx,jsint length,jsval * vector)2788 JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector)
2789 {
2790 CHECK_REQUEST(cx);
2791 /* NB: jsuint cast does ToUint32. */
2792 return js_NewArrayObject(cx, (jsuint)length, vector);
2793 }
2794
2795 JS_PUBLIC_API(JSBool)
JS_IsArrayObject(JSContext * cx,JSObject * obj)2796 JS_IsArrayObject(JSContext *cx, JSObject *obj)
2797 {
2798 return OBJ_GET_CLASS(cx, obj) == &js_ArrayClass;
2799 }
2800
2801 JS_PUBLIC_API(JSBool)
JS_GetArrayLength(JSContext * cx,JSObject * obj,jsuint * lengthp)2802 JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
2803 {
2804 CHECK_REQUEST(cx);
2805 return js_GetLengthProperty(cx, obj, lengthp);
2806 }
2807
2808 JS_PUBLIC_API(JSBool)
JS_SetArrayLength(JSContext * cx,JSObject * obj,jsuint length)2809 JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length)
2810 {
2811 CHECK_REQUEST(cx);
2812 return js_SetLengthProperty(cx, obj, length);
2813 }
2814
2815 JS_PUBLIC_API(JSBool)
JS_HasArrayLength(JSContext * cx,JSObject * obj,jsuint * lengthp)2816 JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
2817 {
2818 CHECK_REQUEST(cx);
2819 return js_HasLengthProperty(cx, obj, lengthp);
2820 }
2821
2822 JS_PUBLIC_API(JSBool)
JS_DefineElement(JSContext * cx,JSObject * obj,jsint index,jsval value,JSPropertyOp getter,JSPropertyOp setter,uintN attrs)2823 JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value,
2824 JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
2825 {
2826 CHECK_REQUEST(cx);
2827 return OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSVAL(index), value,
2828 getter, setter, attrs, NULL);
2829 }
2830
2831 JS_PUBLIC_API(JSBool)
JS_AliasElement(JSContext * cx,JSObject * obj,const char * name,jsint alias)2832 JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
2833 {
2834 JSObject *obj2;
2835 JSProperty *prop;
2836 JSScopeProperty *sprop;
2837 JSBool ok;
2838
2839 CHECK_REQUEST(cx);
2840 if (!LookupProperty(cx, obj, name, &obj2, &prop))
2841 return JS_FALSE;
2842 if (!prop) {
2843 js_ReportIsNotDefined(cx, name);
2844 return JS_FALSE;
2845 }
2846 if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
2847 char numBuf[12];
2848 OBJ_DROP_PROPERTY(cx, obj2, prop);
2849 JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)alias);
2850 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
2851 numBuf, name, OBJ_GET_CLASS(cx, obj2)->name);
2852 return JS_FALSE;
2853 }
2854 sprop = (JSScopeProperty *)prop;
2855 ok = (js_AddNativeProperty(cx, obj, INT_TO_JSVAL(alias),
2856 sprop->getter, sprop->setter, sprop->slot,
2857 sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
2858 sprop->shortid)
2859 != NULL);
2860 OBJ_DROP_PROPERTY(cx, obj, prop);
2861 return ok;
2862 }
2863
2864 JS_PUBLIC_API(JSBool)
JS_HasElement(JSContext * cx,JSObject * obj,jsint index,JSBool * foundp)2865 JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp)
2866 {
2867 JSBool ok;
2868 JSObject *obj2;
2869 JSProperty *prop;
2870
2871 CHECK_REQUEST(cx);
2872 ok = OBJ_LOOKUP_PROPERTY(cx, obj, INT_TO_JSVAL(index), &obj2, &prop);
2873 if (ok) {
2874 *foundp = (prop != NULL);
2875 if (prop)
2876 OBJ_DROP_PROPERTY(cx, obj2, prop);
2877 }
2878 return ok;
2879 }
2880
2881 JS_PUBLIC_API(JSBool)
JS_LookupElement(JSContext * cx,JSObject * obj,jsint index,jsval * vp)2882 JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
2883 {
2884 JSBool ok;
2885 JSObject *obj2;
2886 JSProperty *prop;
2887
2888 CHECK_REQUEST(cx);
2889 ok = OBJ_LOOKUP_PROPERTY(cx, obj, INT_TO_JSVAL(index), &obj2, &prop);
2890 if (ok)
2891 *vp = LookupResult(cx, obj, obj2, prop);
2892 return ok;
2893 }
2894
2895 JS_PUBLIC_API(JSBool)
JS_GetElement(JSContext * cx,JSObject * obj,jsint index,jsval * vp)2896 JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
2897 {
2898 CHECK_REQUEST(cx);
2899 return OBJ_GET_PROPERTY(cx, obj, INT_TO_JSVAL(index), vp);
2900 }
2901
2902 JS_PUBLIC_API(JSBool)
JS_SetElement(JSContext * cx,JSObject * obj,jsint index,jsval * vp)2903 JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
2904 {
2905 CHECK_REQUEST(cx);
2906 return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSVAL(index), vp);
2907 }
2908
2909 JS_PUBLIC_API(JSBool)
JS_DeleteElement(JSContext * cx,JSObject * obj,jsint index)2910 JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index)
2911 {
2912 jsval junk;
2913
2914 CHECK_REQUEST(cx);
2915 return JS_DeleteElement2(cx, obj, index, &junk);
2916 }
2917
2918 JS_PUBLIC_API(JSBool)
JS_DeleteElement2(JSContext * cx,JSObject * obj,jsint index,jsval * rval)2919 JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval)
2920 {
2921 CHECK_REQUEST(cx);
2922 return OBJ_DELETE_PROPERTY(cx, obj, INT_TO_JSVAL(index), rval);
2923 }
2924
2925 JS_PUBLIC_API(void)
JS_ClearScope(JSContext * cx,JSObject * obj)2926 JS_ClearScope(JSContext *cx, JSObject *obj)
2927 {
2928 CHECK_REQUEST(cx);
2929
2930 if (obj->map->ops->clear)
2931 obj->map->ops->clear(cx, obj);
2932 }
2933
2934 JS_PUBLIC_API(JSIdArray *)
JS_Enumerate(JSContext * cx,JSObject * obj)2935 JS_Enumerate(JSContext *cx, JSObject *obj)
2936 {
2937 jsint i, n;
2938 jsval iter_state, num_properties;
2939 jsid id;
2940 JSIdArray *ida;
2941 jsval *vector;
2942
2943 CHECK_REQUEST(cx);
2944
2945 ida = NULL;
2946 iter_state = JSVAL_NULL;
2947
2948 /* Get the number of properties to enumerate. */
2949 if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties))
2950 goto error;
2951 if (!JSVAL_IS_INT(num_properties)) {
2952 JS_ASSERT(0);
2953 goto error;
2954 }
2955
2956 /* Grow as needed if we don't know the exact amount ahead of time. */
2957 n = JSVAL_TO_INT(num_properties);
2958 if (n <= 0)
2959 n = 8;
2960
2961 /* Create an array of jsids large enough to hold all the properties */
2962 ida = js_NewIdArray(cx, n);
2963 if (!ida)
2964 goto error;
2965
2966 i = 0;
2967 vector = &ida->vector[0];
2968 for (;;) {
2969 if (i == ida->length) {
2970 /* Grow length by factor of 1.5 instead of doubling. */
2971 jsint newlen = ida->length + (((jsuint)ida->length + 1) >> 1);
2972 ida = js_GrowIdArray(cx, ida, newlen);
2973 if (!ida)
2974 goto error;
2975 vector = &ida->vector[0];
2976 }
2977
2978 if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &iter_state, &id))
2979 goto error;
2980
2981 /* No more jsid's to enumerate ? */
2982 if (iter_state == JSVAL_NULL)
2983 break;
2984 vector[i++] = id;
2985 }
2986 ida->length = i;
2987 return ida;
2988
2989 error:
2990 if (iter_state != JSVAL_NULL)
2991 OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0);
2992 if (ida)
2993 JS_DestroyIdArray(cx, ida);
2994 return NULL;
2995 }
2996
2997 JS_PUBLIC_API(JSBool)
JS_CheckAccess(JSContext * cx,JSObject * obj,jsid id,JSAccessMode mode,jsval * vp,uintN * attrsp)2998 JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
2999 jsval *vp, uintN *attrsp)
3000 {
3001 CHECK_REQUEST(cx);
3002 return OBJ_CHECK_ACCESS(cx, obj, id, mode, vp, attrsp);
3003 }
3004
3005 JS_PUBLIC_API(JSCheckAccessOp)
JS_SetCheckObjectAccessCallback(JSRuntime * rt,JSCheckAccessOp acb)3006 JS_SetCheckObjectAccessCallback(JSRuntime *rt, JSCheckAccessOp acb)
3007 {
3008 JSCheckAccessOp oldacb;
3009
3010 oldacb = rt->checkObjectAccess;
3011 rt->checkObjectAccess = acb;
3012 return oldacb;
3013 }
3014
3015 static JSBool
ReservedSlotIndexOK(JSContext * cx,JSObject * obj,JSClass * clasp,uint32 index,uint32 limit)3016 ReservedSlotIndexOK(JSContext *cx, JSObject *obj, JSClass *clasp,
3017 uint32 index, uint32 limit)
3018 {
3019 /* Check the computed, possibly per-instance, upper bound. */
3020 if (clasp->reserveSlots)
3021 JS_LOCK_OBJ_VOID(cx, obj, limit += clasp->reserveSlots(cx, obj));
3022 if (index >= limit) {
3023 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
3024 JSMSG_RESERVED_SLOT_RANGE);
3025 return JS_FALSE;
3026 }
3027 return JS_TRUE;
3028 }
3029
3030 JS_PUBLIC_API(JSBool)
JS_GetReservedSlot(JSContext * cx,JSObject * obj,uint32 index,jsval * vp)3031 JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp)
3032 {
3033 JSClass *clasp;
3034 uint32 limit, slot;
3035
3036 CHECK_REQUEST(cx);
3037 clasp = OBJ_GET_CLASS(cx, obj);
3038 limit = JSCLASS_RESERVED_SLOTS(clasp);
3039 if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
3040 return JS_FALSE;
3041 slot = JSSLOT_START(clasp) + index;
3042 *vp = OBJ_GET_REQUIRED_SLOT(cx, obj, slot);
3043 return JS_TRUE;
3044 }
3045
3046 JS_PUBLIC_API(JSBool)
JS_SetReservedSlot(JSContext * cx,JSObject * obj,uint32 index,jsval v)3047 JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
3048 {
3049 JSClass *clasp;
3050 uint32 limit, slot;
3051
3052 CHECK_REQUEST(cx);
3053 clasp = OBJ_GET_CLASS(cx, obj);
3054 limit = JSCLASS_RESERVED_SLOTS(clasp);
3055 if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
3056 return JS_FALSE;
3057 slot = JSSLOT_START(clasp) + index;
3058 return OBJ_SET_REQUIRED_SLOT(cx, obj, slot, v);
3059 }
3060
3061 #ifdef JS_THREADSAFE
3062 JS_PUBLIC_API(jsrefcount)
JS_HoldPrincipals(JSContext * cx,JSPrincipals * principals)3063 JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals)
3064 {
3065 return JS_ATOMIC_INCREMENT(&principals->refcount);
3066 }
3067
3068 JS_PUBLIC_API(jsrefcount)
JS_DropPrincipals(JSContext * cx,JSPrincipals * principals)3069 JS_DropPrincipals(JSContext *cx, JSPrincipals *principals)
3070 {
3071 jsrefcount rc = JS_ATOMIC_DECREMENT(&principals->refcount);
3072 if (rc == 0)
3073 principals->destroy(cx, principals);
3074 return rc;
3075 }
3076 #endif
3077
3078 JS_PUBLIC_API(JSPrincipalsTranscoder)
JS_SetPrincipalsTranscoder(JSRuntime * rt,JSPrincipalsTranscoder px)3079 JS_SetPrincipalsTranscoder(JSRuntime *rt, JSPrincipalsTranscoder px)
3080 {
3081 JSPrincipalsTranscoder oldpx;
3082
3083 oldpx = rt->principalsTranscoder;
3084 rt->principalsTranscoder = px;
3085 return oldpx;
3086 }
3087
3088 JS_PUBLIC_API(JSObjectPrincipalsFinder)
JS_SetObjectPrincipalsFinder(JSContext * cx,JSObjectPrincipalsFinder fop)3089 JS_SetObjectPrincipalsFinder(JSContext *cx, JSObjectPrincipalsFinder fop)
3090 {
3091 JSObjectPrincipalsFinder oldfop;
3092
3093 oldfop = cx->findObjectPrincipals;
3094 cx->findObjectPrincipals = fop;
3095 return oldfop;
3096 }
3097
3098 JS_PUBLIC_API(JSFunction *)
JS_NewFunction(JSContext * cx,JSNative native,uintN nargs,uintN flags,JSObject * parent,const char * name)3099 JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
3100 JSObject *parent, const char *name)
3101 {
3102 JSAtom *atom;
3103
3104 CHECK_REQUEST(cx);
3105
3106 if (!name) {
3107 atom = NULL;
3108 } else {
3109 atom = js_Atomize(cx, name, strlen(name), 0);
3110 if (!atom)
3111 return NULL;
3112 }
3113 return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom);
3114 }
3115
3116 JS_PUBLIC_API(JSObject *)
JS_CloneFunctionObject(JSContext * cx,JSObject * funobj,JSObject * parent)3117 JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
3118 {
3119 CHECK_REQUEST(cx);
3120 if (OBJ_GET_CLASS(cx, funobj) != &js_FunctionClass) {
3121 /* Indicate we cannot clone this object. */
3122 return funobj;
3123 }
3124 return js_CloneFunctionObject(cx, funobj, parent);
3125 }
3126
3127 JS_PUBLIC_API(JSObject *)
JS_GetFunctionObject(JSFunction * fun)3128 JS_GetFunctionObject(JSFunction *fun)
3129 {
3130 return fun->object;
3131 }
3132
3133 JS_PUBLIC_API(const char *)
JS_GetFunctionName(JSFunction * fun)3134 JS_GetFunctionName(JSFunction *fun)
3135 {
3136 return fun->atom
3137 ? JS_GetStringBytes(ATOM_TO_STRING(fun->atom))
3138 : js_anonymous_str;
3139 }
3140
3141 JS_PUBLIC_API(JSString *)
JS_GetFunctionId(JSFunction * fun)3142 JS_GetFunctionId(JSFunction *fun)
3143 {
3144 return fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
3145 }
3146
3147 JS_PUBLIC_API(uintN)
JS_GetFunctionFlags(JSFunction * fun)3148 JS_GetFunctionFlags(JSFunction *fun)
3149 {
3150 return fun->flags;
3151 }
3152
3153 JS_PUBLIC_API(JSBool)
JS_ObjectIsFunction(JSContext * cx,JSObject * obj)3154 JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
3155 {
3156 return OBJ_GET_CLASS(cx, obj) == &js_FunctionClass;
3157 }
3158
3159 JS_PUBLIC_API(JSBool)
JS_DefineFunctions(JSContext * cx,JSObject * obj,JSFunctionSpec * fs)3160 JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
3161 {
3162 JSFunction *fun;
3163
3164 CHECK_REQUEST(cx);
3165 for (; fs->name; fs++) {
3166 fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs,
3167 fs->flags);
3168 if (!fun)
3169 return JS_FALSE;
3170 fun->extra = fs->extra;
3171 }
3172 return JS_TRUE;
3173 }
3174
3175 JS_PUBLIC_API(JSFunction *)
JS_DefineFunction(JSContext * cx,JSObject * obj,const char * name,JSNative call,uintN nargs,uintN attrs)3176 JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
3177 uintN nargs, uintN attrs)
3178 {
3179 JSAtom *atom;
3180
3181 CHECK_REQUEST(cx);
3182 atom = js_Atomize(cx, name, strlen(name), 0);
3183 if (!atom)
3184 return NULL;
3185 return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
3186 }
3187
3188 JS_PUBLIC_API(JSFunction *)
JS_DefineUCFunction(JSContext * cx,JSObject * obj,const jschar * name,size_t namelen,JSNative call,uintN nargs,uintN attrs)3189 JS_DefineUCFunction(JSContext *cx, JSObject *obj,
3190 const jschar *name, size_t namelen, JSNative call,
3191 uintN nargs, uintN attrs)
3192 {
3193 JSAtom *atom;
3194
3195 atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
3196 if (!atom)
3197 return NULL;
3198 return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
3199 }
3200
3201 static JSScript *
CompileTokenStream(JSContext * cx,JSObject * obj,JSTokenStream * ts,void * tempMark,JSBool * eofp)3202 CompileTokenStream(JSContext *cx, JSObject *obj, JSTokenStream *ts,
3203 void *tempMark, JSBool *eofp)
3204 {
3205 JSBool eof;
3206 JSArenaPool codePool, notePool;
3207 JSCodeGenerator cg;
3208 JSScript *script;
3209
3210 CHECK_REQUEST(cx);
3211 eof = JS_FALSE;
3212 JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode));
3213 JS_InitArenaPool(¬ePool, "note", 1024, sizeof(jssrcnote));
3214 if (!js_InitCodeGenerator(cx, &cg, &codePool, ¬ePool,
3215 ts->filename, ts->lineno,
3216 ts->principals)) {
3217 script = NULL;
3218 } else if (!js_CompileTokenStream(cx, obj, ts, &cg)) {
3219 script = NULL;
3220 eof = (ts->flags & TSF_EOF) != 0;
3221 } else {
3222 script = js_NewScriptFromCG(cx, &cg, NULL);
3223 }
3224 if (eofp)
3225 *eofp = eof;
3226 if (!js_CloseTokenStream(cx, ts)) {
3227 if (script)
3228 js_DestroyScript(cx, script);
3229 script = NULL;
3230 }
3231 cg.tempMark = tempMark;
3232 js_FinishCodeGenerator(cx, &cg);
3233 JS_FinishArenaPool(&codePool);
3234 JS_FinishArenaPool(¬ePool);
3235 return script;
3236 }
3237
3238 JS_PUBLIC_API(JSScript *)
JS_CompileScript(JSContext * cx,JSObject * obj,const char * bytes,size_t length,const char * filename,uintN lineno)3239 JS_CompileScript(JSContext *cx, JSObject *obj,
3240 const char *bytes, size_t length,
3241 const char *filename, uintN lineno)
3242 {
3243 jschar *chars;
3244 JSScript *script;
3245
3246 CHECK_REQUEST(cx);
3247 chars = js_InflateString(cx, bytes, length);
3248 if (!chars)
3249 return NULL;
3250 script = JS_CompileUCScript(cx, obj, chars, length, filename, lineno);
3251 JS_free(cx, chars);
3252 return script;
3253 }
3254
3255 JS_PUBLIC_API(JSScript *)
JS_CompileScriptForPrincipals(JSContext * cx,JSObject * obj,JSPrincipals * principals,const char * bytes,size_t length,const char * filename,uintN lineno)3256 JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
3257 JSPrincipals *principals,
3258 const char *bytes, size_t length,
3259 const char *filename, uintN lineno)
3260 {
3261 jschar *chars;
3262 JSScript *script;
3263
3264 CHECK_REQUEST(cx);
3265 chars = js_InflateString(cx, bytes, length);
3266 if (!chars)
3267 return NULL;
3268 script = JS_CompileUCScriptForPrincipals(cx, obj, principals,
3269 chars, length, filename, lineno);
3270 JS_free(cx, chars);
3271 return script;
3272 }
3273
3274 JS_PUBLIC_API(JSScript *)
JS_CompileUCScript(JSContext * cx,JSObject * obj,const jschar * chars,size_t length,const char * filename,uintN lineno)3275 JS_CompileUCScript(JSContext *cx, JSObject *obj,
3276 const jschar *chars, size_t length,
3277 const char *filename, uintN lineno)
3278 {
3279 CHECK_REQUEST(cx);
3280 return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length,
3281 filename, lineno);
3282 }
3283
3284 JS_PUBLIC_API(JSScript *)
JS_CompileUCScriptForPrincipals(JSContext * cx,JSObject * obj,JSPrincipals * principals,const jschar * chars,size_t length,const char * filename,uintN lineno)3285 JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
3286 JSPrincipals *principals,
3287 const jschar *chars, size_t length,
3288 const char *filename, uintN lineno)
3289 {
3290 void *mark;
3291 JSTokenStream *ts;
3292 JSScript *script;
3293
3294 CHECK_REQUEST(cx);
3295 mark = JS_ARENA_MARK(&cx->tempPool);
3296 ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals);
3297 if (!ts)
3298 return NULL;
3299 script = CompileTokenStream(cx, obj, ts, mark, NULL);
3300 #if JS_HAS_EXCEPTIONS
3301 if (!script && !cx->fp)
3302 js_ReportUncaughtException(cx);
3303 #endif
3304 return script;
3305 }
3306
3307 JS_PUBLIC_API(JSBool)
JS_BufferIsCompilableUnit(JSContext * cx,JSObject * obj,const char * bytes,size_t length)3308 JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj,
3309 const char *bytes, size_t length)
3310 {
3311 jschar *chars;
3312 JSBool result;
3313 JSExceptionState *exnState;
3314 void *tempMark;
3315 JSTokenStream *ts;
3316 JSErrorReporter older;
3317
3318 CHECK_REQUEST(cx);
3319 chars = js_InflateString(cx, bytes, length);
3320 if (!chars)
3321 return JS_TRUE;
3322
3323 /*
3324 * Return true on any out-of-memory error, so our caller doesn't try to
3325 * collect more buffered source.
3326 */
3327 result = JS_TRUE;
3328 exnState = JS_SaveExceptionState(cx);
3329 tempMark = JS_ARENA_MARK(&cx->tempPool);
3330 ts = js_NewTokenStream(cx, chars, length, NULL, 0, NULL);
3331 if (ts) {
3332 older = JS_SetErrorReporter(cx, NULL);
3333 if (!js_ParseTokenStream(cx, obj, ts)) {
3334 /*
3335 * We ran into an error. If it was because we ran out of source,
3336 * we return false, so our caller will know to try to collect more
3337 * buffered source.
3338 */
3339 result = (ts->flags & TSF_EOF) == 0;
3340 }
3341
3342 JS_SetErrorReporter(cx, older);
3343 js_CloseTokenStream(cx, ts);
3344 JS_ARENA_RELEASE(&cx->tempPool, tempMark);
3345 }
3346
3347 JS_free(cx, chars);
3348 JS_RestoreExceptionState(cx, exnState);
3349 return result;
3350 }
3351
3352 JS_PUBLIC_API(JSScript *)
JS_CompileFile(JSContext * cx,JSObject * obj,const char * filename)3353 JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename)
3354 {
3355 void *mark;
3356 JSTokenStream *ts;
3357 JSScript *script;
3358
3359 CHECK_REQUEST(cx);
3360 mark = JS_ARENA_MARK(&cx->tempPool);
3361 ts = js_NewFileTokenStream(cx, filename, stdin);
3362 if (!ts)
3363 return NULL;
3364 script = CompileTokenStream(cx, obj, ts, mark, NULL);
3365 #if JS_HAS_EXCEPTIONS
3366 if (!script && !cx->fp)
3367 js_ReportUncaughtException(cx);
3368 #endif
3369 return script;
3370 }
3371
3372 JS_PUBLIC_API(JSScript *)
JS_CompileFileHandle(JSContext * cx,JSObject * obj,const char * filename,FILE * file)3373 JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename,
3374 FILE *file)
3375 {
3376 return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, NULL);
3377 }
3378
3379 JS_PUBLIC_API(JSScript *)
JS_CompileFileHandleForPrincipals(JSContext * cx,JSObject * obj,const char * filename,FILE * file,JSPrincipals * principals)3380 JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj,
3381 const char *filename, FILE *file,
3382 JSPrincipals *principals)
3383 {
3384 void *mark;
3385 JSTokenStream *ts;
3386 JSScript *script;
3387
3388 CHECK_REQUEST(cx);
3389 mark = JS_ARENA_MARK(&cx->tempPool);
3390 ts = js_NewFileTokenStream(cx, NULL, file);
3391 if (!ts)
3392 return NULL;
3393 ts->filename = filename;
3394 /* XXXshaver js_NewFileTokenStream should do this, because it drops */
3395 if (principals) {
3396 ts->principals = principals;
3397 JSPRINCIPALS_HOLD(cx, ts->principals);
3398 }
3399 script = CompileTokenStream(cx, obj, ts, mark, NULL);
3400 #if JS_HAS_EXCEPTIONS
3401 if (!script && !cx->fp)
3402 js_ReportUncaughtException(cx);
3403 #endif
3404 return script;
3405 }
3406
3407 JS_PUBLIC_API(JSObject *)
JS_NewScriptObject(JSContext * cx,JSScript * script)3408 JS_NewScriptObject(JSContext *cx, JSScript *script)
3409 {
3410 JSObject *obj;
3411
3412 obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
3413 if (!obj)
3414 return NULL;
3415
3416 if (script) {
3417 if (!JS_SetPrivate(cx, obj, script))
3418 return NULL;
3419 script->object = obj;
3420 }
3421 return obj;
3422 }
3423
3424 JS_PUBLIC_API(JSObject *)
JS_GetScriptObject(JSScript * script)3425 JS_GetScriptObject(JSScript *script)
3426 {
3427 return script->object;
3428 }
3429
3430 JS_PUBLIC_API(void)
JS_DestroyScript(JSContext * cx,JSScript * script)3431 JS_DestroyScript(JSContext *cx, JSScript *script)
3432 {
3433 CHECK_REQUEST(cx);
3434 js_DestroyScript(cx, script);
3435 }
3436
3437 JS_PUBLIC_API(JSFunction *)
JS_CompileFunction(JSContext * cx,JSObject * obj,const char * name,uintN nargs,const char ** argnames,const char * bytes,size_t length,const char * filename,uintN lineno)3438 JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
3439 uintN nargs, const char **argnames,
3440 const char *bytes, size_t length,
3441 const char *filename, uintN lineno)
3442 {
3443 jschar *chars;
3444 JSFunction *fun;
3445
3446 CHECK_REQUEST(cx);
3447 chars = js_InflateString(cx, bytes, length);
3448 if (!chars)
3449 return NULL;
3450 fun = JS_CompileUCFunction(cx, obj, name, nargs, argnames, chars, length,
3451 filename, lineno);
3452 JS_free(cx, chars);
3453 return fun;
3454 }
3455
3456 JS_PUBLIC_API(JSFunction *)
JS_CompileFunctionForPrincipals(JSContext * cx,JSObject * obj,JSPrincipals * principals,const char * name,uintN nargs,const char ** argnames,const char * bytes,size_t length,const char * filename,uintN lineno)3457 JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
3458 JSPrincipals *principals, const char *name,
3459 uintN nargs, const char **argnames,
3460 const char *bytes, size_t length,
3461 const char *filename, uintN lineno)
3462 {
3463 jschar *chars;
3464 JSFunction *fun;
3465
3466 CHECK_REQUEST(cx);
3467 chars = js_InflateString(cx, bytes, length);
3468 if (!chars)
3469 return NULL;
3470 fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name,
3471 nargs, argnames, chars, length,
3472 filename, lineno);
3473 JS_free(cx, chars);
3474 return fun;
3475 }
3476
3477 JS_PUBLIC_API(JSFunction *)
JS_CompileUCFunction(JSContext * cx,JSObject * obj,const char * name,uintN nargs,const char ** argnames,const jschar * chars,size_t length,const char * filename,uintN lineno)3478 JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
3479 uintN nargs, const char **argnames,
3480 const jschar *chars, size_t length,
3481 const char *filename, uintN lineno)
3482 {
3483 CHECK_REQUEST(cx);
3484 return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name,
3485 nargs, argnames,
3486 chars, length,
3487 filename, lineno);
3488 }
3489
3490 JS_PUBLIC_API(JSFunction *)
JS_CompileUCFunctionForPrincipals(JSContext * cx,JSObject * obj,JSPrincipals * principals,const char * name,uintN nargs,const char ** argnames,const jschar * chars,size_t length,const char * filename,uintN lineno)3491 JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
3492 JSPrincipals *principals, const char *name,
3493 uintN nargs, const char **argnames,
3494 const jschar *chars, size_t length,
3495 const char *filename, uintN lineno)
3496 {
3497 void *mark;
3498 JSTokenStream *ts;
3499 JSFunction *fun;
3500 JSAtom *funAtom, *argAtom;
3501 uintN i;
3502
3503 CHECK_REQUEST(cx);
3504 mark = JS_ARENA_MARK(&cx->tempPool);
3505 ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals);
3506 if (!ts) {
3507 fun = NULL;
3508 goto out;
3509 }
3510 if (!name) {
3511 funAtom = NULL;
3512 } else {
3513 funAtom = js_Atomize(cx, name, strlen(name), 0);
3514 if (!funAtom) {
3515 fun = NULL;
3516 goto out;
3517 }
3518 }
3519 fun = js_NewFunction(cx, NULL, NULL, nargs, 0, obj, funAtom);
3520 if (!fun)
3521 goto out;
3522 if (nargs) {
3523 for (i = 0; i < nargs; i++) {
3524 argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0);
3525 if (!argAtom)
3526 break;
3527 if (!js_AddNativeProperty(cx, fun->object, (jsid)argAtom,
3528 js_GetArgument, js_SetArgument,
3529 SPROP_INVALID_SLOT,
3530 JSPROP_ENUMERATE | JSPROP_PERMANENT |
3531 JSPROP_SHARED,
3532 SPROP_HAS_SHORTID, i)) {
3533 break;
3534 }
3535 }
3536 if (i < nargs) {
3537 fun = NULL;
3538 goto out;
3539 }
3540 }
3541 if (!js_CompileFunctionBody(cx, ts, fun)) {
3542 fun = NULL;
3543 goto out;
3544 }
3545 if (obj && funAtom) {
3546 if (!OBJ_DEFINE_PROPERTY(cx, obj, (jsid)funAtom,
3547 OBJECT_TO_JSVAL(fun->object),
3548 NULL, NULL, 0, NULL)) {
3549 return NULL;
3550 }
3551 }
3552 out:
3553 if (ts)
3554 js_CloseTokenStream(cx, ts);
3555 JS_ARENA_RELEASE(&cx->tempPool, mark);
3556 #if JS_HAS_EXCEPTIONS
3557 if (!fun && !cx->fp)
3558 js_ReportUncaughtException(cx);
3559 #endif
3560 return fun;
3561 }
3562
3563 JS_PUBLIC_API(JSString *)
JS_DecompileScript(JSContext * cx,JSScript * script,const char * name,uintN indent)3564 JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
3565 uintN indent)
3566 {
3567 JSPrinter *jp;
3568 JSString *str;
3569
3570 CHECK_REQUEST(cx);
3571 jp = js_NewPrinter(cx, name,
3572 indent & ~JS_DONT_PRETTY_PRINT,
3573 !(indent & JS_DONT_PRETTY_PRINT));
3574 if (!jp)
3575 return NULL;
3576 if (js_DecompileScript(jp, script))
3577 str = js_GetPrinterOutput(jp);
3578 else
3579 str = NULL;
3580 js_DestroyPrinter(jp);
3581 return str;
3582 }
3583
3584 JS_PUBLIC_API(JSString *)
JS_DecompileFunction(JSContext * cx,JSFunction * fun,uintN indent)3585 JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent)
3586 {
3587 JSPrinter *jp;
3588 JSString *str;
3589
3590 CHECK_REQUEST(cx);
3591 jp = js_NewPrinter(cx, JS_GetFunctionName(fun),
3592 indent & ~JS_DONT_PRETTY_PRINT,
3593 !(indent & JS_DONT_PRETTY_PRINT));
3594 if (!jp)
3595 return NULL;
3596 if (js_DecompileFunction(jp, fun))
3597 str = js_GetPrinterOutput(jp);
3598 else
3599 str = NULL;
3600 js_DestroyPrinter(jp);
3601 return str;
3602 }
3603
3604 JS_PUBLIC_API(JSString *)
JS_DecompileFunctionBody(JSContext * cx,JSFunction * fun,uintN indent)3605 JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent)
3606 {
3607 JSPrinter *jp;
3608 JSString *str;
3609
3610 CHECK_REQUEST(cx);
3611 jp = js_NewPrinter(cx, JS_GetFunctionName(fun),
3612 indent & ~JS_DONT_PRETTY_PRINT,
3613 !(indent & JS_DONT_PRETTY_PRINT));
3614 if (!jp)
3615 return NULL;
3616 if (js_DecompileFunctionBody(jp, fun))
3617 str = js_GetPrinterOutput(jp);
3618 else
3619 str = NULL;
3620 js_DestroyPrinter(jp);
3621 return str;
3622 }
3623
3624 JS_PUBLIC_API(JSBool)
JS_ExecuteScript(JSContext * cx,JSObject * obj,JSScript * script,jsval * rval)3625 JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval)
3626 {
3627 CHECK_REQUEST(cx);
3628 if (!js_Execute(cx, obj, script, NULL, 0, rval)) {
3629 #if JS_HAS_EXCEPTIONS
3630 if (!cx->fp)
3631 js_ReportUncaughtException(cx);
3632 #endif
3633 return JS_FALSE;
3634 }
3635 return JS_TRUE;
3636 }
3637
3638 JS_PUBLIC_API(JSBool)
JS_ExecuteScriptPart(JSContext * cx,JSObject * obj,JSScript * script,JSExecPart part,jsval * rval)3639 JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script,
3640 JSExecPart part, jsval *rval)
3641 {
3642 JSScript tmp;
3643 JSRuntime *rt;
3644 JSBool ok;
3645
3646 /* Make a temporary copy of the JSScript structure and farble it a bit. */
3647 tmp = *script;
3648 if (part == JSEXEC_PROLOG) {
3649 tmp.length = PTRDIFF(tmp.main, tmp.code, jsbytecode);
3650 } else {
3651 tmp.length -= PTRDIFF(tmp.main, tmp.code, jsbytecode);
3652 tmp.code = tmp.main;
3653 }
3654
3655 /* Tell the debugger about our temporary copy of the script structure. */
3656 rt = cx->runtime;
3657 if (rt->newScriptHook) {
3658 rt->newScriptHook(cx, tmp.filename, tmp.lineno, &tmp, NULL,
3659 rt->newScriptHookData);
3660 }
3661
3662 /* Execute the farbled struct and tell the debugger to forget about it. */
3663 ok = JS_ExecuteScript(cx, obj, &tmp, rval);
3664 if (rt->destroyScriptHook)
3665 rt->destroyScriptHook(cx, &tmp, rt->destroyScriptHookData);
3666 return ok;
3667 }
3668
3669 JS_PUBLIC_API(JSBool)
JS_EvaluateScript(JSContext * cx,JSObject * obj,const char * bytes,uintN length,const char * filename,uintN lineno,jsval * rval)3670 JS_EvaluateScript(JSContext *cx, JSObject *obj,
3671 const char *bytes, uintN length,
3672 const char *filename, uintN lineno,
3673 jsval *rval)
3674 {
3675 jschar *chars;
3676 JSBool ok;
3677
3678 CHECK_REQUEST(cx);
3679 chars = js_InflateString(cx, bytes, length);
3680 if (!chars)
3681 return JS_FALSE;
3682 ok = JS_EvaluateUCScript(cx, obj, chars, length, filename, lineno, rval);
3683 JS_free(cx, chars);
3684 return ok;
3685 }
3686
3687 JS_PUBLIC_API(JSBool)
JS_EvaluateScriptForPrincipals(JSContext * cx,JSObject * obj,JSPrincipals * principals,const char * bytes,uintN length,const char * filename,uintN lineno,jsval * rval)3688 JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj,
3689 JSPrincipals *principals,
3690 const char *bytes, uintN length,
3691 const char *filename, uintN lineno,
3692 jsval *rval)
3693 {
3694 jschar *chars;
3695 JSBool ok;
3696
3697 CHECK_REQUEST(cx);
3698 chars = js_InflateString(cx, bytes, length);
3699 if (!chars)
3700 return JS_FALSE;
3701 ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length,
3702 filename, lineno, rval);
3703 JS_free(cx, chars);
3704 return ok;
3705 }
3706
3707 JS_PUBLIC_API(JSBool)
JS_EvaluateUCScript(JSContext * cx,JSObject * obj,const jschar * chars,uintN length,const char * filename,uintN lineno,jsval * rval)3708 JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
3709 const jschar *chars, uintN length,
3710 const char *filename, uintN lineno,
3711 jsval *rval)
3712 {
3713 CHECK_REQUEST(cx);
3714 return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length,
3715 filename, lineno, rval);
3716 }
3717
3718 JS_PUBLIC_API(JSBool)
JS_EvaluateUCScriptForPrincipals(JSContext * cx,JSObject * obj,JSPrincipals * principals,const jschar * chars,uintN length,const char * filename,uintN lineno,jsval * rval)3719 JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
3720 JSPrincipals *principals,
3721 const jschar *chars, uintN length,
3722 const char *filename, uintN lineno,
3723 jsval *rval)
3724 {
3725 uint32 options;
3726 JSScript *script;
3727 JSBool ok;
3728
3729 CHECK_REQUEST(cx);
3730 options = cx->options;
3731 cx->options = options | JSOPTION_COMPILE_N_GO;
3732 script = JS_CompileUCScriptForPrincipals(cx, obj, principals, chars, length,
3733 filename, lineno);
3734 cx->options = options;
3735 if (!script)
3736 return JS_FALSE;
3737 ok = js_Execute(cx, obj, script, NULL, 0, rval);
3738 #if JS_HAS_EXCEPTIONS
3739 if (!ok && !cx->fp)
3740 js_ReportUncaughtException(cx);
3741 #endif
3742 JS_DestroyScript(cx, script);
3743 return ok;
3744 }
3745
3746 JS_PUBLIC_API(JSBool)
JS_CallFunction(JSContext * cx,JSObject * obj,JSFunction * fun,uintN argc,jsval * argv,jsval * rval)3747 JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
3748 jsval *argv, jsval *rval)
3749 {
3750 CHECK_REQUEST(cx);
3751 if (!js_InternalCall(cx, obj, OBJECT_TO_JSVAL(fun->object), argc, argv,
3752 rval)) {
3753 #if JS_HAS_EXCEPTIONS
3754 if (!cx->fp)
3755 js_ReportUncaughtException(cx);
3756 #endif
3757 return JS_FALSE;
3758 }
3759 return JS_TRUE;
3760 }
3761
3762 JS_PUBLIC_API(JSBool)
JS_CallFunctionName(JSContext * cx,JSObject * obj,const char * name,uintN argc,jsval * argv,jsval * rval)3763 JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,
3764 jsval *argv, jsval *rval)
3765 {
3766 jsval fval;
3767
3768 CHECK_REQUEST(cx);
3769 if (!JS_GetProperty(cx, obj, name, &fval))
3770 return JS_FALSE;
3771 if (!js_InternalCall(cx, obj, fval, argc, argv, rval)) {
3772 #if JS_HAS_EXCEPTIONS
3773 if (!cx->fp)
3774 js_ReportUncaughtException(cx);
3775 #endif
3776 return JS_FALSE;
3777 }
3778 return JS_TRUE;
3779 }
3780
3781 JS_PUBLIC_API(JSBool)
JS_CallFunctionValue(JSContext * cx,JSObject * obj,jsval fval,uintN argc,jsval * argv,jsval * rval)3782 JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
3783 jsval *argv, jsval *rval)
3784 {
3785 CHECK_REQUEST(cx);
3786 if (!js_InternalCall(cx, obj, fval, argc, argv, rval)) {
3787 #if JS_HAS_EXCEPTIONS
3788 if (!cx->fp)
3789 js_ReportUncaughtException(cx);
3790 #endif
3791 return JS_FALSE;
3792 }
3793 return JS_TRUE;
3794 }
3795
3796 JS_PUBLIC_API(JSBranchCallback)
JS_SetBranchCallback(JSContext * cx,JSBranchCallback cb)3797 JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb)
3798 {
3799 JSBranchCallback oldcb;
3800
3801 oldcb = cx->branchCallback;
3802 cx->branchCallback = cb;
3803 return oldcb;
3804 }
3805
3806 JS_PUBLIC_API(JSBool)
JS_IsRunning(JSContext * cx)3807 JS_IsRunning(JSContext *cx)
3808 {
3809 return cx->fp != NULL;
3810 }
3811
3812 JS_PUBLIC_API(JSBool)
JS_IsConstructing(JSContext * cx)3813 JS_IsConstructing(JSContext *cx)
3814 {
3815 return cx->fp && (cx->fp->flags & JSFRAME_CONSTRUCTING);
3816 }
3817
3818 JS_FRIEND_API(JSBool)
JS_IsAssigning(JSContext * cx)3819 JS_IsAssigning(JSContext *cx)
3820 {
3821 JSStackFrame *fp;
3822 jsbytecode *pc;
3823
3824 for (fp = cx->fp; fp && !fp->script; fp = fp->down)
3825 continue;
3826 if (!fp || !(pc = fp->pc))
3827 return JS_FALSE;
3828 return (js_CodeSpec[*pc].format & JOF_ASSIGNING) != 0;
3829 }
3830
3831 JS_PUBLIC_API(void)
JS_SetCallReturnValue2(JSContext * cx,jsval v)3832 JS_SetCallReturnValue2(JSContext *cx, jsval v)
3833 {
3834 #if JS_HAS_LVALUE_RETURN
3835 cx->rval2 = v;
3836 cx->rval2set = JS_TRUE;
3837 #endif
3838 }
3839
3840 /************************************************************************/
3841
3842 JS_PUBLIC_API(JSString *)
JS_NewString(JSContext * cx,char * bytes,size_t length)3843 JS_NewString(JSContext *cx, char *bytes, size_t length)
3844 {
3845 jschar *chars;
3846 JSString *str;
3847
3848 CHECK_REQUEST(cx);
3849 /* Make a Unicode vector from the 8-bit char codes in bytes. */
3850 chars = js_InflateString(cx, bytes, length);
3851 if (!chars)
3852 return NULL;
3853
3854 /* Free chars (but not bytes, which caller frees on error) if we fail. */
3855 str = js_NewString(cx, chars, length, 0);
3856 if (!str) {
3857 JS_free(cx, chars);
3858 return NULL;
3859 }
3860
3861 /* Hand off bytes to the deflated string cache, if possible. */
3862 if (!js_SetStringBytes(str, bytes, length))
3863 JS_free(cx, bytes);
3864 return str;
3865 }
3866
3867 JS_PUBLIC_API(JSString *)
JS_NewStringCopyN(JSContext * cx,const char * s,size_t n)3868 JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
3869 {
3870 jschar *js;
3871 JSString *str;
3872
3873 CHECK_REQUEST(cx);
3874 js = js_InflateString(cx, s, n);
3875 if (!js)
3876 return NULL;
3877 str = js_NewString(cx, js, n, 0);
3878 if (!str)
3879 JS_free(cx, js);
3880 return str;
3881 }
3882
3883 JS_PUBLIC_API(JSString *)
JS_NewStringCopyZ(JSContext * cx,const char * s)3884 JS_NewStringCopyZ(JSContext *cx, const char *s)
3885 {
3886 size_t n;
3887 jschar *js;
3888 JSString *str;
3889
3890 CHECK_REQUEST(cx);
3891 if (!s)
3892 return cx->runtime->emptyString;
3893 n = strlen(s);
3894 js = js_InflateString(cx, s, n);
3895 if (!js)
3896 return NULL;
3897 str = js_NewString(cx, js, n, 0);
3898 if (!str)
3899 JS_free(cx, js);
3900 return str;
3901 }
3902
3903 JS_PUBLIC_API(JSString *)
JS_InternString(JSContext * cx,const char * s)3904 JS_InternString(JSContext *cx, const char *s)
3905 {
3906 JSAtom *atom;
3907
3908 CHECK_REQUEST(cx);
3909 atom = js_Atomize(cx, s, strlen(s), ATOM_INTERNED);
3910 if (!atom)
3911 return NULL;
3912 return ATOM_TO_STRING(atom);
3913 }
3914
3915 JS_PUBLIC_API(JSString *)
JS_NewUCString(JSContext * cx,jschar * chars,size_t length)3916 JS_NewUCString(JSContext *cx, jschar *chars, size_t length)
3917 {
3918 CHECK_REQUEST(cx);
3919 return js_NewString(cx, chars, length, 0);
3920 }
3921
3922 JS_PUBLIC_API(JSString *)
JS_NewUCStringCopyN(JSContext * cx,const jschar * s,size_t n)3923 JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n)
3924 {
3925 CHECK_REQUEST(cx);
3926 return js_NewStringCopyN(cx, s, n, 0);
3927 }
3928
3929 JS_PUBLIC_API(JSString *)
JS_NewUCStringCopyZ(JSContext * cx,const jschar * s)3930 JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
3931 {
3932 CHECK_REQUEST(cx);
3933 if (!s)
3934 return cx->runtime->emptyString;
3935 return js_NewStringCopyZ(cx, s, 0);
3936 }
3937
3938 JS_PUBLIC_API(JSString *)
JS_InternUCStringN(JSContext * cx,const jschar * s,size_t length)3939 JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
3940 {
3941 JSAtom *atom;
3942
3943 CHECK_REQUEST(cx);
3944 atom = js_AtomizeChars(cx, s, length, ATOM_INTERNED);
3945 if (!atom)
3946 return NULL;
3947 return ATOM_TO_STRING(atom);
3948 }
3949
3950 JS_PUBLIC_API(JSString *)
JS_InternUCString(JSContext * cx,const jschar * s)3951 JS_InternUCString(JSContext *cx, const jschar *s)
3952 {
3953 return JS_InternUCStringN(cx, s, js_strlen(s));
3954 }
3955
3956 JS_PUBLIC_API(char *)
JS_GetStringBytes(JSString * str)3957 JS_GetStringBytes(JSString *str)
3958 {
3959 char *bytes;
3960
3961 bytes = js_GetStringBytes(str);
3962 return bytes ? bytes : "";
3963 }
3964
3965 JS_PUBLIC_API(jschar *)
JS_GetStringChars(JSString * str)3966 JS_GetStringChars(JSString *str)
3967 {
3968 /*
3969 * API botch (again, shades of JS_GetStringBytes): we have no cx to pass
3970 * to js_UndependString (called by js_GetStringChars) for out-of-memory
3971 * error reports, so js_UndependString passes NULL and suppresses errors.
3972 * If it fails to convert a dependent string into an independent one, our
3973 * caller will not be guaranteed a \u0000 terminator as a backstop. This
3974 * may break some clients who already misbehave on embedded NULs.
3975 *
3976 * The gain of dependent strings, which cure quadratic and cubic growth
3977 * rate bugs in string concatenation, is worth this slight loss in API
3978 * compatibility.
3979 */
3980 jschar *chars;
3981
3982 chars = js_GetStringChars(str);
3983 return chars ? chars : JSSTRING_CHARS(str);
3984 }
3985
3986 JS_PUBLIC_API(size_t)
JS_GetStringLength(JSString * str)3987 JS_GetStringLength(JSString *str)
3988 {
3989 return JSSTRING_LENGTH(str);
3990 }
3991
3992 JS_PUBLIC_API(intN)
JS_CompareStrings(JSString * str1,JSString * str2)3993 JS_CompareStrings(JSString *str1, JSString *str2)
3994 {
3995 return js_CompareStrings(str1, str2);
3996 }
3997
3998 JS_PUBLIC_API(JSString *)
JS_NewGrowableString(JSContext * cx,jschar * chars,size_t length)3999 JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length)
4000 {
4001 CHECK_REQUEST(cx);
4002 return js_NewString(cx, chars, length, GCF_MUTABLE);
4003 }
4004
4005 JS_PUBLIC_API(JSString *)
JS_NewDependentString(JSContext * cx,JSString * str,size_t start,size_t length)4006 JS_NewDependentString(JSContext *cx, JSString *str, size_t start,
4007 size_t length)
4008 {
4009 CHECK_REQUEST(cx);
4010 return js_NewDependentString(cx, str, start, length, 0);
4011 }
4012
4013 JS_PUBLIC_API(JSString *)
JS_ConcatStrings(JSContext * cx,JSString * left,JSString * right)4014 JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
4015 {
4016 CHECK_REQUEST(cx);
4017 return js_ConcatStrings(cx, left, right);
4018 }
4019
4020 JS_PUBLIC_API(const jschar *)
JS_UndependString(JSContext * cx,JSString * str)4021 JS_UndependString(JSContext *cx, JSString *str)
4022 {
4023 CHECK_REQUEST(cx);
4024 return js_UndependString(cx, str);
4025 }
4026
4027 JS_PUBLIC_API(JSBool)
JS_MakeStringImmutable(JSContext * cx,JSString * str)4028 JS_MakeStringImmutable(JSContext *cx, JSString *str)
4029 {
4030 CHECK_REQUEST(cx);
4031 if (!js_UndependString(cx, str))
4032 return JS_FALSE;
4033
4034 *js_GetGCThingFlags(str) &= ~GCF_MUTABLE;
4035 return JS_TRUE;
4036 }
4037
4038 /************************************************************************/
4039
4040 JS_PUBLIC_API(void)
JS_ReportError(JSContext * cx,const char * format,...)4041 JS_ReportError(JSContext *cx, const char *format, ...)
4042 {
4043 va_list ap;
4044
4045 va_start(ap, format);
4046 js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap);
4047 va_end(ap);
4048 }
4049
4050 JS_PUBLIC_API(void)
JS_ReportErrorNumber(JSContext * cx,JSErrorCallback errorCallback,void * userRef,const uintN errorNumber,...)4051 JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
4052 void *userRef, const uintN errorNumber, ...)
4053 {
4054 va_list ap;
4055
4056 va_start(ap, errorNumber);
4057 js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
4058 errorNumber, JS_TRUE, ap);
4059 va_end(ap);
4060 }
4061
4062 JS_PUBLIC_API(void)
JS_ReportErrorNumberUC(JSContext * cx,JSErrorCallback errorCallback,void * userRef,const uintN errorNumber,...)4063 JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
4064 void *userRef, const uintN errorNumber, ...)
4065 {
4066 va_list ap;
4067
4068 va_start(ap, errorNumber);
4069 js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
4070 errorNumber, JS_FALSE, ap);
4071 va_end(ap);
4072 }
4073
4074 JS_PUBLIC_API(JSBool)
JS_ReportWarning(JSContext * cx,const char * format,...)4075 JS_ReportWarning(JSContext *cx, const char *format, ...)
4076 {
4077 va_list ap;
4078 JSBool ok;
4079
4080 va_start(ap, format);
4081 ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap);
4082 va_end(ap);
4083 return ok;
4084 }
4085
4086 JS_PUBLIC_API(JSBool)
JS_ReportErrorFlagsAndNumber(JSContext * cx,uintN flags,JSErrorCallback errorCallback,void * userRef,const uintN errorNumber,...)4087 JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags,
4088 JSErrorCallback errorCallback, void *userRef,
4089 const uintN errorNumber, ...)
4090 {
4091 va_list ap;
4092 JSBool ok;
4093
4094 va_start(ap, errorNumber);
4095 ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
4096 errorNumber, JS_TRUE, ap);
4097 va_end(ap);
4098 return ok;
4099 }
4100
4101 JS_PUBLIC_API(JSBool)
JS_ReportErrorFlagsAndNumberUC(JSContext * cx,uintN flags,JSErrorCallback errorCallback,void * userRef,const uintN errorNumber,...)4102 JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags,
4103 JSErrorCallback errorCallback, void *userRef,
4104 const uintN errorNumber, ...)
4105 {
4106 va_list ap;
4107 JSBool ok;
4108
4109 va_start(ap, errorNumber);
4110 ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
4111 errorNumber, JS_FALSE, ap);
4112 va_end(ap);
4113 return ok;
4114 }
4115
4116 JS_PUBLIC_API(void)
JS_ReportOutOfMemory(JSContext * cx)4117 JS_ReportOutOfMemory(JSContext *cx)
4118 {
4119 js_ReportOutOfMemory(cx, js_GetErrorMessage);
4120 }
4121
4122 JS_PUBLIC_API(JSErrorReporter)
JS_SetErrorReporter(JSContext * cx,JSErrorReporter er)4123 JS_SetErrorReporter(JSContext *cx, JSErrorReporter er)
4124 {
4125 JSErrorReporter older;
4126
4127 older = cx->errorReporter;
4128 cx->errorReporter = er;
4129 return older;
4130 }
4131
4132 /************************************************************************/
4133
4134 /*
4135 * Regular Expressions.
4136 */
4137 JS_PUBLIC_API(JSObject *)
JS_NewRegExpObject(JSContext * cx,char * bytes,size_t length,uintN flags)4138 JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags)
4139 {
4140 #if JS_HAS_REGEXPS
4141 jschar *chars;
4142 JSObject *obj;
4143
4144 CHECK_REQUEST(cx);
4145 chars = js_InflateString(cx, bytes, length);
4146 if (!chars)
4147 return NULL;
4148 obj = js_NewRegExpObject(cx, NULL, chars, length, flags);
4149 JS_free(cx, chars);
4150 return obj;
4151 #else
4152 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_REG_EXPS);
4153 return NULL;
4154 #endif
4155 }
4156
4157 JS_PUBLIC_API(JSObject *)
JS_NewUCRegExpObject(JSContext * cx,jschar * chars,size_t length,uintN flags)4158 JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags)
4159 {
4160 CHECK_REQUEST(cx);
4161 #if JS_HAS_REGEXPS
4162 return js_NewRegExpObject(cx, NULL, chars, length, flags);
4163 #else
4164 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_REG_EXPS);
4165 return NULL;
4166 #endif
4167 }
4168
4169 JS_PUBLIC_API(void)
JS_SetRegExpInput(JSContext * cx,JSString * input,JSBool multiline)4170 JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline)
4171 {
4172 JSRegExpStatics *res;
4173
4174 CHECK_REQUEST(cx);
4175 /* No locking required, cx is thread-private and input must be live. */
4176 res = &cx->regExpStatics;
4177 res->input = input;
4178 res->multiline = multiline;
4179 cx->runtime->gcPoke = JS_TRUE;
4180 }
4181
4182 JS_PUBLIC_API(void)
JS_ClearRegExpStatics(JSContext * cx)4183 JS_ClearRegExpStatics(JSContext *cx)
4184 {
4185 JSRegExpStatics *res;
4186
4187 /* No locking required, cx is thread-private and input must be live. */
4188 res = &cx->regExpStatics;
4189 res->input = NULL;
4190 res->multiline = JS_FALSE;
4191 res->parenCount = 0;
4192 res->lastMatch = res->lastParen = js_EmptySubString;
4193 res->leftContext = res->rightContext = js_EmptySubString;
4194 cx->runtime->gcPoke = JS_TRUE;
4195 }
4196
4197 JS_PUBLIC_API(void)
JS_ClearRegExpRoots(JSContext * cx)4198 JS_ClearRegExpRoots(JSContext *cx)
4199 {
4200 JSRegExpStatics *res;
4201
4202 /* No locking required, cx is thread-private and input must be live. */
4203 res = &cx->regExpStatics;
4204 res->input = NULL;
4205 cx->runtime->gcPoke = JS_TRUE;
4206 }
4207
4208 /* TODO: compile, execute, get/set other statics... */
4209
4210 /************************************************************************/
4211
4212 JS_PUBLIC_API(void)
JS_SetLocaleCallbacks(JSContext * cx,JSLocaleCallbacks * callbacks)4213 JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks)
4214 {
4215 cx->localeCallbacks = callbacks;
4216 }
4217
4218 JS_PUBLIC_API(JSLocaleCallbacks *)
JS_GetLocaleCallbacks(JSContext * cx)4219 JS_GetLocaleCallbacks(JSContext *cx)
4220 {
4221 return cx->localeCallbacks;
4222 }
4223
4224 /************************************************************************/
4225
4226 JS_PUBLIC_API(JSBool)
JS_IsExceptionPending(JSContext * cx)4227 JS_IsExceptionPending(JSContext *cx)
4228 {
4229 #if JS_HAS_EXCEPTIONS
4230 return (JSBool) cx->throwing;
4231 #else
4232 return JS_FALSE;
4233 #endif
4234 }
4235
4236 JS_PUBLIC_API(JSBool)
JS_GetPendingException(JSContext * cx,jsval * vp)4237 JS_GetPendingException(JSContext *cx, jsval *vp)
4238 {
4239 #if JS_HAS_EXCEPTIONS
4240 CHECK_REQUEST(cx);
4241 if (!cx->throwing)
4242 return JS_FALSE;
4243 *vp = cx->exception;
4244 return JS_TRUE;
4245 #else
4246 return JS_FALSE;
4247 #endif
4248 }
4249
4250 JS_PUBLIC_API(void)
JS_SetPendingException(JSContext * cx,jsval v)4251 JS_SetPendingException(JSContext *cx, jsval v)
4252 {
4253 CHECK_REQUEST(cx);
4254 #if JS_HAS_EXCEPTIONS
4255 cx->throwing = JS_TRUE;
4256 cx->exception = v;
4257 #endif
4258 }
4259
4260 JS_PUBLIC_API(void)
JS_ClearPendingException(JSContext * cx)4261 JS_ClearPendingException(JSContext *cx)
4262 {
4263 #if JS_HAS_EXCEPTIONS
4264 cx->throwing = JS_FALSE;
4265 cx->exception = JSVAL_VOID;
4266 #endif
4267 }
4268
4269 JS_PUBLIC_API(JSBool)
JS_ReportPendingException(JSContext * cx)4270 JS_ReportPendingException(JSContext *cx)
4271 {
4272 #if JS_HAS_EXCEPTIONS
4273 CHECK_REQUEST(cx);
4274 return js_ReportUncaughtException(cx);
4275 #else
4276 return JS_TRUE;
4277 #endif
4278 }
4279
4280 #if JS_HAS_EXCEPTIONS
4281 struct JSExceptionState {
4282 JSBool throwing;
4283 jsval exception;
4284 };
4285 #endif
4286
4287 JS_PUBLIC_API(JSExceptionState *)
JS_SaveExceptionState(JSContext * cx)4288 JS_SaveExceptionState(JSContext *cx)
4289 {
4290 #if JS_HAS_EXCEPTIONS
4291 JSExceptionState *state;
4292
4293 CHECK_REQUEST(cx);
4294 state = (JSExceptionState *) JS_malloc(cx, sizeof(JSExceptionState));
4295 if (state) {
4296 state->throwing = JS_GetPendingException(cx, &state->exception);
4297 if (state->throwing && JSVAL_IS_GCTHING(state->exception))
4298 js_AddRoot(cx, &state->exception, "JSExceptionState.exception");
4299 }
4300 return state;
4301 #else
4302 return NULL;
4303 #endif
4304 }
4305
4306 JS_PUBLIC_API(void)
JS_RestoreExceptionState(JSContext * cx,JSExceptionState * state)4307 JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state)
4308 {
4309 #if JS_HAS_EXCEPTIONS
4310 CHECK_REQUEST(cx);
4311 if (state) {
4312 if (state->throwing)
4313 JS_SetPendingException(cx, state->exception);
4314 else
4315 JS_ClearPendingException(cx);
4316 JS_DropExceptionState(cx, state);
4317 }
4318 #endif
4319 }
4320
4321 JS_PUBLIC_API(void)
JS_DropExceptionState(JSContext * cx,JSExceptionState * state)4322 JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
4323 {
4324 #if JS_HAS_EXCEPTIONS
4325 CHECK_REQUEST(cx);
4326 if (state) {
4327 if (state->throwing && JSVAL_IS_GCTHING(state->exception))
4328 JS_RemoveRoot(cx, &state->exception);
4329 JS_free(cx, state);
4330 }
4331 #endif
4332 }
4333
4334 JS_PUBLIC_API(JSErrorReport *)
JS_ErrorFromException(JSContext * cx,jsval v)4335 JS_ErrorFromException(JSContext *cx, jsval v)
4336 {
4337 #if JS_HAS_EXCEPTIONS
4338 CHECK_REQUEST(cx);
4339 return js_ErrorFromException(cx, v);
4340 #else
4341 return NULL;
4342 #endif
4343 }
4344
4345 #ifdef JS_THREADSAFE
4346 JS_PUBLIC_API(jsword)
JS_GetContextThread(JSContext * cx)4347 JS_GetContextThread(JSContext *cx)
4348 {
4349 return cx->thread;
4350 }
4351
4352 JS_PUBLIC_API(jsword)
JS_SetContextThread(JSContext * cx)4353 JS_SetContextThread(JSContext *cx)
4354 {
4355 jsword old = cx->thread;
4356 cx->thread = js_CurrentThreadId();
4357 return old;
4358 }
4359
4360 JS_PUBLIC_API(jsword)
JS_ClearContextThread(JSContext * cx)4361 JS_ClearContextThread(JSContext *cx)
4362 {
4363 jsword old = cx->thread;
4364 cx->thread = 0;
4365 return old;
4366 }
4367 #endif
4368
4369 /************************************************************************/
4370
4371 #if defined(XP_WIN)
4372 #include <windows.h>
4373 /*
4374 * Initialization routine for the JS DLL...
4375 */
4376
4377 /*
4378 * Global Instance handle...
4379 * In Win32 this is the module handle of the DLL.
4380 *
4381 * In Win16 this is the instance handle of the application
4382 * which loaded the DLL.
4383 */
4384
4385 #ifdef _WIN32
DllMain(HINSTANCE hDLL,DWORD dwReason,LPVOID lpReserved)4386 BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
4387 {
4388 return TRUE;
4389 }
4390
4391 #else /* !_WIN32 */
4392
LibMain(HINSTANCE hInst,WORD wDataSeg,WORD cbHeapSize,LPSTR lpszCmdLine)4393 int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg,
4394 WORD cbHeapSize, LPSTR lpszCmdLine )
4395 {
4396 return TRUE;
4397 }
4398
WEP(BOOL fSystemExit)4399 BOOL CALLBACK __loadds WEP(BOOL fSystemExit)
4400 {
4401 return TRUE;
4402 }
4403
4404 #endif /* !_WIN32 */
4405 #endif /* XP_WIN */
4406