📄 jsapi.c
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=78: * * ***** 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#if JS_HAS_XML_SUPPORT#include "jsxml.h"#endif#if JS_HAS_GENERATORS#include "jsiter.h"#endif#ifdef HAVE_VA_LIST_AS_ARRAY#define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(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)#endifJS_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 JSBoolTryArgumentFormatter(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': obj = js_ValueToFunctionObject(cx, sp, 0); if (!obj) return JS_FALSE; *va_arg(ap, JSFunction **) = (JSFunction *) JS_GetPrivate(cx, obj); 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; JSString *str; jsdouble d, *dp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -