diff options
| author | Aaron Spike <aaron@ekips.org> | 2006-04-12 13:20:54 +0000 |
|---|---|---|
| committer | acspike <acspike@users.sourceforge.net> | 2006-04-12 13:20:54 +0000 |
| commit | ddfaffe08d23e4663fe759d67ae33fd67fc9ce5b (patch) | |
| tree | 234f5425a7ef7058e69dc2ab77f89810e4f3ed91 /src/dom/js/jsapi.c | |
| parent | fix 1466070 (diff) | |
| download | inkscape-ddfaffe08d23e4663fe759d67ae33fd67fc9ce5b.tar.gz inkscape-ddfaffe08d23e4663fe759d67ae33fd67fc9ce5b.zip | |
Removed file/folder for ishmal
(bzr r478)
Diffstat (limited to 'src/dom/js/jsapi.c')
| -rw-r--r-- | src/dom/js/jsapi.c | 4187 |
1 files changed, 0 insertions, 4187 deletions
diff --git a/src/dom/js/jsapi.c b/src/dom/js/jsapi.c deleted file mode 100644 index faf02d983..000000000 --- a/src/dom/js/jsapi.c +++ /dev/null @@ -1,4187 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * JavaScript API. - */ -#include "jsstddef.h" -#include <ctype.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> -#include "jstypes.h" -#include "jsarena.h" /* Added by JSIFY */ -#include "jsutil.h" /* Added by JSIFY */ -#include "jsclist.h" -#include "jsdhash.h" -#include "jsprf.h" -#include "jsapi.h" -#include "jsarray.h" -#include "jsatom.h" -#include "jsbool.h" -#include "jscntxt.h" -#include "jsconfig.h" -#include "jsdate.h" -#include "jsdtoa.h" -#include "jsemit.h" -#include "jsexn.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jsinterp.h" -#include "jslock.h" -#include "jsmath.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsopcode.h" -#include "jsparse.h" -#include "jsregexp.h" -#include "jsscan.h" -#include "jsscope.h" -#include "jsscript.h" -#include "jsstr.h" -#include "prmjtime.h" - -#if JS_HAS_FILE_OBJECT -#include "jsfile.h" -#endif - -#ifdef HAVE_VA_LIST_AS_ARRAY -#define JS_ADDRESSOF_VA_LIST(ap) (ap) -#else -#define JS_ADDRESSOF_VA_LIST(ap) (&(ap)) -#endif - -#if defined(JS_PARANOID_REQUEST) && defined(JS_THREADSAFE) -#define CHECK_REQUEST(cx) JS_ASSERT(cx->requestDepth) -#else -#define CHECK_REQUEST(cx) ((void)0) -#endif - -JS_PUBLIC_API(int64) -JS_Now() -{ - return PRMJ_Now(); -} - -JS_PUBLIC_API(jsval) -JS_GetNaNValue(JSContext *cx) -{ - return DOUBLE_TO_JSVAL(cx->runtime->jsNaN); -} - -JS_PUBLIC_API(jsval) -JS_GetNegativeInfinityValue(JSContext *cx) -{ - return DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity); -} - -JS_PUBLIC_API(jsval) -JS_GetPositiveInfinityValue(JSContext *cx) -{ - return DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity); -} - -JS_PUBLIC_API(jsval) -JS_GetEmptyStringValue(JSContext *cx) -{ - return STRING_TO_JSVAL(cx->runtime->emptyString); -} - -static JSBool -TryArgumentFormatter(JSContext *cx, const char **formatp, JSBool fromJS, - jsval **vpp, va_list *app) -{ - const char *format; - JSArgumentFormatMap *map; - - format = *formatp; - for (map = cx->argumentFormatMap; map; map = map->next) { - if (!strncmp(format, map->format, map->length)) { - *formatp = format + map->length; - return map->formatter(cx, format, fromJS, vpp, app); - } - } - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR, format); - return JS_FALSE; -} - -JS_PUBLIC_API(JSBool) -JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format, - ...) -{ - va_list ap; - JSBool ok; - - va_start(ap, format); - ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap); - va_end(ap); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv, - const char *format, va_list ap) -{ - jsval *sp; - JSBool required; - char c; - JSFunction *fun; - jsdouble d; - JSString *str; - JSObject *obj; - - CHECK_REQUEST(cx); - sp = argv; - required = JS_TRUE; - while ((c = *format++) != '\0') { - if (isspace(c)) - continue; - if (c == '/') { - required = JS_FALSE; - continue; - } - if (sp == argv + argc) { - if (required) { - fun = js_ValueToFunction(cx, &argv[-2], 0); - if (fun) { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%u", argc); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_MORE_ARGS_NEEDED, - JS_GetFunctionName(fun), numBuf, - (argc == 1) ? "" : "s"); - } - return JS_FALSE; - } - break; - } - switch (c) { - case 'b': - if (!js_ValueToBoolean(cx, *sp, va_arg(ap, JSBool *))) - return JS_FALSE; - break; - case 'c': - if (!js_ValueToUint16(cx, *sp, va_arg(ap, uint16 *))) - return JS_FALSE; - break; - case 'i': - if (!js_ValueToECMAInt32(cx, *sp, va_arg(ap, int32 *))) - return JS_FALSE; - break; - case 'u': - if (!js_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32 *))) - return JS_FALSE; - break; - case 'j': - if (!js_ValueToInt32(cx, *sp, va_arg(ap, int32 *))) - return JS_FALSE; - break; - case 'd': - if (!js_ValueToNumber(cx, *sp, va_arg(ap, jsdouble *))) - return JS_FALSE; - break; - case 'I': - if (!js_ValueToNumber(cx, *sp, &d)) - return JS_FALSE; - *va_arg(ap, jsdouble *) = js_DoubleToInteger(d); - break; - case 's': - case 'S': - case 'W': - str = js_ValueToString(cx, *sp); - if (!str) - return JS_FALSE; - *sp = STRING_TO_JSVAL(str); - if (c == 's') - *va_arg(ap, char **) = JS_GetStringBytes(str); - else if (c == 'W') - *va_arg(ap, jschar **) = JS_GetStringChars(str); - else - *va_arg(ap, JSString **) = str; - break; - case 'o': - if (!js_ValueToObject(cx, *sp, &obj)) - return JS_FALSE; - *sp = OBJECT_TO_JSVAL(obj); - *va_arg(ap, JSObject **) = obj; - break; - case 'f': - fun = js_ValueToFunction(cx, sp, 0); - if (!fun) - return JS_FALSE; - *sp = OBJECT_TO_JSVAL(fun->object); - *va_arg(ap, JSFunction **) = fun; - break; - case 'v': - *va_arg(ap, jsval *) = *sp; - break; - case '*': - break; - default: - format--; - if (!TryArgumentFormatter(cx, &format, JS_TRUE, &sp, - JS_ADDRESSOF_VA_LIST(ap))) { - return JS_FALSE; - } - /* NB: the formatter already updated sp, so we continue here. */ - continue; - } - sp++; - } - return JS_TRUE; -} - -JS_PUBLIC_API(jsval *) -JS_PushArguments(JSContext *cx, void **markp, const char *format, ...) -{ - va_list ap; - jsval *argv; - - va_start(ap, format); - argv = JS_PushArgumentsVA(cx, markp, format, ap); - va_end(ap); - return argv; -} - -JS_PUBLIC_API(jsval *) -JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap) -{ - uintN argc; - jsval *argv, *sp; - char c; - const char *cp; - JSString *str; - JSFunction *fun; - JSStackHeader *sh; - - CHECK_REQUEST(cx); - *markp = NULL; - argc = 0; - for (cp = format; (c = *cp) != '\0'; cp++) { - /* - * Count non-space non-star characters as individual jsval arguments. - * This may over-allocate stack, but we'll fix below. - */ - if (isspace(c) || c == '*') - continue; - argc++; - } - sp = js_AllocStack(cx, argc, markp); - if (!sp) - return NULL; - argv = sp; - while ((c = *format++) != '\0') { - if (isspace(c) || c == '*') - continue; - switch (c) { - case 'b': - *sp = BOOLEAN_TO_JSVAL((JSBool) va_arg(ap, int)); - break; - case 'c': - *sp = INT_TO_JSVAL((uint16) va_arg(ap, unsigned int)); - break; - case 'i': - case 'j': - if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, int32), sp)) - goto bad; - break; - case 'u': - if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, uint32), sp)) - goto bad; - break; - case 'd': - case 'I': - if (!js_NewDoubleValue(cx, va_arg(ap, jsdouble), sp)) - goto bad; - break; - case 's': - str = JS_NewStringCopyZ(cx, va_arg(ap, char *)); - if (!str) - goto bad; - *sp = STRING_TO_JSVAL(str); - break; - case 'W': - str = JS_NewUCStringCopyZ(cx, va_arg(ap, jschar *)); - if (!str) - goto bad; - *sp = STRING_TO_JSVAL(str); - break; - case 'S': - str = va_arg(ap, JSString *); - *sp = STRING_TO_JSVAL(str); - break; - case 'o': - *sp = OBJECT_TO_JSVAL(va_arg(ap, JSObject *)); - break; - case 'f': - fun = va_arg(ap, JSFunction *); - *sp = fun ? OBJECT_TO_JSVAL(fun->object) : JSVAL_NULL; - break; - case 'v': - *sp = va_arg(ap, jsval); - break; - default: - format--; - if (!TryArgumentFormatter(cx, &format, JS_FALSE, &sp, - JS_ADDRESSOF_VA_LIST(ap))) { - goto bad; - } - /* NB: the formatter already updated sp, so we continue here. */ - continue; - } - sp++; - } - - /* - * We may have overallocated stack due to a multi-character format code - * handled by a JSArgumentFormatter. Give back that stack space! - */ - JS_ASSERT(sp <= argv + argc); - if (sp < argv + argc) { - /* Return slots not pushed to the current stack arena. */ - cx->stackPool.current->avail = (jsuword)sp; - - /* Reduce the count of slots the GC will scan in this stack segment. */ - sh = cx->stackHeaders; - JS_ASSERT(JS_STACK_SEGMENT(sh) + sh->nslots == argv + argc); - sh->nslots -= argc - (sp - argv); - } - return argv; - -bad: - js_FreeStack(cx, *markp); - return NULL; -} - -JS_PUBLIC_API(void) -JS_PopArguments(JSContext *cx, void *mark) -{ - CHECK_REQUEST(cx); - js_FreeStack(cx, mark); -} - -JS_PUBLIC_API(JSBool) -JS_AddArgumentFormatter(JSContext *cx, const char *format, - JSArgumentFormatter formatter) -{ - size_t length; - JSArgumentFormatMap **mpp, *map; - - length = strlen(format); - mpp = &cx->argumentFormatMap; - while ((map = *mpp) != NULL) { - /* Insert before any shorter string to match before prefixes. */ - if (map->length < length) - break; - if (map->length == length && !strcmp(map->format, format)) - goto out; - mpp = &map->next; - } - map = (JSArgumentFormatMap *) JS_malloc(cx, sizeof *map); - if (!map) - return JS_FALSE; - map->format = format; - map->length = length; - map->next = *mpp; - *mpp = map; -out: - map->formatter = formatter; - return JS_TRUE; -} - -JS_PUBLIC_API(void) -JS_RemoveArgumentFormatter(JSContext *cx, const char *format) -{ - size_t length; - JSArgumentFormatMap **mpp, *map; - - length = strlen(format); - mpp = &cx->argumentFormatMap; - while ((map = *mpp) != NULL) { - if (map->length == length && !strcmp(map->format, format)) { - *mpp = map->next; - JS_free(cx, map); - return; - } - mpp = &map->next; - } -} - -JS_PUBLIC_API(JSBool) -JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp) -{ - JSBool ok, b; - JSObject *obj; - JSFunction *fun; - JSString *str; - jsdouble d, *dp; - - CHECK_REQUEST(cx); - switch (type) { - case JSTYPE_VOID: - *vp = JSVAL_VOID; - ok = JS_TRUE; - break; - case JSTYPE_OBJECT: - ok = js_ValueToObject(cx, v, &obj); - if (ok) - *vp = OBJECT_TO_JSVAL(obj); - break; - case JSTYPE_FUNCTION: - fun = js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK); - ok = (fun != NULL); - if (ok) - *vp = OBJECT_TO_JSVAL(fun->object); - break; - case JSTYPE_STRING: - str = js_ValueToString(cx, v); - ok = (str != NULL); - if (ok) - *vp = STRING_TO_JSVAL(str); - break; - case JSTYPE_NUMBER: - ok = js_ValueToNumber(cx, v, &d); - if (ok) { - dp = js_NewDouble(cx, d); - ok = (dp != NULL); - if (ok) - *vp = DOUBLE_TO_JSVAL(dp); - } - break; - case JSTYPE_BOOLEAN: - ok = js_ValueToBoolean(cx, v, &b); - if (ok) - *vp = BOOLEAN_TO_JSVAL(b); - break; - default: { - char numBuf[12]; - JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE, - numBuf); - ok = JS_FALSE; - break; - } - } - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp) -{ - CHECK_REQUEST(cx); - return js_ValueToObject(cx, v, objp); -} - -JS_PUBLIC_API(JSFunction *) -JS_ValueToFunction(JSContext *cx, jsval v) -{ - CHECK_REQUEST(cx); - return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK); -} - -JS_PUBLIC_API(JSFunction *) -JS_ValueToConstructor(JSContext *cx, jsval v) -{ - CHECK_REQUEST(cx); - return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK); -} - -JS_PUBLIC_API(JSString *) -JS_ValueToString(JSContext *cx, jsval v) -{ - CHECK_REQUEST(cx); - return js_ValueToString(cx, v); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp) -{ - CHECK_REQUEST(cx); - return js_ValueToNumber(cx, v, dp); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip) -{ - CHECK_REQUEST(cx); - return js_ValueToECMAInt32(cx, v, ip); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip) -{ - CHECK_REQUEST(cx); - return js_ValueToECMAUint32(cx, v, ip); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip) -{ - CHECK_REQUEST(cx); - return js_ValueToInt32(cx, v, ip); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip) -{ - CHECK_REQUEST(cx); - return js_ValueToUint16(cx, v, ip); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp) -{ - CHECK_REQUEST(cx); - return js_ValueToBoolean(cx, v, bp); -} - -JS_PUBLIC_API(JSType) -JS_TypeOfValue(JSContext *cx, jsval v) -{ - JSType type; - JSObject *obj; - JSObjectOps *ops; - JSClass *clasp; - - CHECK_REQUEST(cx); - if (JSVAL_IS_OBJECT(v)) { - /* XXX JSVAL_IS_OBJECT(v) is true for null too! Can we change ECMA? */ - obj = JSVAL_TO_OBJECT(v); - if (obj && - (ops = obj->map->ops, - ops == &js_ObjectOps - ? (clasp = OBJ_GET_CLASS(cx, obj), - clasp->call || clasp == &js_FunctionClass) - : ops->call != 0)) { - type = JSTYPE_FUNCTION; - } else { - type = JSTYPE_OBJECT; - } - } else if (JSVAL_IS_NUMBER(v)) { - type = JSTYPE_NUMBER; - } else if (JSVAL_IS_STRING(v)) { - type = JSTYPE_STRING; - } else if (JSVAL_IS_BOOLEAN(v)) { - type = JSTYPE_BOOLEAN; - } else { - type = JSTYPE_VOID; - } - return type; -} - -JS_PUBLIC_API(const char *) -JS_GetTypeName(JSContext *cx, JSType type) -{ - if ((uintN)type >= (uintN)JSTYPE_LIMIT) - return NULL; - return js_type_str[type]; -} - -/************************************************************************/ - -JS_PUBLIC_API(JSRuntime *) -JS_NewRuntime(uint32 maxbytes) -{ - JSRuntime *rt; - -#ifdef DEBUG - JS_BEGIN_MACRO - /* - * This code asserts that the numbers associated with the error names in - * jsmsg.def are monotonically increasing. It uses values for the error - * names enumerated in jscntxt.c. It's not a compiletime check, but it's - * better than nothing. - */ - int errorNumber = 0; -#define MSG_DEF(name, number, count, exception, format) \ - JS_ASSERT(name == errorNumber++); -#include "js.msg" -#undef MSG_DEF - JS_END_MACRO; -#endif /* DEBUG */ - - if (!js_InitScriptGlobals()) - return NULL; - if (!js_InitStringGlobals()) - return NULL; - rt = (JSRuntime *) malloc(sizeof(JSRuntime)); - if (!rt) - return NULL; - - /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */ - memset(rt, 0, sizeof(JSRuntime)); - JS_INIT_CLIST(&rt->contextList); - JS_INIT_CLIST(&rt->trapList); - JS_INIT_CLIST(&rt->watchPointList); - - if (!js_InitGC(rt, maxbytes)) - goto bad; -#ifdef JS_THREADSAFE - rt->gcLock = JS_NEW_LOCK(); - if (!rt->gcLock) - goto bad; - rt->gcDone = JS_NEW_CONDVAR(rt->gcLock); - if (!rt->gcDone) - goto bad; - rt->requestDone = JS_NEW_CONDVAR(rt->gcLock); - if (!rt->requestDone) - goto bad; - js_SetupLocks(8, 16); /* this is asymmetric with JS_ShutDown. */ - rt->rtLock = JS_NEW_LOCK(); - if (!rt->rtLock) - goto bad; - rt->stateChange = JS_NEW_CONDVAR(rt->gcLock); - if (!rt->stateChange) - goto bad; - rt->setSlotLock = JS_NEW_LOCK(); - if (!rt->setSlotLock) - goto bad; - rt->setSlotDone = JS_NEW_CONDVAR(rt->setSlotLock); - if (!rt->setSlotDone) - goto bad; - rt->scopeSharingDone = JS_NEW_CONDVAR(rt->gcLock); - if (!rt->scopeSharingDone) - goto bad; - rt->scopeSharingTodo = NO_SCOPE_SHARING_TODO; -#endif - rt->propertyCache.empty = JS_TRUE; - if (!js_InitPropertyTree(rt)) - goto bad; - return rt; - -bad: - JS_DestroyRuntime(rt); - return NULL; -} - -JS_PUBLIC_API(void) -JS_DestroyRuntime(JSRuntime *rt) -{ -#ifdef DEBUG - /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */ - if (!JS_CLIST_IS_EMPTY(&rt->contextList)) { - JSContext *cx, *iter = NULL; - uintN cxcount = 0; - while ((cx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL) - cxcount++; - fprintf(stderr, -"JS API usage error: %u contexts left in runtime upon JS_DestroyRuntime.\n", - cxcount); - } -#endif - - js_FinishAtomState(&rt->atomState); - js_FinishGC(rt); -#ifdef JS_THREADSAFE - if (rt->gcLock) - JS_DESTROY_LOCK(rt->gcLock); - if (rt->gcDone) - JS_DESTROY_CONDVAR(rt->gcDone); - if (rt->requestDone) - JS_DESTROY_CONDVAR(rt->requestDone); - if (rt->rtLock) - JS_DESTROY_LOCK(rt->rtLock); - if (rt->stateChange) - JS_DESTROY_CONDVAR(rt->stateChange); - if (rt->setSlotLock) - JS_DESTROY_LOCK(rt->setSlotLock); - if (rt->setSlotDone) - JS_DESTROY_CONDVAR(rt->setSlotDone); - if (rt->scopeSharingDone) - JS_DESTROY_CONDVAR(rt->scopeSharingDone); -#endif - js_FinishPropertyTree(rt); - free(rt); -} - -JS_PUBLIC_API(void) -JS_ShutDown(void) -{ - JS_ArenaShutDown(); - js_FinishDtoa(); - js_FreeScriptGlobals(); - js_FreeStringGlobals(); -#ifdef JS_THREADSAFE - js_CleanupLocks(); -#endif -} - -JS_PUBLIC_API(void *) -JS_GetRuntimePrivate(JSRuntime *rt) -{ - return rt->data; -} - -JS_PUBLIC_API(void) -JS_SetRuntimePrivate(JSRuntime *rt, void *data) -{ - rt->data = data; -} - -#ifdef JS_THREADSAFE - -JS_PUBLIC_API(void) -JS_BeginRequest(JSContext *cx) -{ - JSRuntime *rt; - - JS_ASSERT(cx->thread); - if (!cx->requestDepth) { - /* Wait until the GC is finished. */ - rt = cx->runtime; - JS_LOCK_GC(rt); - - /* NB: we use cx->thread here, not js_CurrentThreadId(). */ - if (rt->gcThread != cx->thread) { - while (rt->gcLevel > 0) - JS_AWAIT_GC_DONE(rt); - } - - /* Indicate that a request is running. */ - rt->requestCount++; - cx->requestDepth = 1; - JS_UNLOCK_GC(rt); - return; - } - cx->requestDepth++; -} - -JS_PUBLIC_API(void) -JS_EndRequest(JSContext *cx) -{ - JSRuntime *rt; - JSScope *scope, **todop; - uintN nshares; - - CHECK_REQUEST(cx); - JS_ASSERT(cx->requestDepth > 0); - if (cx->requestDepth == 1) { - /* Lock before clearing to interlock with ClaimScope, in jslock.c. */ - rt = cx->runtime; - JS_LOCK_GC(rt); - cx->requestDepth = 0; - - /* See whether cx has any single-threaded scopes to start sharing. */ - todop = &rt->scopeSharingTodo; - nshares = 0; - while ((scope = *todop) != NO_SCOPE_SHARING_TODO) { - if (scope->ownercx != cx) { - todop = &scope->u.link; - continue; - } - *todop = scope->u.link; - scope->u.link = NULL; /* null u.link for sanity ASAP */ - - /* - * If js_DropObjectMap returns null, we held the last ref to scope. - * The waiting thread(s) must have been killed, after which the GC - * collected the object that held this scope. Unlikely, because it - * requires that the GC ran (e.g., from a branch callback) during - * this request, but possible. - */ - if (js_DropObjectMap(cx, &scope->map, NULL)) { - js_InitLock(&scope->lock); - scope->u.count = 0; /* NULL may not pun as 0 */ - js_FinishSharingScope(rt, scope); /* set ownercx = NULL */ - nshares++; - } - } - if (nshares) - JS_NOTIFY_ALL_CONDVAR(rt->scopeSharingDone); - - /* Give the GC a chance to run if this was the last request running. */ - JS_ASSERT(rt->requestCount > 0); - rt->requestCount--; - if (rt->requestCount == 0) - JS_NOTIFY_REQUEST_DONE(rt); - - JS_UNLOCK_GC(rt); - return; - } - - cx->requestDepth--; -} - -/* Yield to pending GC operations, regardless of request depth */ -JS_PUBLIC_API(void) -JS_YieldRequest(JSContext *cx) -{ - JSRuntime *rt; - - JS_ASSERT(cx->thread); - CHECK_REQUEST(cx); - - rt = cx->runtime; - JS_LOCK_GC(rt); - JS_ASSERT(rt->requestCount > 0); - rt->requestCount--; - if (rt->requestCount == 0) - JS_NOTIFY_REQUEST_DONE(rt); - JS_UNLOCK_GC(rt); - /* XXXbe give the GC or another request calling it a chance to run here? - Assumes FIFO scheduling */ - JS_LOCK_GC(rt); - rt->requestCount++; - JS_UNLOCK_GC(rt); -} - -JS_PUBLIC_API(jsrefcount) -JS_SuspendRequest(JSContext *cx) -{ - jsrefcount saveDepth = cx->requestDepth; - - while (cx->requestDepth) - JS_EndRequest(cx); - return saveDepth; -} - -JS_PUBLIC_API(void) -JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth) -{ - JS_ASSERT(!cx->requestDepth); - while (--saveDepth >= 0) - JS_BeginRequest(cx); -} - -#endif /* JS_THREADSAFE */ - -JS_PUBLIC_API(void) -JS_Lock(JSRuntime *rt) -{ - JS_LOCK_RUNTIME(rt); -} - -JS_PUBLIC_API(void) -JS_Unlock(JSRuntime *rt) -{ - JS_UNLOCK_RUNTIME(rt); -} - -JS_PUBLIC_API(JSContext *) -JS_NewContext(JSRuntime *rt, size_t stackChunkSize) -{ - return js_NewContext(rt, stackChunkSize); -} - -JS_PUBLIC_API(void) -JS_DestroyContext(JSContext *cx) -{ - js_DestroyContext(cx, JS_FORCE_GC); -} - -JS_PUBLIC_API(void) -JS_DestroyContextNoGC(JSContext *cx) -{ - js_DestroyContext(cx, JS_NO_GC); -} - -JS_PUBLIC_API(void) -JS_DestroyContextMaybeGC(JSContext *cx) -{ - js_DestroyContext(cx, JS_MAYBE_GC); -} - -JS_PUBLIC_API(void *) -JS_GetContextPrivate(JSContext *cx) -{ - return cx->data; -} - -JS_PUBLIC_API(void) -JS_SetContextPrivate(JSContext *cx, void *data) -{ - cx->data = data; -} - -JS_PUBLIC_API(JSRuntime *) -JS_GetRuntime(JSContext *cx) -{ - return cx->runtime; -} - -JS_PUBLIC_API(JSContext *) -JS_ContextIterator(JSRuntime *rt, JSContext **iterp) -{ - return js_ContextIterator(rt, JS_TRUE, iterp); -} - -JS_PUBLIC_API(JSVersion) -JS_GetVersion(JSContext *cx) -{ - return cx->version; -} - -JS_PUBLIC_API(JSVersion) -JS_SetVersion(JSContext *cx, JSVersion version) -{ - JSVersion oldVersion; - - oldVersion = cx->version; - if (version == oldVersion) - return oldVersion; - - cx->version = version; - -#if !JS_BUG_FALLIBLE_EQOPS - if (cx->version == JSVERSION_1_2) { - cx->jsop_eq = JSOP_NEW_EQ; - cx->jsop_ne = JSOP_NEW_NE; - } else { - cx->jsop_eq = JSOP_EQ; - cx->jsop_ne = JSOP_NE; - } -#endif /* !JS_BUG_FALLIBLE_EQOPS */ - - return oldVersion; -} - -static struct v2smap { - JSVersion version; - const char *string; -} v2smap[] = { - {JSVERSION_1_0, "1.0"}, - {JSVERSION_1_1, "1.1"}, - {JSVERSION_1_2, "1.2"}, - {JSVERSION_1_3, "1.3"}, - {JSVERSION_1_4, "1.4"}, - {JSVERSION_ECMA_3, "ECMAv3"}, - {JSVERSION_1_5, "1.5"}, - {JSVERSION_DEFAULT, "default"}, - {JSVERSION_UNKNOWN, NULL}, /* must be last, NULL is sentinel */ -}; - -JS_PUBLIC_API(const char *) -JS_VersionToString(JSVersion version) -{ - int i; - - for (i = 0; v2smap[i].string; i++) - if (v2smap[i].version == version) - return v2smap[i].string; - return "unknown"; -} - -JS_PUBLIC_API(JSVersion) -JS_StringToVersion(const char *string) -{ - int i; - - for (i = 0; v2smap[i].string; i++) - if (strcmp(v2smap[i].string, string) == 0) - return v2smap[i].version; - return JSVERSION_UNKNOWN; -} - -JS_PUBLIC_API(uint32) -JS_GetOptions(JSContext *cx) -{ - return cx->options; -} - -JS_PUBLIC_API(uint32) -JS_SetOptions(JSContext *cx, uint32 options) -{ - uint32 oldopts = cx->options; - cx->options = options; - return oldopts; -} - -JS_PUBLIC_API(uint32) -JS_ToggleOptions(JSContext *cx, uint32 options) -{ - uint32 oldopts = cx->options; - cx->options ^= options; - return oldopts; -} - -JS_PUBLIC_API(const char *) -JS_GetImplementationVersion(void) -{ - return "JavaScript-C 1.5 pre-release 6 2004-01-27"; -} - - -JS_PUBLIC_API(JSObject *) -JS_GetGlobalObject(JSContext *cx) -{ - return cx->globalObject; -} - -JS_PUBLIC_API(void) -JS_SetGlobalObject(JSContext *cx, JSObject *obj) -{ - cx->globalObject = obj; -} - -static JSObject * -InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj) -{ - JSDHashTable *table; - JSBool resolving; - JSRuntime *rt; - JSResolvingKey key; - JSResolvingEntry *entry; - JSObject *fun_proto, *obj_proto; - - /* If cx has no global object, use obj so prototypes can be found. */ - if (!cx->globalObject) - cx->globalObject = obj; - - /* Record Function and Object in cx->resolvingTable, if we are resolving. */ - table = cx->resolvingTable; - resolving = (table && table->entryCount); - if (resolving) { - rt = cx->runtime; - key.obj = obj; - key.id = (jsid) rt->atomState.FunctionAtom; - entry = (JSResolvingEntry *) - JS_DHashTableOperate(table, &key, JS_DHASH_ADD); - if (entry && entry->key.obj && (entry->flags & JSRESFLAG_LOOKUP)) { - /* Already resolving Function, record Object too. */ - JS_ASSERT(entry->key.obj == obj); - key.id = (jsid) rt->atomState.ObjectAtom; - entry = (JSResolvingEntry *) - JS_DHashTableOperate(table, &key, JS_DHASH_ADD); - } - if (!entry) { - JS_ReportOutOfMemory(cx); - return NULL; - } - JS_ASSERT(!entry->key.obj && entry->flags == 0); - entry->key = key; - entry->flags = JSRESFLAG_LOOKUP; - } - - /* Initialize the function class first so constructors can be made. */ - fun_proto = js_InitFunctionClass(cx, obj); - if (!fun_proto) - goto out; - - /* Initialize the object class next so Object.prototype works. */ - obj_proto = js_InitObjectClass(cx, obj); - if (!obj_proto) { - fun_proto = NULL; - goto out; - } - - /* Function.prototype and the global object delegate to Object.prototype. */ - OBJ_SET_PROTO(cx, fun_proto, obj_proto); - if (!OBJ_GET_PROTO(cx, obj)) - OBJ_SET_PROTO(cx, obj, obj_proto); - -out: - /* If resolving, remove the other entry (Object or Function) from table. */ - if (resolving) - JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE); - return fun_proto; -} - -JS_PUBLIC_API(JSBool) -JS_InitStandardClasses(JSContext *cx, JSObject *obj) -{ - CHECK_REQUEST(cx); - -#if JS_HAS_UNDEFINED -{ - /* Define a top-level property 'undefined' with the undefined value. */ - JSAtom *atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID]; - if (!OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL, NULL, - JSPROP_PERMANENT, NULL)) { - return JS_FALSE; - } -} -#endif - - /* Function and Object require cooperative bootstrapping magic. */ - if (!InitFunctionAndObjectClasses(cx, obj)) - return JS_FALSE; - - /* Initialize the rest of the standard objects and functions. */ - return js_InitArrayClass(cx, obj) && - js_InitBooleanClass(cx, obj) && - js_InitMathClass(cx, obj) && - js_InitNumberClass(cx, obj) && - js_InitStringClass(cx, obj) && -#if JS_HAS_CALL_OBJECT - js_InitCallClass(cx, obj) && -#endif -#if JS_HAS_REGEXPS - js_InitRegExpClass(cx, obj) && -#endif -#if JS_HAS_SCRIPT_OBJECT - js_InitScriptClass(cx, obj) && -#endif -#if JS_HAS_ERROR_EXCEPTIONS - js_InitExceptionClasses(cx, obj) && -#endif -#if JS_HAS_FILE_OBJECT - js_InitFileClass(cx, obj, JS_TRUE) && -#endif - js_InitDateClass(cx, obj); -} - -#define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom) -#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off))) - -/* - * Table of class initializers and their atom offsets in rt->atomState. - * If you add a "standard" class, remember to update this table. - */ -static struct { - JSObjectOp init; - size_t atomOffset; -} standard_class_atoms[] = { - {InitFunctionAndObjectClasses, ATOM_OFFSET(Function)}, - {InitFunctionAndObjectClasses, ATOM_OFFSET(Object)}, - {js_InitArrayClass, ATOM_OFFSET(Array)}, - {js_InitBooleanClass, ATOM_OFFSET(Boolean)}, - {js_InitDateClass, ATOM_OFFSET(Date)}, - {js_InitMathClass, ATOM_OFFSET(Math)}, - {js_InitNumberClass, ATOM_OFFSET(Number)}, - {js_InitStringClass, ATOM_OFFSET(String)}, -#if JS_HAS_CALL_OBJECT - {js_InitCallClass, ATOM_OFFSET(Call)}, -#endif -#if JS_HAS_ERROR_EXCEPTIONS - {js_InitExceptionClasses, ATOM_OFFSET(Error)}, -#endif -#if JS_HAS_REGEXPS - {js_InitRegExpClass, ATOM_OFFSET(RegExp)}, -#endif -#if JS_HAS_SCRIPT_OBJECT - {js_InitScriptClass, ATOM_OFFSET(Script)}, -#endif - {NULL, 0} -}; - -/* - * Table of top-level function and constant names and their init functions. - * If you add a "standard" global function or property, remember to update - * this table. - */ -typedef struct JSStdName { - JSObjectOp init; - size_t atomOffset; /* offset of atom pointer in JSAtomState */ - const char *name; /* null if atom is pre-pinned, else name */ -} JSStdName; - -static JSAtom * -StdNameToAtom(JSContext *cx, JSStdName *stdn) -{ - size_t offset; - JSAtom *atom; - const char *name; - - offset = stdn->atomOffset; - atom = OFFSET_TO_ATOM(cx->runtime, offset); - if (!atom) { - name = stdn->name; - if (name) { - atom = js_Atomize(cx, name, strlen(name), ATOM_PINNED); - OFFSET_TO_ATOM(cx->runtime, offset) = atom; - } - } - return atom; -} - -#define EAGERLY_PINNED_ATOM(name) ATOM_OFFSET(name), NULL -#define LAZILY_PINNED_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str - -static JSStdName standard_class_names[] = { - /* ECMA requires that eval be a direct property of the global object. */ - {js_InitObjectClass, EAGERLY_PINNED_ATOM(eval)}, - - /* Global properties and functions defined by the Number class. */ - {js_InitNumberClass, LAZILY_PINNED_ATOM(NaN)}, - {js_InitNumberClass, LAZILY_PINNED_ATOM(Infinity)}, - {js_InitNumberClass, LAZILY_PINNED_ATOM(isNaN)}, - {js_InitNumberClass, LAZILY_PINNED_ATOM(isFinite)}, - {js_InitNumberClass, LAZILY_PINNED_ATOM(parseFloat)}, - {js_InitNumberClass, LAZILY_PINNED_ATOM(parseInt)}, - - /* String global functions. */ - {js_InitStringClass, LAZILY_PINNED_ATOM(escape)}, - {js_InitStringClass, LAZILY_PINNED_ATOM(unescape)}, - {js_InitStringClass, LAZILY_PINNED_ATOM(decodeURI)}, - {js_InitStringClass, LAZILY_PINNED_ATOM(encodeURI)}, - {js_InitStringClass, LAZILY_PINNED_ATOM(decodeURIComponent)}, - {js_InitStringClass, LAZILY_PINNED_ATOM(encodeURIComponent)}, -#if JS_HAS_UNEVAL - {js_InitStringClass, LAZILY_PINNED_ATOM(uneval)}, -#endif - - /* Exception constructors. */ -#if JS_HAS_ERROR_EXCEPTIONS - {js_InitExceptionClasses, EAGERLY_PINNED_ATOM(Error)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(InternalError)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(EvalError)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(RangeError)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(ReferenceError)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(SyntaxError)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(TypeError)}, - {js_InitExceptionClasses, LAZILY_PINNED_ATOM(URIError)}, -#endif - - {NULL, 0, NULL} -}; - -static JSStdName object_prototype_names[] = { - /* Object.prototype properties (global delegates to Object.prototype). */ - {js_InitObjectClass, EAGERLY_PINNED_ATOM(proto)}, - {js_InitObjectClass, EAGERLY_PINNED_ATOM(parent)}, - {js_InitObjectClass, EAGERLY_PINNED_ATOM(count)}, -#if JS_HAS_TOSOURCE - {js_InitObjectClass, EAGERLY_PINNED_ATOM(toSource)}, -#endif - {js_InitObjectClass, EAGERLY_PINNED_ATOM(toString)}, - {js_InitObjectClass, EAGERLY_PINNED_ATOM(toLocaleString)}, - {js_InitObjectClass, EAGERLY_PINNED_ATOM(valueOf)}, -#if JS_HAS_OBJ_WATCHPOINT - {js_InitObjectClass, LAZILY_PINNED_ATOM(watch)}, - {js_InitObjectClass, LAZILY_PINNED_ATOM(unwatch)}, -#endif -#if JS_HAS_NEW_OBJ_METHODS - {js_InitObjectClass, LAZILY_PINNED_ATOM(hasOwnProperty)}, - {js_InitObjectClass, LAZILY_PINNED_ATOM(isPrototypeOf)}, - {js_InitObjectClass, LAZILY_PINNED_ATOM(propertyIsEnumerable)}, -#endif -#if JS_HAS_GETTER_SETTER - {js_InitObjectClass, LAZILY_PINNED_ATOM(defineGetter)}, - {js_InitObjectClass, LAZILY_PINNED_ATOM(defineSetter)}, - {js_InitObjectClass, LAZILY_PINNED_ATOM(lookupGetter)}, - {js_InitObjectClass, LAZILY_PINNED_ATOM(lookupSetter)}, -#endif - - {NULL, 0, NULL} -}; - -#undef EAGERLY_PINNED_ATOM -#undef LAZILY_PINNED_ATOM - -JS_PUBLIC_API(JSBool) -JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id, - JSBool *resolved) -{ - JSString *idstr; - JSRuntime *rt; - JSAtom *atom; - JSObjectOp init; - uintN i; - - CHECK_REQUEST(cx); - *resolved = JS_FALSE; - - if (!JSVAL_IS_STRING(id)) - return JS_TRUE; - idstr = JSVAL_TO_STRING(id); - rt = cx->runtime; - -#if JS_HAS_UNDEFINED - /* See if we're resolving 'undefined', and define it if so. */ - atom = rt->atomState.typeAtoms[JSTYPE_VOID]; - if (idstr == ATOM_TO_STRING(atom)) { - *resolved = JS_TRUE; - return OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL, NULL, - JSPROP_PERMANENT, NULL); - } -#endif - - /* Try for class constructors/prototypes named by well-known atoms. */ - init = NULL; - for (i = 0; standard_class_atoms[i].init; i++) { - atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset); - if (idstr == ATOM_TO_STRING(atom)) { - init = standard_class_atoms[i].init; - break; - } - } - - if (!init) { - /* Try less frequently used top-level functions and constants. */ - for (i = 0; standard_class_names[i].init; i++) { - atom = StdNameToAtom(cx, &standard_class_names[i]); - if (!atom) - return JS_FALSE; - if (idstr == ATOM_TO_STRING(atom)) { - init = standard_class_names[i].init; - break; - } - } - - if (!init && !OBJ_GET_PROTO(cx, obj)) { - /* - * Try even less frequently used names delegated from the global - * object to Object.prototype, but only if the Object class hasn't - * yet been initialized. - */ - for (i = 0; object_prototype_names[i].init; i++) { - atom = StdNameToAtom(cx, &object_prototype_names[i]); - if (!atom) - return JS_FALSE; - if (idstr == ATOM_TO_STRING(atom)) { - init = standard_class_names[i].init; - break; - } - } - } - } - - if (init) { - if (!init(cx, obj)) - return JS_FALSE; - *resolved = JS_TRUE; - } - return JS_TRUE; -} - -static JSBool -HasOwnProperty(JSContext *cx, JSObject *obj, JSAtom *atom, JSBool *ownp) -{ - JSObject *pobj; - JSProperty *prop; - - if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &pobj, &prop)) - return JS_FALSE; - if (prop) - OBJ_DROP_PROPERTY(cx, pobj, prop); - *ownp = (pobj == obj && prop); - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj) -{ - JSRuntime *rt; - JSAtom *atom; - JSBool found; - uintN i; - - CHECK_REQUEST(cx); - rt = cx->runtime; - -#if JS_HAS_UNDEFINED - /* See if we need to bind 'undefined' and define it if so. */ - atom = rt->atomState.typeAtoms[JSTYPE_VOID]; - if (!HasOwnProperty(cx, obj, atom, &found)) - return JS_FALSE; - if (!found && - !OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL, NULL, - JSPROP_PERMANENT, NULL)) { - return JS_FALSE; - } -#endif - - /* Initialize any classes that have not been resolved yet. */ - for (i = 0; standard_class_atoms[i].init; i++) { - atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset); - if (!HasOwnProperty(cx, obj, atom, &found)) - return JS_FALSE; - if (!found && !standard_class_atoms[i].init(cx, obj)) - return JS_FALSE; - } - - return JS_TRUE; -} - -#undef ATOM_OFFSET -#undef OFFSET_TO_ATOM - -JS_PUBLIC_API(JSObject *) -JS_GetScopeChain(JSContext *cx) -{ - return cx->fp ? cx->fp->scopeChain : NULL; -} - -JS_PUBLIC_API(void *) -JS_malloc(JSContext *cx, size_t nbytes) -{ - void *p; - - JS_ASSERT(nbytes != 0); - if (nbytes == 0) - nbytes = 1; - cx->runtime->gcMallocBytes += nbytes; - p = malloc(nbytes); - if (!p) - JS_ReportOutOfMemory(cx); - return p; -} - -JS_PUBLIC_API(void *) -JS_realloc(JSContext *cx, void *p, size_t nbytes) -{ - p = realloc(p, nbytes); - if (!p) - JS_ReportOutOfMemory(cx); - return p; -} - -JS_PUBLIC_API(void) -JS_free(JSContext *cx, void *p) -{ - if (p) - free(p); -} - -JS_PUBLIC_API(char *) -JS_strdup(JSContext *cx, const char *s) -{ - size_t n; - void *p; - - n = strlen(s) + 1; - p = JS_malloc(cx, n); - if (!p) - return NULL; - return (char *)memcpy(p, s, n); -} - -JS_PUBLIC_API(jsdouble *) -JS_NewDouble(JSContext *cx, jsdouble d) -{ - CHECK_REQUEST(cx); - return js_NewDouble(cx, d); -} - -JS_PUBLIC_API(JSBool) -JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval) -{ - CHECK_REQUEST(cx); - return js_NewDoubleValue(cx, d, rval); -} - -JS_PUBLIC_API(JSBool) -JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval) -{ - CHECK_REQUEST(cx); - return js_NewNumberValue(cx, d, rval); -} - -#undef JS_AddRoot -JS_PUBLIC_API(JSBool) -JS_AddRoot(JSContext *cx, void *rp) -{ - CHECK_REQUEST(cx); - return js_AddRoot(cx, rp, NULL); -} - -JS_PUBLIC_API(JSBool) -JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name) -{ - return js_AddRootRT(rt, rp, name); -} - -JS_PUBLIC_API(JSBool) -JS_RemoveRoot(JSContext *cx, void *rp) -{ - CHECK_REQUEST(cx); - return js_RemoveRoot(cx->runtime, rp); -} - -JS_PUBLIC_API(JSBool) -JS_RemoveRootRT(JSRuntime *rt, void *rp) -{ - return js_RemoveRoot(rt, rp); -} - -JS_PUBLIC_API(JSBool) -JS_AddNamedRoot(JSContext *cx, void *rp, const char *name) -{ - CHECK_REQUEST(cx); - return js_AddRoot(cx, rp, name); -} - -JS_PUBLIC_API(void) -JS_ClearNewbornRoots(JSContext *cx) -{ - uintN i; - - for (i = 0; i < GCX_NTYPES; i++) - cx->newborn[i] = NULL; - cx->lastAtom = NULL; -} - -#include "jshash.h" /* Added by JSIFY */ - -#ifdef DEBUG - -typedef struct NamedRootDumpArgs { - void (*dump)(const char *name, void *rp, void *data); - void *data; -} NamedRootDumpArgs; - -JS_STATIC_DLL_CALLBACK(JSDHashOperator) -js_named_root_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, - void *arg) -{ - NamedRootDumpArgs *args = (NamedRootDumpArgs *) arg; - JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr; - - if (rhe->name) - args->dump(rhe->name, rhe->root, args->data); - return JS_DHASH_NEXT; -} - -JS_PUBLIC_API(void) -JS_DumpNamedRoots(JSRuntime *rt, - void (*dump)(const char *name, void *rp, void *data), - void *data) -{ - NamedRootDumpArgs args; - - args.dump = dump; - args.data = data; - JS_DHashTableEnumerate(&rt->gcRootsHash, js_named_root_dumper, &args); -} - -#endif /* DEBUG */ - -typedef struct GCRootMapArgs { - JSGCRootMapFun map; - void *data; -} GCRootMapArgs; - -JS_STATIC_DLL_CALLBACK(JSDHashOperator) -js_gcroot_mapper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, - void *arg) -{ - GCRootMapArgs *args = (GCRootMapArgs *) arg; - JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr; - intN mapflags; - JSDHashOperator op; - - mapflags = args->map(rhe->root, rhe->name, args->data); - -#if JS_MAP_GCROOT_NEXT == JS_DHASH_NEXT && \ - JS_MAP_GCROOT_STOP == JS_DHASH_STOP && \ - JS_MAP_GCROOT_REMOVE == JS_DHASH_REMOVE - op = (JSDHashOperator)mapflags; -#else - op = JS_DHASH_NEXT; - if (mapflags & JS_MAP_GCROOT_STOP) - op |= JS_DHASH_STOP; - if (mapflags & JS_MAP_GCROOT_REMOVE) - op |= JS_DHASH_REMOVE; -#endif - - return op; -} - -JS_PUBLIC_API(uint32) -JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data) -{ - GCRootMapArgs args; - uint32 rv; - - args.map = map; - args.data = data; - JS_LOCK_GC(rt); - rv = JS_DHashTableEnumerate(&rt->gcRootsHash, js_gcroot_mapper, &args); - JS_UNLOCK_GC(rt); - return rv; -} - -JS_PUBLIC_API(JSBool) -JS_LockGCThing(JSContext *cx, void *thing) -{ - JSBool ok; - - CHECK_REQUEST(cx); - ok = js_LockGCThing(cx, thing); - if (!ok) - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_LOCK); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_LockGCThingRT(JSRuntime *rt, void *thing) -{ - return js_LockGCThingRT(rt, thing); -} - -JS_PUBLIC_API(JSBool) -JS_UnlockGCThing(JSContext *cx, void *thing) -{ - JSBool ok; - - CHECK_REQUEST(cx); - ok = js_UnlockGCThingRT(cx->runtime, thing); - if (!ok) - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_UNLOCK); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_UnlockGCThingRT(JSRuntime *rt, void *thing) -{ - return js_UnlockGCThingRT(rt, thing); -} - -JS_PUBLIC_API(void) -JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg) -{ - JS_ASSERT(cx->runtime->gcLevel > 0); -#ifdef JS_THREADSAFE - JS_ASSERT(cx->runtime->gcThread == js_CurrentThreadId()); -#endif - - GC_MARK(cx, thing, name, arg); -} - -JS_PUBLIC_API(void) -JS_GC(JSContext *cx) -{ - /* Don't nuke active arenas if executing or compiling. */ - if (cx->stackPool.current == &cx->stackPool.first) - JS_FinishArenaPool(&cx->stackPool); - if (cx->tempPool.current == &cx->tempPool.first) - JS_FinishArenaPool(&cx->tempPool); - js_ForceGC(cx, 0); -} - -JS_PUBLIC_API(void) -JS_MaybeGC(JSContext *cx) -{ - JSRuntime *rt; - uint32 bytes, lastBytes; - - rt = cx->runtime; - bytes = rt->gcBytes; - lastBytes = rt->gcLastBytes; - if ((bytes > 8192 && bytes > lastBytes + lastBytes / 2) || - rt->gcMallocBytes > rt->gcMaxBytes) { - /* - * Run the GC if we have half again as many bytes of GC-things as - * the last time we GC'd, or if we have malloc'd more bytes through - * JS_malloc than we were told to allocate by JS_NewRuntime. - */ - JS_GC(cx); - } -} - -JS_PUBLIC_API(JSGCCallback) -JS_SetGCCallback(JSContext *cx, JSGCCallback cb) -{ - return JS_SetGCCallbackRT(cx->runtime, cb); -} - -JS_PUBLIC_API(JSGCCallback) -JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb) -{ - JSGCCallback oldcb; - - oldcb = rt->gcCallback; - rt->gcCallback = cb; - return oldcb; -} - -JS_PUBLIC_API(JSBool) -JS_IsAboutToBeFinalized(JSContext *cx, void *thing) -{ - JS_ASSERT(thing); - return js_IsAboutToBeFinalized(cx, thing); -} - -JS_PUBLIC_API(intN) -JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer) -{ - return js_ChangeExternalStringFinalizer(NULL, finalizer); -} - -JS_PUBLIC_API(intN) -JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer) -{ - return js_ChangeExternalStringFinalizer(finalizer, NULL); -} - -JS_PUBLIC_API(JSString *) -JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type) -{ - JSString *str; - - CHECK_REQUEST(cx); - JS_ASSERT(GCX_EXTERNAL_STRING <= type && type < (intN) GCX_NTYPES); - - str = (JSString *) js_AllocGCThing(cx, (uintN) type); - if (!str) - return NULL; - str->length = length; - str->chars = chars; - return str; -} - -JS_PUBLIC_API(intN) -JS_GetExternalStringGCType(JSRuntime *rt, JSString *str) -{ - uint8 type = (uint8) (*js_GetGCThingFlags(str) & GCF_TYPEMASK); - - if (type >= GCX_EXTERNAL_STRING) - return (intN)type; - JS_ASSERT(type == GCX_STRING || type == GCX_MUTABLE_STRING); - return -1; -} - -#ifdef DEBUG -static void -CheckStackGrowthDirection(int *dummy1addr, jsuword limitAddr) -{ - int dummy2; - -#if JS_STACK_GROWTH_DIRECTION > 0 - JS_ASSERT(dummy1addr < &dummy2); - JS_ASSERT((jsuword)&dummy2 < limitAddr); -#else - /* Stack grows downward, the common case on modern architectures. */ - JS_ASSERT(&dummy2 < dummy1addr); - JS_ASSERT(limitAddr < (jsuword)&dummy2); -#endif -} -#endif - -JS_PUBLIC_API(void) -JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr) -{ -#ifdef DEBUG - int dummy1; - - CheckStackGrowthDirection(&dummy1, limitAddr); -#endif - -#if JS_STACK_GROWTH_DIRECTION > 0 - if (limitAddr == 0) - limitAddr = (jsuword)-1; -#endif - cx->stackLimit = limitAddr; -} - -/************************************************************************/ - -JS_PUBLIC_API(void) -JS_DestroyIdArray(JSContext *cx, JSIdArray *ida) -{ - JS_free(cx, ida); -} - -JS_PUBLIC_API(JSBool) -JS_ValueToId(JSContext *cx, jsval v, jsid *idp) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - if (JSVAL_IS_INT(v)) { - *idp = v; - } else { - atom = js_ValueToStringAtom(cx, v); - if (!atom) - return JS_FALSE; - *idp = (jsid)atom; - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_IdToValue(JSContext *cx, jsid id, jsval *vp) -{ - CHECK_REQUEST(cx); - *vp = ID_TO_VALUE(id); - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_EnumerateStub(JSContext *cx, JSObject *obj) -{ - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id) -{ - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp) -{ -#if JS_BUG_EAGER_TOSTRING - if (type == JSTYPE_STRING) - return JS_TRUE; -#endif - return js_TryValueOf(cx, obj, type, vp); -} - -JS_PUBLIC_API(void) -JS_FinalizeStub(JSContext *cx, JSObject *obj) -{ -} - -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) -{ - JSAtom *atom; - JSObject *proto, *ctor; - JSBool named; - JSFunction *fun; - jsval junk; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0); - if (!atom) - return NULL; - - /* Create a prototype object for this class. */ - proto = js_NewObject(cx, clasp, parent_proto, obj); - if (!proto) - return NULL; - - if (!constructor) { - /* Lacking a constructor, name the prototype (e.g., Math). */ - named = OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, OBJECT_TO_JSVAL(proto), - NULL, NULL, 0, NULL); - if (!named) - goto bad; - ctor = proto; - } else { - /* Define the constructor function in obj's scope. */ - fun = js_DefineFunction(cx, obj, atom, constructor, nargs, 0); - named = (fun != NULL); - if (!fun) - goto bad; - - /* - * Remember the class this function is a constructor for so that - * we know to create an object of this class when we call the - * constructor. - */ - fun->clasp = clasp; - - /* Connect constructor and prototype by named properties. */ - ctor = fun->object; - if (!js_SetClassPrototype(cx, ctor, proto, - JSPROP_READONLY | JSPROP_PERMANENT)) { - goto bad; - } - - /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */ - if (OBJ_GET_CLASS(cx, ctor) == clasp) { - /* XXXMLM - this fails in framesets that are writing over - * themselves! - * JS_ASSERT(!OBJ_GET_PROTO(cx, ctor)); - */ - OBJ_SET_PROTO(cx, ctor, proto); - } - } - - /* Add properties and methods to the prototype and the constructor. */ - if ((ps && !JS_DefineProperties(cx, proto, ps)) || - (fs && !JS_DefineFunctions(cx, proto, fs)) || - (static_ps && !JS_DefineProperties(cx, ctor, static_ps)) || - (static_fs && !JS_DefineFunctions(cx, ctor, static_fs))) { - goto bad; - } - return proto; - -bad: - if (named) - (void) OBJ_DELETE_PROPERTY(cx, obj, (jsid)atom, &junk); - cx->newborn[GCX_OBJECT] = NULL; - return NULL; -} - -#ifdef JS_THREADSAFE -JS_PUBLIC_API(JSClass *) -JS_GetClass(JSContext *cx, JSObject *obj) -{ - return (JSClass *) - JSVAL_TO_PRIVATE(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_CLASS)); -} -#else -JS_PUBLIC_API(JSClass *) -JS_GetClass(JSObject *obj) -{ - return LOCKED_OBJ_GET_CLASS(obj); -} -#endif - -JS_PUBLIC_API(JSBool) -JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv) -{ - JSFunction *fun; - - CHECK_REQUEST(cx); - if (OBJ_GET_CLASS(cx, obj) == clasp) - return JS_TRUE; - if (argv) { - fun = js_ValueToFunction(cx, &argv[-2], 0); - if (fun) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_INCOMPATIBLE_PROTO, - clasp->name, JS_GetFunctionName(fun), - OBJ_GET_CLASS(cx, obj)->name); - } - } - return JS_FALSE; -} - -JS_PUBLIC_API(void *) -JS_GetPrivate(JSContext *cx, JSObject *obj) -{ - jsval v; - - JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE); - v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PRIVATE); - if (!JSVAL_IS_INT(v)) - return NULL; - return JSVAL_TO_PRIVATE(v); -} - -JS_PUBLIC_API(JSBool) -JS_SetPrivate(JSContext *cx, JSObject *obj, void *data) -{ - JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE); - OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(data)); - return JS_TRUE; -} - -JS_PUBLIC_API(void *) -JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp, - jsval *argv) -{ - if (!JS_InstanceOf(cx, obj, clasp, argv)) - return NULL; - return JS_GetPrivate(cx, obj); -} - -JS_PUBLIC_API(JSObject *) -JS_GetPrototype(JSContext *cx, JSObject *obj) -{ - JSObject *proto; - - CHECK_REQUEST(cx); - proto = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PROTO)); - - /* Beware ref to dead object (we may be called from obj's finalizer). */ - return proto && proto->map ? proto : NULL; -} - -JS_PUBLIC_API(JSBool) -JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto) -{ - CHECK_REQUEST(cx); - if (obj->map->ops->setProto) - return obj->map->ops->setProto(cx, obj, JSSLOT_PROTO, proto); - OBJ_SET_SLOT(cx, obj, JSSLOT_PROTO, OBJECT_TO_JSVAL(proto)); - return JS_TRUE; -} - -JS_PUBLIC_API(JSObject *) -JS_GetParent(JSContext *cx, JSObject *obj) -{ - JSObject *parent; - - parent = JSVAL_TO_OBJECT(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PARENT)); - - /* Beware ref to dead object (we may be called from obj's finalizer). */ - return parent && parent->map ? parent : NULL; -} - -JS_PUBLIC_API(JSBool) -JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent) -{ - CHECK_REQUEST(cx); - if (obj->map->ops->setParent) - return obj->map->ops->setParent(cx, obj, JSSLOT_PARENT, parent); - OBJ_SET_SLOT(cx, obj, JSSLOT_PARENT, OBJECT_TO_JSVAL(parent)); - return JS_TRUE; -} - -JS_PUBLIC_API(JSObject *) -JS_GetConstructor(JSContext *cx, JSObject *proto) -{ - jsval cval; - - CHECK_REQUEST(cx); - if (!OBJ_GET_PROPERTY(cx, proto, - (jsid)cx->runtime->atomState.constructorAtom, - &cval)) { - return NULL; - } - if (!JSVAL_IS_FUNCTION(cx, cval)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR, - OBJ_GET_CLASS(cx, proto)->name); - return NULL; - } - return JSVAL_TO_OBJECT(cval); -} - -JS_PUBLIC_API(JSBool) -JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp) -{ - *idp = (jsid) obj; - return JS_TRUE; -} - -JS_PUBLIC_API(JSObject *) -JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent) -{ - CHECK_REQUEST(cx); - if (!clasp) - clasp = &js_ObjectClass; /* default class is Object */ - return js_NewObject(cx, clasp, proto, parent); -} - -JS_PUBLIC_API(JSBool) -JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep) -{ - JSScope *scope; - JSIdArray *ida; - uint32 nslots; - jsval v, *vp, *end; - - if (!OBJ_IS_NATIVE(obj)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CANT_SEAL_OBJECT, - OBJ_GET_CLASS(cx, obj)->name); - return JS_FALSE; - } - - scope = OBJ_SCOPE(obj); - -#if defined JS_THREADSAFE && defined DEBUG - /* Insist on scope being used exclusively by cx's thread. */ - if (scope->ownercx != cx) { - JS_LOCK_OBJ(cx, obj); - JS_ASSERT(OBJ_SCOPE(obj) == scope); - JS_ASSERT(scope->ownercx == cx); - JS_UNLOCK_SCOPE(cx, scope); - } -#endif - - /* Nothing to do if obj's scope is already sealed. */ - if (SCOPE_IS_SEALED(scope)) - return JS_TRUE; - - /* XXX Enumerate lazy properties now, as they can't be added later. */ - ida = JS_Enumerate(cx, obj); - if (!ida) - return JS_FALSE; - JS_DestroyIdArray(cx, ida); - - /* Ensure that obj has its own, mutable scope, and seal that scope. */ - JS_LOCK_OBJ(cx, obj); - scope = js_GetMutableScope(cx, obj); - if (scope) - SCOPE_SET_SEALED(scope); - JS_UNLOCK_SCOPE(cx, scope); - if (!scope) - return JS_FALSE; - - /* If we are not sealing an entire object graph, we're done. */ - if (!deep) - return JS_TRUE; - - /* Walk obj->slots and if any value is a non-null object, seal it. */ - nslots = JS_MIN(scope->map.freeslot, scope->map.nslots); - for (vp = obj->slots, end = vp + nslots; vp < end; vp++) { - v = *vp; - if (JSVAL_IS_PRIMITIVE(v)) - continue; - if (!JS_SealObject(cx, JSVAL_TO_OBJECT(v), deep)) - return JS_FALSE; - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSObject *) -JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto, - JSObject *parent) -{ - CHECK_REQUEST(cx); - if (!clasp) - clasp = &js_ObjectClass; /* default class is Object */ - return js_ConstructObject(cx, clasp, proto, parent, 0, NULL); -} - -JS_PUBLIC_API(JSObject *) -JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto, - JSObject *parent, uintN argc, jsval *argv) -{ - CHECK_REQUEST(cx); - if (!clasp) - clasp = &js_ObjectClass; /* default class is Object */ - return js_ConstructObject(cx, clasp, proto, parent, argc, argv); -} - -static JSBool -DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs, - uintN flags, intN tinyid) -{ - jsid id; - JSAtom *atom; - - if (attrs & JSPROP_INDEX) { - id = INT_TO_JSVAL((jsint)name); - atom = NULL; - attrs &= ~JSPROP_INDEX; - } else { - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - id = (jsid)atom; - } - if (flags != 0 && OBJ_IS_NATIVE(obj)) { - return js_DefineNativeProperty(cx, obj, id, value, getter, setter, - attrs, flags, tinyid, NULL); - } - return OBJ_DEFINE_PROPERTY(cx, obj, id, value, getter, setter, attrs, - NULL); -} - -#define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n)) - -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) -{ - JSAtom *atom; - - atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name,namelen), 0); - if (!atom) - return JS_FALSE; - if (flags != 0 && OBJ_IS_NATIVE(obj)) { - return js_DefineNativeProperty(cx, obj, (jsid)atom, value, - getter, setter, attrs, flags, tinyid, - NULL); - } - return OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, value, getter, setter, - attrs, NULL); -} - -JS_PUBLIC_API(JSObject *) -JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp, - JSObject *proto, uintN attrs) -{ - JSObject *nobj; - - CHECK_REQUEST(cx); - if (!clasp) - clasp = &js_ObjectClass; /* default class is Object */ - nobj = js_NewObject(cx, clasp, proto, obj); - if (!nobj) - return NULL; - if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs, - 0, 0)) { - cx->newborn[GCX_OBJECT] = NULL; - return NULL; - } - return nobj; -} - -JS_PUBLIC_API(JSBool) -JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds) -{ - JSBool ok; - jsval value; - uintN flags; - - CHECK_REQUEST(cx); - for (ok = JS_TRUE; cds->name; cds++) { - ok = js_NewNumberValue(cx, cds->dval, &value); - if (!ok) - break; - flags = cds->flags; - if (!flags) - flags = JSPROP_READONLY | JSPROP_PERMANENT; - ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, flags, 0, 0); - if (!ok) - break; - } - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps) -{ - JSBool ok; - - CHECK_REQUEST(cx); - for (ok = JS_TRUE; ps->name; ps++) { - ok = DefineProperty(cx, obj, ps->name, JSVAL_VOID, - ps->getter, ps->setter, ps->flags, - SPROP_HAS_SHORTID, ps->tinyid); - if (!ok) - break; - } - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs) -{ - CHECK_REQUEST(cx); - return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0); -} - -JS_PUBLIC_API(JSBool) -JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name, - int8 tinyid, jsval value, - JSPropertyOp getter, JSPropertyOp setter, - uintN attrs) -{ - CHECK_REQUEST(cx); - return DefineProperty(cx, obj, name, value, getter, setter, attrs, - SPROP_HAS_SHORTID, tinyid); -} - -static JSBool -LookupProperty(JSContext *cx, JSObject *obj, const char *name, JSObject **objp, - JSProperty **propp) -{ - JSAtom *atom; - - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - return OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, objp, propp); -} - -static JSBool -LookupUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - JSObject **objp, JSProperty **propp) -{ - JSAtom *atom; - - atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name,namelen), 0); - if (!atom) - return JS_FALSE; - return OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, objp, propp); -} - -JS_PUBLIC_API(JSBool) -JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name, - const char *alias) -{ - JSObject *obj2; - JSProperty *prop; - JSAtom *atom; - JSBool ok; - JSScopeProperty *sprop; - - CHECK_REQUEST(cx); - if (!LookupProperty(cx, obj, name, &obj2, &prop)) - return JS_FALSE; - if (!prop) { - js_ReportIsNotDefined(cx, name); - return JS_FALSE; - } - if (obj2 != obj || !OBJ_IS_NATIVE(obj)) { - OBJ_DROP_PROPERTY(cx, obj2, prop); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS, - alias, name, OBJ_GET_CLASS(cx, obj2)->name); - return JS_FALSE; - } - atom = js_Atomize(cx, alias, strlen(alias), 0); - if (!atom) { - ok = JS_FALSE; - } else { - sprop = (JSScopeProperty *)prop; - ok = (js_AddNativeProperty(cx, obj, (jsid)atom, - sprop->getter, sprop->setter, sprop->slot, - sprop->attrs, sprop->flags | SPROP_IS_ALIAS, - sprop->shortid) - != NULL); - } - OBJ_DROP_PROPERTY(cx, obj, prop); - return ok; -} - -static jsval -LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop) -{ - JSScopeProperty *sprop; - jsval rval; - - if (!prop) { - /* XXX bad API: no way to tell "not defined" from "void value" */ - return JSVAL_VOID; - } - if (OBJ_IS_NATIVE(obj2)) { - /* Peek at the native property's slot value, without doing a Get. */ - sprop = (JSScopeProperty *)prop; - rval = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2)) - ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot) - : JSVAL_TRUE; - } else { - /* XXX bad API: no way to return "defined but value unknown" */ - rval = JSVAL_TRUE; - } - OBJ_DROP_PROPERTY(cx, obj2, prop); - return rval; -} - -static JSBool -GetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom, - uintN *attrsp, JSBool *foundp) -{ - JSObject *obj2; - JSProperty *prop; - JSBool ok; - - if (!atom) - return JS_FALSE; - if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &obj2, &prop)) - return JS_FALSE; - if (!prop || obj != obj2) { - *foundp = JS_FALSE; - if (prop) - OBJ_DROP_PROPERTY(cx, obj2, prop); - return JS_TRUE; - } - - *foundp = JS_TRUE; - ok = OBJ_GET_ATTRIBUTES(cx, obj, (jsid)atom, prop, attrsp); - OBJ_DROP_PROPERTY(cx, obj, prop); - return ok; -} - -static JSBool -SetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom, - uintN attrs, JSBool *foundp) -{ - JSObject *obj2; - JSProperty *prop; - JSBool ok; - - if (!atom) - return JS_FALSE; - if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &obj2, &prop)) - return JS_FALSE; - if (!prop || obj != obj2) { - *foundp = JS_FALSE; - if (prop) - OBJ_DROP_PROPERTY(cx, obj2, prop); - return JS_TRUE; - } - - *foundp = JS_TRUE; - ok = OBJ_SET_ATTRIBUTES(cx, obj, (jsid)atom, prop, &attrs); - OBJ_DROP_PROPERTY(cx, obj, prop); - return ok; -} - - -JS_PUBLIC_API(JSBool) -JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name, - uintN *attrsp, JSBool *foundp) -{ - CHECK_REQUEST(cx); - return GetPropertyAttributes(cx, obj, - js_Atomize(cx, name, strlen(name), 0), - attrsp, foundp); -} - -JS_PUBLIC_API(JSBool) -JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name, - uintN attrs, JSBool *foundp) -{ - CHECK_REQUEST(cx); - return SetPropertyAttributes(cx, obj, - js_Atomize(cx, name, strlen(name), 0), - attrs, foundp); -} - -JS_PUBLIC_API(JSBool) -JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp) -{ - JSBool ok; - JSObject *obj2; - JSProperty *prop; - - CHECK_REQUEST(cx); - ok = LookupProperty(cx, obj, name, &obj2, &prop); - if (ok) - *vp = LookupResult(cx, obj, obj2, prop); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - return OBJ_GET_PROPERTY(cx, obj, (jsid)atom, vp); -} - -JS_PUBLIC_API(JSBool) -JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - return OBJ_SET_PROPERTY(cx, obj, (jsid)atom, vp); -} - -JS_PUBLIC_API(JSBool) -JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name) -{ - jsval junk; - - CHECK_REQUEST(cx); - return JS_DeleteProperty2(cx, obj, name, &junk); -} - -JS_PUBLIC_API(JSBool) -JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name, - jsval *rval) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return JS_FALSE; - return OBJ_DELETE_PROPERTY(cx, obj, (jsid)atom, rval); -} - -JS_PUBLIC_API(JSBool) -JS_DefineUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, jsval value, - JSPropertyOp getter, JSPropertyOp setter, - uintN attrs) -{ - CHECK_REQUEST(cx); - return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, - attrs, 0, 0); -} - -JS_PUBLIC_API(JSBool) -JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - uintN *attrsp, JSBool *foundp) -{ - CHECK_REQUEST(cx); - return GetPropertyAttributes(cx, obj, - js_AtomizeChars(cx, name, AUTO_NAMELEN(name,namelen), 0), - attrsp, foundp); -} - -JS_PUBLIC_API(JSBool) -JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - uintN attrs, JSBool *foundp) -{ - CHECK_REQUEST(cx); - return SetPropertyAttributes(cx, obj, - js_AtomizeChars(cx, name, AUTO_NAMELEN(name,namelen), 0), - attrs, foundp); -} - -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) -{ - CHECK_REQUEST(cx); - return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, - attrs, SPROP_HAS_SHORTID, tinyid); -} - -JS_PUBLIC_API(JSBool) -JS_LookupUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - jsval *vp) -{ - JSBool ok; - JSObject *obj2; - JSProperty *prop; - - CHECK_REQUEST(cx); - ok = LookupUCProperty(cx, obj, name, namelen, &obj2, &prop); - if (ok) - *vp = LookupResult(cx, obj, obj2, prop); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_GetUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - jsval *vp) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name,namelen), 0); - if (!atom) - return JS_FALSE; - return OBJ_GET_PROPERTY(cx, obj, (jsid)atom, vp); -} - -JS_PUBLIC_API(JSBool) -JS_SetUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - jsval *vp) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name,namelen), 0); - if (!atom) - return JS_FALSE; - return OBJ_SET_PROPERTY(cx, obj, (jsid)atom, vp); -} - -JS_PUBLIC_API(JSBool) -JS_DeleteUCProperty2(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - jsval *rval) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name,namelen), 0); - if (!atom) - return JS_FALSE; - return OBJ_DELETE_PROPERTY(cx, obj, (jsid)atom, rval); -} - -JS_PUBLIC_API(JSObject *) -JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector) -{ - CHECK_REQUEST(cx); - /* NB: jsuint cast does ToUint32. */ - return js_NewArrayObject(cx, (jsuint)length, vector); -} - -JS_PUBLIC_API(JSBool) -JS_IsArrayObject(JSContext *cx, JSObject *obj) -{ - return OBJ_GET_CLASS(cx, obj) == &js_ArrayClass; -} - -JS_PUBLIC_API(JSBool) -JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp) -{ - CHECK_REQUEST(cx); - return js_GetLengthProperty(cx, obj, lengthp); -} - -JS_PUBLIC_API(JSBool) -JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length) -{ - CHECK_REQUEST(cx); - return js_SetLengthProperty(cx, obj, length); -} - -JS_PUBLIC_API(JSBool) -JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp) -{ - CHECK_REQUEST(cx); - return js_HasLengthProperty(cx, obj, lengthp); -} - -JS_PUBLIC_API(JSBool) -JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value, - JSPropertyOp getter, JSPropertyOp setter, uintN attrs) -{ - CHECK_REQUEST(cx); - return OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSVAL(index), value, - getter, setter, attrs, NULL); -} - -JS_PUBLIC_API(JSBool) -JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias) -{ - JSObject *obj2; - JSProperty *prop; - JSScopeProperty *sprop; - JSBool ok; - - CHECK_REQUEST(cx); - if (!LookupProperty(cx, obj, name, &obj2, &prop)) - return JS_FALSE; - if (!prop) { - js_ReportIsNotDefined(cx, name); - return JS_FALSE; - } - if (obj2 != obj || !OBJ_IS_NATIVE(obj)) { - char numBuf[12]; - OBJ_DROP_PROPERTY(cx, obj2, prop); - JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)alias); - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS, - numBuf, name, OBJ_GET_CLASS(cx, obj2)->name); - return JS_FALSE; - } - sprop = (JSScopeProperty *)prop; - ok = (js_AddNativeProperty(cx, obj, INT_TO_JSVAL(alias), - sprop->getter, sprop->setter, sprop->slot, - sprop->attrs, sprop->flags | SPROP_IS_ALIAS, - sprop->shortid) - != NULL); - OBJ_DROP_PROPERTY(cx, obj, prop); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp) -{ - JSBool ok; - JSObject *obj2; - JSProperty *prop; - - CHECK_REQUEST(cx); - ok = OBJ_LOOKUP_PROPERTY(cx, obj, INT_TO_JSVAL(index), &obj2, &prop); - if (ok) - *vp = LookupResult(cx, obj, obj2, prop); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp) -{ - CHECK_REQUEST(cx); - return OBJ_GET_PROPERTY(cx, obj, INT_TO_JSVAL(index), vp); -} - -JS_PUBLIC_API(JSBool) -JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp) -{ - CHECK_REQUEST(cx); - return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSVAL(index), vp); -} - -JS_PUBLIC_API(JSBool) -JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index) -{ - jsval junk; - - CHECK_REQUEST(cx); - return JS_DeleteElement2(cx, obj, index, &junk); -} - -JS_PUBLIC_API(JSBool) -JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval) -{ - CHECK_REQUEST(cx); - return OBJ_DELETE_PROPERTY(cx, obj, INT_TO_JSVAL(index), rval); -} - -JS_PUBLIC_API(void) -JS_ClearScope(JSContext *cx, JSObject *obj) -{ - CHECK_REQUEST(cx); - - if (obj->map->ops->clear) - obj->map->ops->clear(cx, obj); -} - -JS_PUBLIC_API(JSIdArray *) -JS_Enumerate(JSContext *cx, JSObject *obj) -{ - jsint i, n; - jsval iter_state, num_properties; - jsid id; - JSIdArray *ida; - jsval *vector; - - CHECK_REQUEST(cx); - - ida = NULL; - iter_state = JSVAL_NULL; - - /* Get the number of properties to enumerate. */ - if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties)) - goto error; - if (!JSVAL_IS_INT(num_properties)) { - JS_ASSERT(0); - goto error; - } - - /* Grow as needed if we don't know the exact amount ahead of time. */ - n = JSVAL_TO_INT(num_properties); - if (n <= 0) - n = 8; - - /* Create an array of jsids large enough to hold all the properties */ - ida = js_NewIdArray(cx, n); - if (!ida) - goto error; - - i = 0; - vector = &ida->vector[0]; - for (;;) { - if (i == ida->length) { - /* Grow length by factor of 1.5 instead of doubling. */ - jsint newlen = ida->length + (((jsuint)ida->length + 1) >> 1); - ida = js_GrowIdArray(cx, ida, newlen); - if (!ida) - goto error; - vector = &ida->vector[0]; - } - - if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &iter_state, &id)) - goto error; - - /* No more jsid's to enumerate ? */ - if (iter_state == JSVAL_NULL) - break; - vector[i++] = id; - } - ida->length = i; - return ida; - -error: - if (iter_state != JSVAL_NULL) - OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0); - if (ida) - JS_DestroyIdArray(cx, ida); - return NULL; -} - -JS_PUBLIC_API(JSBool) -JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, - jsval *vp, uintN *attrsp) -{ - CHECK_REQUEST(cx); - return OBJ_CHECK_ACCESS(cx, obj, id, mode, vp, attrsp); -} - -JS_PUBLIC_API(JSCheckAccessOp) -JS_SetCheckObjectAccessCallback(JSRuntime *rt, JSCheckAccessOp acb) -{ - JSCheckAccessOp oldacb; - - oldacb = rt->checkObjectAccess; - rt->checkObjectAccess = acb; - return oldacb; -} - -JS_PUBLIC_API(JSBool) -JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp) -{ - JSClass *clasp; - uint32 slot; - - CHECK_REQUEST(cx); - clasp = OBJ_GET_CLASS(cx, obj); - if (index >= JSCLASS_RESERVED_SLOTS(clasp)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_RESERVED_SLOT_RANGE); - return JS_FALSE; - } - slot = JSSLOT_START(clasp) + index; - *vp = OBJ_GET_REQUIRED_SLOT(cx, obj, slot); - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v) -{ - JSClass *clasp; - uint32 slot; - - CHECK_REQUEST(cx); - clasp = OBJ_GET_CLASS(cx, obj); - if (index >= JSCLASS_RESERVED_SLOTS(clasp)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_RESERVED_SLOT_RANGE); - return JS_FALSE; - } - slot = JSSLOT_START(clasp) + index; - OBJ_SET_REQUIRED_SLOT(cx, obj, slot, v); - return JS_TRUE; -} - -#ifdef JS_THREADSAFE -JS_PUBLIC_API(jsrefcount) -JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals) -{ - return JS_ATOMIC_INCREMENT(&principals->refcount); -} - -JS_PUBLIC_API(jsrefcount) -JS_DropPrincipals(JSContext *cx, JSPrincipals *principals) -{ - jsrefcount rc = JS_ATOMIC_DECREMENT(&principals->refcount); - if (rc == 0) - principals->destroy(cx, principals); - return rc; -} -#endif - -JS_PUBLIC_API(JSPrincipalsTranscoder) -JS_SetPrincipalsTranscoder(JSRuntime *rt, JSPrincipalsTranscoder px) -{ - JSPrincipalsTranscoder oldpx; - - oldpx = rt->principalsTranscoder; - rt->principalsTranscoder = px; - return oldpx; -} - -JS_PUBLIC_API(JSObjectPrincipalsFinder) -JS_SetObjectPrincipalsFinder(JSContext *cx, JSObjectPrincipalsFinder fop) -{ - JSObjectPrincipalsFinder oldfop; - - oldfop = cx->findObjectPrincipals; - cx->findObjectPrincipals = fop; - return oldfop; -} - -JS_PUBLIC_API(JSFunction *) -JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags, - JSObject *parent, const char *name) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - - if (!name) { - atom = NULL; - } else { - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return NULL; - } - return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom); -} - -JS_PUBLIC_API(JSObject *) -JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent) -{ - CHECK_REQUEST(cx); - if (OBJ_GET_CLASS(cx, funobj) != &js_FunctionClass) { - /* Indicate we cannot clone this object. */ - return funobj; - } - return js_CloneFunctionObject(cx, funobj, parent); -} - -JS_PUBLIC_API(JSObject *) -JS_GetFunctionObject(JSFunction *fun) -{ - return fun->object; -} - -JS_PUBLIC_API(const char *) -JS_GetFunctionName(JSFunction *fun) -{ - return fun->atom - ? JS_GetStringBytes(ATOM_TO_STRING(fun->atom)) - : js_anonymous_str; -} - -JS_PUBLIC_API(JSString *) -JS_GetFunctionId(JSFunction *fun) -{ - return fun->atom ? ATOM_TO_STRING(fun->atom) : NULL; -} - -JS_PUBLIC_API(uintN) -JS_GetFunctionFlags(JSFunction *fun) -{ - return fun->flags; -} - -JS_PUBLIC_API(JSBool) -JS_ObjectIsFunction(JSContext *cx, JSObject *obj) -{ - return OBJ_GET_CLASS(cx, obj) == &js_FunctionClass; -} - -JS_PUBLIC_API(JSBool) -JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs) -{ - JSFunction *fun; - - CHECK_REQUEST(cx); - for (; fs->name; fs++) { - fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, - fs->flags); - if (!fun) - return JS_FALSE; - fun->extra = fs->extra; - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSFunction *) -JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call, - uintN nargs, uintN attrs) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, name, strlen(name), 0); - if (!atom) - return NULL; - return js_DefineFunction(cx, obj, atom, call, nargs, attrs); -} - -static JSScript * -CompileTokenStream(JSContext *cx, JSObject *obj, JSTokenStream *ts, - void *tempMark, JSBool *eofp) -{ - JSBool eof; - JSArenaPool codePool, notePool; - JSCodeGenerator cg; - JSScript *script; - - CHECK_REQUEST(cx); - eof = JS_FALSE; - JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode)); - JS_InitArenaPool(¬ePool, "note", 1024, sizeof(jssrcnote)); - if (!js_InitCodeGenerator(cx, &cg, &codePool, ¬ePool, - ts->filename, ts->lineno, - ts->principals)) { - script = NULL; - } else if (!js_CompileTokenStream(cx, obj, ts, &cg)) { - script = NULL; - eof = (ts->flags & TSF_EOF) != 0; - } else { - script = js_NewScriptFromCG(cx, &cg, NULL); - } - if (eofp) - *eofp = eof; - if (!js_CloseTokenStream(cx, ts)) { - if (script) - js_DestroyScript(cx, script); - script = NULL; - } - cg.tempMark = tempMark; - js_FinishCodeGenerator(cx, &cg); - JS_FinishArenaPool(&codePool); - JS_FinishArenaPool(¬ePool); - return script; -} - -JS_PUBLIC_API(JSScript *) -JS_CompileScript(JSContext *cx, JSObject *obj, - const char *bytes, size_t length, - const char *filename, uintN lineno) -{ - jschar *chars; - JSScript *script; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, length); - if (!chars) - return NULL; - script = JS_CompileUCScript(cx, obj, chars, length, filename, lineno); - JS_free(cx, chars); - return script; -} - -JS_PUBLIC_API(JSScript *) -JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, - const char *bytes, size_t length, - const char *filename, uintN lineno) -{ - jschar *chars; - JSScript *script; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, length); - if (!chars) - return NULL; - script = JS_CompileUCScriptForPrincipals(cx, obj, principals, - chars, length, filename, lineno); - JS_free(cx, chars); - return script; -} - -JS_PUBLIC_API(JSScript *) -JS_CompileUCScript(JSContext *cx, JSObject *obj, - const jschar *chars, size_t length, - const char *filename, uintN lineno) -{ - CHECK_REQUEST(cx); - return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length, - filename, lineno); -} - -JS_PUBLIC_API(JSScript *) -JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, - const jschar *chars, size_t length, - const char *filename, uintN lineno) -{ - void *mark; - JSTokenStream *ts; - JSScript *script; - - CHECK_REQUEST(cx); - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals); - if (!ts) - return NULL; - script = CompileTokenStream(cx, obj, ts, mark, NULL); -#if JS_HAS_EXCEPTIONS - if (!script && !cx->fp) - js_ReportUncaughtException(cx); -#endif - return script; -} - -JS_PUBLIC_API(JSBool) -JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, - const char *bytes, size_t length) -{ - jschar *chars; - JSBool result; - JSExceptionState *exnState; - void *tempMark; - JSTokenStream *ts; - JSErrorReporter older; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, length); - if (!chars) - return JS_TRUE; - - /* - * Return true on any out-of-memory error, so our caller doesn't try to - * collect more buffered source. - */ - result = JS_TRUE; - exnState = JS_SaveExceptionState(cx); - tempMark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewTokenStream(cx, chars, length, NULL, 0, NULL); - if (ts) { - older = JS_SetErrorReporter(cx, NULL); - if (!js_ParseTokenStream(cx, obj, ts)) { - /* - * We ran into an error. If it was because we ran out of source, - * we return false, so our caller will know to try to collect more - * buffered source. - */ - result = (ts->flags & TSF_EOF) == 0; - } - - JS_SetErrorReporter(cx, older); - js_CloseTokenStream(cx, ts); - JS_ARENA_RELEASE(&cx->tempPool, tempMark); - } - - JS_free(cx, chars); - JS_RestoreExceptionState(cx, exnState); - return result; -} - -JS_PUBLIC_API(JSScript *) -JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename) -{ - void *mark; - JSTokenStream *ts; - JSScript *script; - - CHECK_REQUEST(cx); - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewFileTokenStream(cx, filename, stdin); - if (!ts) - return NULL; - script = CompileTokenStream(cx, obj, ts, mark, NULL); -#if JS_HAS_EXCEPTIONS - if (!script && !cx->fp) - js_ReportUncaughtException(cx); -#endif - return script; -} - -JS_PUBLIC_API(JSScript *) -JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename, - FILE *file) -{ - return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, NULL); -} - -JS_PUBLIC_API(JSScript *) -JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj, - const char *filename, FILE *file, - JSPrincipals *principals) -{ - void *mark; - JSTokenStream *ts; - JSScript *script; - - CHECK_REQUEST(cx); - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewFileTokenStream(cx, NULL, file); - if (!ts) - return NULL; - ts->filename = filename; - /* XXXshaver js_NewFileTokenStream should do this, because it drops */ - if (principals) { - ts->principals = principals; - JSPRINCIPALS_HOLD(cx, ts->principals); - } - script = CompileTokenStream(cx, obj, ts, mark, NULL); -#if JS_HAS_EXCEPTIONS - if (!script && !cx->fp) - js_ReportUncaughtException(cx); -#endif - return script; -} - -JS_PUBLIC_API(JSObject *) -JS_NewScriptObject(JSContext *cx, JSScript *script) -{ - JSObject *obj; - - /* - * We use a dummy stack frame to protect the script from a GC caused - * by debugger-hook execution. - * - * XXX We really need a way to manage local roots and such more - * XXX automatically, at which point we can remove this one-off hack - * XXX and others within the engine. See bug 40757 for discussion. - */ - JSStackFrame dummy; - - CHECK_REQUEST(cx); - - memset(&dummy, 0, sizeof dummy); - dummy.down = cx->fp; - dummy.script = script; - cx->fp = &dummy; - - obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL); - - cx->fp = dummy.down; - if (!obj) - return NULL; - - if (script) { - if (!JS_SetPrivate(cx, obj, script)) - return NULL; - script->object = obj; - } - return obj; -} - -JS_PUBLIC_API(JSObject *) -JS_GetScriptObject(JSScript *script) -{ - return script->object; -} - -JS_PUBLIC_API(void) -JS_DestroyScript(JSContext *cx, JSScript *script) -{ - CHECK_REQUEST(cx); - js_DestroyScript(cx, script); -} - -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) -{ - jschar *chars; - JSFunction *fun; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, length); - if (!chars) - return NULL; - fun = JS_CompileUCFunction(cx, obj, name, nargs, argnames, chars, length, - filename, lineno); - JS_free(cx, chars); - return fun; -} - -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) -{ - jschar *chars; - JSFunction *fun; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, length); - if (!chars) - return NULL; - fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name, - nargs, argnames, chars, length, - filename, lineno); - JS_free(cx, chars); - return fun; -} - -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) -{ - CHECK_REQUEST(cx); - return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name, - nargs, argnames, - chars, length, - filename, lineno); -} - -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) -{ - void *mark; - JSTokenStream *ts; - JSFunction *fun; - JSAtom *funAtom, *argAtom; - uintN i; - - CHECK_REQUEST(cx); - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals); - if (!ts) { - fun = NULL; - goto out; - } - if (!name) { - funAtom = NULL; - } else { - funAtom = js_Atomize(cx, name, strlen(name), 0); - if (!funAtom) { - fun = NULL; - goto out; - } - } - fun = js_NewFunction(cx, NULL, NULL, nargs, 0, obj, funAtom); - if (!fun) - goto out; - if (nargs) { - for (i = 0; i < nargs; i++) { - argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0); - if (!argAtom) - break; - if (!js_AddNativeProperty(cx, fun->object, (jsid)argAtom, - js_GetArgument, js_SetArgument, - SPROP_INVALID_SLOT, - JSPROP_ENUMERATE | JSPROP_PERMANENT | - JSPROP_SHARED, - SPROP_HAS_SHORTID, i)) { - break; - } - } - if (i < nargs) { - fun = NULL; - goto out; - } - } - if (!js_CompileFunctionBody(cx, ts, fun)) { - fun = NULL; - goto out; - } - if (obj && funAtom) { - if (!OBJ_DEFINE_PROPERTY(cx, obj, (jsid)funAtom, - OBJECT_TO_JSVAL(fun->object), - NULL, NULL, 0, NULL)) { - return NULL; - } - } -out: - if (ts) - js_CloseTokenStream(cx, ts); - JS_ARENA_RELEASE(&cx->tempPool, mark); -#if JS_HAS_EXCEPTIONS - if (!fun && !cx->fp) - js_ReportUncaughtException(cx); -#endif - return fun; -} - -JS_PUBLIC_API(JSString *) -JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, - uintN indent) -{ - JSPrinter *jp; - JSString *str; - - CHECK_REQUEST(cx); - jp = js_NewPrinter(cx, name, - indent & ~JS_DONT_PRETTY_PRINT, - !(indent & JS_DONT_PRETTY_PRINT)); - if (!jp) - return NULL; - if (js_DecompileScript(jp, script)) - str = js_GetPrinterOutput(jp); - else - str = NULL; - js_DestroyPrinter(jp); - return str; -} - -JS_PUBLIC_API(JSString *) -JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent) -{ - JSPrinter *jp; - JSString *str; - - CHECK_REQUEST(cx); - jp = js_NewPrinter(cx, JS_GetFunctionName(fun), - indent & ~JS_DONT_PRETTY_PRINT, - !(indent & JS_DONT_PRETTY_PRINT)); - if (!jp) - return NULL; - if (js_DecompileFunction(jp, fun)) - str = js_GetPrinterOutput(jp); - else - str = NULL; - js_DestroyPrinter(jp); - return str; -} - -JS_PUBLIC_API(JSString *) -JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent) -{ - JSPrinter *jp; - JSString *str; - - CHECK_REQUEST(cx); - jp = js_NewPrinter(cx, JS_GetFunctionName(fun), - indent & ~JS_DONT_PRETTY_PRINT, - !(indent & JS_DONT_PRETTY_PRINT)); - if (!jp) - return NULL; - if (js_DecompileFunctionBody(jp, fun)) - str = js_GetPrinterOutput(jp); - else - str = NULL; - js_DestroyPrinter(jp); - return str; -} - -JS_PUBLIC_API(JSBool) -JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval) -{ - CHECK_REQUEST(cx); - if (!js_Execute(cx, obj, script, NULL, 0, rval)) { -#if JS_HAS_EXCEPTIONS - if (!cx->fp) - js_ReportUncaughtException(cx); -#endif - return JS_FALSE; - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script, - JSExecPart part, jsval *rval) -{ - JSScript tmp; - JSRuntime *rt; - JSBool ok; - - /* Make a temporary copy of the JSScript structure and farble it a bit. */ - tmp = *script; - if (part == JSEXEC_PROLOG) { - tmp.length = PTRDIFF(tmp.main, tmp.code, jsbytecode); - } else { - tmp.length -= PTRDIFF(tmp.main, tmp.code, jsbytecode); - tmp.code = tmp.main; - } - - /* Tell the debugger about our temporary copy of the script structure. */ - rt = cx->runtime; - if (rt->newScriptHook) { - rt->newScriptHook(cx, tmp.filename, tmp.lineno, &tmp, NULL, - rt->newScriptHookData); - } - - /* Execute the farbled struct and tell the debugger to forget about it. */ - ok = JS_ExecuteScript(cx, obj, &tmp, rval); - if (rt->destroyScriptHook) - rt->destroyScriptHook(cx, &tmp, rt->destroyScriptHookData); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_EvaluateScript(JSContext *cx, JSObject *obj, - const char *bytes, uintN length, - const char *filename, uintN lineno, - jsval *rval) -{ - jschar *chars; - JSBool ok; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, length); - if (!chars) - return JS_FALSE; - ok = JS_EvaluateUCScript(cx, obj, chars, length, filename, lineno, rval); - JS_free(cx, chars); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, - const char *bytes, uintN length, - const char *filename, uintN lineno, - jsval *rval) -{ - jschar *chars; - JSBool ok; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, length); - if (!chars) - return JS_FALSE; - ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length, - filename, lineno, rval); - JS_free(cx, chars); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_EvaluateUCScript(JSContext *cx, JSObject *obj, - const jschar *chars, uintN length, - const char *filename, uintN lineno, - jsval *rval) -{ - CHECK_REQUEST(cx); - return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length, - filename, lineno, rval); -} - -JS_PUBLIC_API(JSBool) -JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj, - JSPrincipals *principals, - const jschar *chars, uintN length, - const char *filename, uintN lineno, - jsval *rval) -{ - JSScript *script; - JSBool ok; - - CHECK_REQUEST(cx); - script = JS_CompileUCScriptForPrincipals(cx, obj, principals, chars, length, - filename, lineno); - if (!script) - return JS_FALSE; - ok = js_Execute(cx, obj, script, NULL, 0, rval); -#if JS_HAS_EXCEPTIONS - if (!ok && !cx->fp) - js_ReportUncaughtException(cx); -#endif - JS_DestroyScript(cx, script); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc, - jsval *argv, jsval *rval) -{ - CHECK_REQUEST(cx); - if (!js_InternalCall(cx, obj, OBJECT_TO_JSVAL(fun->object), argc, argv, - rval)) { -#if JS_HAS_EXCEPTIONS - if (!cx->fp) - js_ReportUncaughtException(cx); -#endif - return JS_FALSE; - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc, - jsval *argv, jsval *rval) -{ - jsval fval; - - CHECK_REQUEST(cx); - if (!JS_GetProperty(cx, obj, name, &fval)) - return JS_FALSE; - if (!js_InternalCall(cx, obj, fval, argc, argv, rval)) { -#if JS_HAS_EXCEPTIONS - if (!cx->fp) - js_ReportUncaughtException(cx); -#endif - return JS_FALSE; - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSBool) -JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc, - jsval *argv, jsval *rval) -{ - CHECK_REQUEST(cx); - if (!js_InternalCall(cx, obj, fval, argc, argv, rval)) { -#if JS_HAS_EXCEPTIONS - if (!cx->fp) - js_ReportUncaughtException(cx); -#endif - return JS_FALSE; - } - return JS_TRUE; -} - -JS_PUBLIC_API(JSBranchCallback) -JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb) -{ - JSBranchCallback oldcb; - - oldcb = cx->branchCallback; - cx->branchCallback = cb; - return oldcb; -} - -JS_PUBLIC_API(JSBool) -JS_IsRunning(JSContext *cx) -{ - return cx->fp != NULL; -} - -JS_PUBLIC_API(JSBool) -JS_IsConstructing(JSContext *cx) -{ - return cx->fp && (cx->fp->flags & JSFRAME_CONSTRUCTING); -} - -JS_FRIEND_API(JSBool) -JS_IsAssigning(JSContext *cx) -{ - JSStackFrame *fp; - jsbytecode *pc; - - for (fp = cx->fp; fp && !fp->script; fp = fp->down) - continue; - if (!fp || !(pc = fp->pc)) - return JS_FALSE; - return (js_CodeSpec[*pc].format & JOF_ASSIGNING) != 0; -} - -JS_PUBLIC_API(void) -JS_SetCallReturnValue2(JSContext *cx, jsval v) -{ -#if JS_HAS_LVALUE_RETURN - cx->rval2 = v; - cx->rval2set = JS_TRUE; -#endif -} - -/************************************************************************/ - -JS_PUBLIC_API(JSString *) -JS_NewString(JSContext *cx, char *bytes, size_t length) -{ - jschar *chars; - JSString *str; - - CHECK_REQUEST(cx); - /* Make a Unicode vector from the 8-bit char codes in bytes. */ - chars = js_InflateString(cx, bytes, length); - if (!chars) - return NULL; - - /* Free chars (but not bytes, which caller frees on error) if we fail. */ - str = js_NewString(cx, chars, length, 0); - if (!str) { - JS_free(cx, chars); - return NULL; - } - - /* Hand off bytes to the deflated string cache, if possible. */ - if (!js_SetStringBytes(str, bytes, length)) - JS_free(cx, bytes); - return str; -} - -JS_PUBLIC_API(JSString *) -JS_NewStringCopyN(JSContext *cx, const char *s, size_t n) -{ - jschar *js; - JSString *str; - - CHECK_REQUEST(cx); - js = js_InflateString(cx, s, n); - if (!js) - return NULL; - str = js_NewString(cx, js, n, 0); - if (!str) - JS_free(cx, js); - return str; -} - -JS_PUBLIC_API(JSString *) -JS_NewStringCopyZ(JSContext *cx, const char *s) -{ - size_t n; - jschar *js; - JSString *str; - - CHECK_REQUEST(cx); - if (!s) - return cx->runtime->emptyString; - n = strlen(s); - js = js_InflateString(cx, s, n); - if (!js) - return NULL; - str = js_NewString(cx, js, n, 0); - if (!str) - JS_free(cx, js); - return str; -} - -JS_PUBLIC_API(JSString *) -JS_InternString(JSContext *cx, const char *s) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_Atomize(cx, s, strlen(s), ATOM_INTERNED); - if (!atom) - return NULL; - return ATOM_TO_STRING(atom); -} - -JS_PUBLIC_API(JSString *) -JS_NewUCString(JSContext *cx, jschar *chars, size_t length) -{ - CHECK_REQUEST(cx); - return js_NewString(cx, chars, length, 0); -} - -JS_PUBLIC_API(JSString *) -JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n) -{ - CHECK_REQUEST(cx); - return js_NewStringCopyN(cx, s, n, 0); -} - -JS_PUBLIC_API(JSString *) -JS_NewUCStringCopyZ(JSContext *cx, const jschar *s) -{ - CHECK_REQUEST(cx); - if (!s) - return cx->runtime->emptyString; - return js_NewStringCopyZ(cx, s, 0); -} - -JS_PUBLIC_API(JSString *) -JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length) -{ - JSAtom *atom; - - CHECK_REQUEST(cx); - atom = js_AtomizeChars(cx, s, length, ATOM_INTERNED); - if (!atom) - return NULL; - return ATOM_TO_STRING(atom); -} - -JS_PUBLIC_API(JSString *) -JS_InternUCString(JSContext *cx, const jschar *s) -{ - return JS_InternUCStringN(cx, s, js_strlen(s)); -} - -JS_PUBLIC_API(char *) -JS_GetStringBytes(JSString *str) -{ - char *bytes; - - bytes = js_GetStringBytes(str); - return bytes ? bytes : ""; -} - -JS_PUBLIC_API(jschar *) -JS_GetStringChars(JSString *str) -{ - /* - * API botch (again, shades of JS_GetStringBytes): we have no cx to pass - * to js_UndependString (called by js_GetStringChars) for out-of-memory - * error reports, so js_UndependString passes NULL and suppresses errors. - * If it fails to convert a dependent string into an independent one, our - * caller will not be guaranteed a \u0000 terminator as a backstop. This - * may break some clients who already misbehave on embedded NULs. - * - * The gain of dependent strings, which cure quadratic and cubic growth - * rate bugs in string concatenation, is worth this slight loss in API - * compatibility. - */ - jschar *chars; - - chars = js_GetStringChars(str); - return chars ? chars : JSSTRING_CHARS(str); -} - -JS_PUBLIC_API(size_t) -JS_GetStringLength(JSString *str) -{ - return JSSTRING_LENGTH(str); -} - -JS_PUBLIC_API(intN) -JS_CompareStrings(JSString *str1, JSString *str2) -{ - return js_CompareStrings(str1, str2); -} - -JS_PUBLIC_API(JSString *) -JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length) -{ - CHECK_REQUEST(cx); - return js_NewString(cx, chars, length, GCF_MUTABLE); -} - -JS_PUBLIC_API(JSString *) -JS_NewDependentString(JSContext *cx, JSString *str, size_t start, - size_t length) -{ - CHECK_REQUEST(cx); - return js_NewDependentString(cx, str, start, length, 0); -} - -JS_PUBLIC_API(JSString *) -JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right) -{ - CHECK_REQUEST(cx); - return js_ConcatStrings(cx, left, right); -} - -JS_PUBLIC_API(const jschar *) -JS_UndependString(JSContext *cx, JSString *str) -{ - CHECK_REQUEST(cx); - return js_UndependString(cx, str); -} - -JS_PUBLIC_API(JSBool) -JS_MakeStringImmutable(JSContext *cx, JSString *str) -{ - CHECK_REQUEST(cx); - if (!js_UndependString(cx, str)) - return JS_FALSE; - - *js_GetGCThingFlags(str) &= ~GCF_MUTABLE; - return JS_TRUE; -} - -/************************************************************************/ - -JS_PUBLIC_API(void) -JS_ReportError(JSContext *cx, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap); - va_end(ap); -} - -JS_PUBLIC_API(void) -JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback, - void *userRef, const uintN errorNumber, ...) -{ - va_list ap; - - va_start(ap, errorNumber); - js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef, - errorNumber, JS_TRUE, ap); - va_end(ap); -} - -JS_PUBLIC_API(void) -JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback, - void *userRef, const uintN errorNumber, ...) -{ - va_list ap; - - va_start(ap, errorNumber); - js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef, - errorNumber, JS_FALSE, ap); - va_end(ap); -} - -JS_PUBLIC_API(JSBool) -JS_ReportWarning(JSContext *cx, const char *format, ...) -{ - va_list ap; - JSBool ok; - - va_start(ap, format); - ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap); - va_end(ap); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags, - JSErrorCallback errorCallback, void *userRef, - const uintN errorNumber, ...) -{ - va_list ap; - JSBool ok; - - va_start(ap, errorNumber); - ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef, - errorNumber, JS_TRUE, ap); - va_end(ap); - return ok; -} - -JS_PUBLIC_API(JSBool) -JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags, - JSErrorCallback errorCallback, void *userRef, - const uintN errorNumber, ...) -{ - va_list ap; - JSBool ok; - - va_start(ap, errorNumber); - ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef, - errorNumber, JS_FALSE, ap); - va_end(ap); - return ok; -} - -JS_PUBLIC_API(void) -JS_ReportOutOfMemory(JSContext *cx) -{ - js_ReportOutOfMemory(cx, js_GetErrorMessage); -} - -JS_PUBLIC_API(JSErrorReporter) -JS_SetErrorReporter(JSContext *cx, JSErrorReporter er) -{ - JSErrorReporter older; - - older = cx->errorReporter; - cx->errorReporter = er; - return older; -} - -/************************************************************************/ - -/* - * Regular Expressions. - */ -JS_PUBLIC_API(JSObject *) -JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags) -{ -#if JS_HAS_REGEXPS - jschar *chars; - JSObject *obj; - - CHECK_REQUEST(cx); - chars = js_InflateString(cx, bytes, length); - if (!chars) - return NULL; - obj = js_NewRegExpObject(cx, NULL, chars, length, flags); - JS_free(cx, chars); - return obj; -#else - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_REG_EXPS); - return NULL; -#endif -} - -JS_PUBLIC_API(JSObject *) -JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags) -{ - CHECK_REQUEST(cx); -#if JS_HAS_REGEXPS - return js_NewRegExpObject(cx, NULL, chars, length, flags); -#else - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_REG_EXPS); - return NULL; -#endif -} - -JS_PUBLIC_API(void) -JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline) -{ - JSRegExpStatics *res; - - CHECK_REQUEST(cx); - /* No locking required, cx is thread-private and input must be live. */ - res = &cx->regExpStatics; - res->input = input; - res->multiline = multiline; - cx->runtime->gcPoke = JS_TRUE; -} - -JS_PUBLIC_API(void) -JS_ClearRegExpStatics(JSContext *cx) -{ - JSRegExpStatics *res; - - /* No locking required, cx is thread-private and input must be live. */ - res = &cx->regExpStatics; - res->input = NULL; - res->multiline = JS_FALSE; - res->parenCount = 0; - res->lastMatch = res->lastParen = js_EmptySubString; - res->leftContext = res->rightContext = js_EmptySubString; - cx->runtime->gcPoke = JS_TRUE; -} - -JS_PUBLIC_API(void) -JS_ClearRegExpRoots(JSContext *cx) -{ - JSRegExpStatics *res; - - /* No locking required, cx is thread-private and input must be live. */ - res = &cx->regExpStatics; - res->input = NULL; - cx->runtime->gcPoke = JS_TRUE; -} - -/* TODO: compile, execute, get/set other statics... */ - -/************************************************************************/ - -JS_PUBLIC_API(void) -JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks) -{ - cx->localeCallbacks = callbacks; -} - -JS_PUBLIC_API(JSLocaleCallbacks *) -JS_GetLocaleCallbacks(JSContext *cx) -{ - return cx->localeCallbacks; -} - -/************************************************************************/ - -JS_PUBLIC_API(JSBool) -JS_IsExceptionPending(JSContext *cx) -{ -#if JS_HAS_EXCEPTIONS - return (JSBool) cx->throwing; -#else - return JS_FALSE; -#endif -} - -JS_PUBLIC_API(JSBool) -JS_GetPendingException(JSContext *cx, jsval *vp) -{ -#if JS_HAS_EXCEPTIONS - CHECK_REQUEST(cx); - if (!cx->throwing) - return JS_FALSE; - *vp = cx->exception; - return JS_TRUE; -#else - return JS_FALSE; -#endif -} - -JS_PUBLIC_API(void) -JS_SetPendingException(JSContext *cx, jsval v) -{ - CHECK_REQUEST(cx); -#if JS_HAS_EXCEPTIONS - cx->throwing = JS_TRUE; - cx->exception = v; -#endif -} - -JS_PUBLIC_API(void) -JS_ClearPendingException(JSContext *cx) -{ -#if JS_HAS_EXCEPTIONS - cx->throwing = JS_FALSE; - cx->exception = JSVAL_VOID; -#endif -} - -#if JS_HAS_EXCEPTIONS -struct JSExceptionState { - JSBool throwing; - jsval exception; -}; -#endif - -JS_PUBLIC_API(JSExceptionState *) -JS_SaveExceptionState(JSContext *cx) -{ -#if JS_HAS_EXCEPTIONS - JSExceptionState *state; - - CHECK_REQUEST(cx); - state = (JSExceptionState *) JS_malloc(cx, sizeof(JSExceptionState)); - if (state) { - state->throwing = JS_GetPendingException(cx, &state->exception); - if (state->throwing && JSVAL_IS_GCTHING(state->exception)) - js_AddRoot(cx, &state->exception, "JSExceptionState.exception"); - } - return state; -#else - return NULL; -#endif -} - -JS_PUBLIC_API(void) -JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state) -{ -#if JS_HAS_EXCEPTIONS - CHECK_REQUEST(cx); - if (state) { - if (state->throwing) - JS_SetPendingException(cx, state->exception); - else - JS_ClearPendingException(cx); - JS_DropExceptionState(cx, state); - } -#endif -} - -JS_PUBLIC_API(void) -JS_DropExceptionState(JSContext *cx, JSExceptionState *state) -{ -#if JS_HAS_EXCEPTIONS - CHECK_REQUEST(cx); - if (state) { - if (state->throwing && JSVAL_IS_GCTHING(state->exception)) - JS_RemoveRoot(cx, &state->exception); - JS_free(cx, state); - } -#endif -} - -JS_PUBLIC_API(JSErrorReport *) -JS_ErrorFromException(JSContext *cx, jsval v) -{ -#if JS_HAS_EXCEPTIONS - CHECK_REQUEST(cx); - return js_ErrorFromException(cx, v); -#else - return NULL; -#endif -} - -#ifdef JS_THREADSAFE -JS_PUBLIC_API(jsword) -JS_GetContextThread(JSContext *cx) -{ - return cx->thread; -} - -JS_PUBLIC_API(jsword) -JS_SetContextThread(JSContext *cx) -{ - intN old = cx->thread; - cx->thread = js_CurrentThreadId(); - return old; -} - -JS_PUBLIC_API(intN) -JS_ClearContextThread(JSContext *cx) -{ - intN old = cx->thread; - cx->thread = 0; - return old; -} -#endif - -/************************************************************************/ - -#if defined(XP_WIN) -#include <windows.h> -/* - * Initialization routine for the JS DLL... - */ - -/* - * Global Instance handle... - * In Win32 this is the module handle of the DLL. - * - * In Win16 this is the instance handle of the application - * which loaded the DLL. - */ - -#ifdef _WIN32 -BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved) -{ - return TRUE; -} - -#else /* !_WIN32 */ - -int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg, - WORD cbHeapSize, LPSTR lpszCmdLine ) -{ - return TRUE; -} - -BOOL CALLBACK __loadds WEP(BOOL fSystemExit) -{ - return TRUE; -} - -#endif /* !_WIN32 */ -#endif /* XP_WIN */ |
