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(&notePool, "note", 1024, sizeof(jssrcnote));
3214     if (!js_InitCodeGenerator(cx, &cg, &codePool, &notePool,
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(&notePool);
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