Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: master
Fetching contributors…

Cannot retrieve contributors at this time

339 lines (281 sloc) 7.289 kB
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <js/jsapi.h>
#include "utf8.h"
#include "http.h"
int gExitCode = 0;
#ifdef JS_THREADSAFE
#define SETUP_REQUEST(cx) \
JS_SetContextThread(cx); \
JS_BeginRequest(cx);
#define FINISH_REQUEST(cx) \
JS_EndRequest(cx); \
JS_ClearContextThread(cx);
#else
#define SETUP_REQUEST(cx)
#define FINISH_REQUEST(cx)
#endif
static JSBool
evalcx(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
JSString *str;
JSObject *sandbox;
JSContext *subcx;
const jschar *src;
size_t srclen;
JSBool ret = JS_FALSE;
jsval v;
sandbox = NULL;
if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox))
{
return JS_FALSE;
}
subcx = JS_NewContext(JS_GetRuntime(cx), 8L * 1024L);
if(!subcx)
{
JS_ReportOutOfMemory(cx);
return JS_FALSE;
}
SETUP_REQUEST(subcx);
src = JS_GetStringChars(str);
srclen = JS_GetStringLength(str);
if(!sandbox)
{
sandbox = JS_NewObject(subcx, NULL, NULL, NULL);
if(!sandbox || !JS_InitStandardClasses(subcx, sandbox)) goto done;
}
if(srclen == 0)
{
*rval = OBJECT_TO_JSVAL(sandbox);
}
else
{
JS_EvaluateUCScript(subcx, sandbox, src, srclen, NULL, 0, rval);
}
ret = JS_TRUE;
done:
FINISH_REQUEST(subcx);
JS_DestroyContext(subcx);
return ret;
}
static JSBool
gc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
JS_GC(cx);
return JS_TRUE;
}
static JSBool
print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
uintN i;
char *bytes;
for(i = 0; i < argc; i++)
{
bytes = enc_string(cx, argv[i], NULL);
if(!bytes) return JS_FALSE;
fprintf(stdout, "%s%s", i ? " " : "", bytes);
JS_free(cx, bytes);
}
fputc('\n', stdout);
fflush(stdout);
return JS_TRUE;
}
static JSBool
quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
JS_ConvertArguments(cx, argc, argv, "/ i", &gExitCode);
return JS_FALSE;
}
static char*
readfp(JSContext* cx, FILE* fp, size_t* buflen)
{
char* bytes = NULL;
char* tmp = NULL;
size_t used = 0;
size_t byteslen = 256;
size_t readlen = 0;
bytes = JS_malloc(cx, byteslen);
if(bytes == NULL) return NULL;
while((readlen = js_fgets(bytes+used, byteslen-used, stdin)) > 0)
{
used += readlen;
if(bytes[used-1] == '\n')
{
bytes[used-1] = '\0';
break;
}
// Double our buffer and read more.
byteslen *= 2;
tmp = JS_realloc(cx, bytes, byteslen);
if(!tmp)
{
JS_free(cx, bytes);
return NULL;
}
bytes = tmp;
}
*buflen = used;
return bytes;
}
static JSBool
readline(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) {
jschar *chars;
JSString *str;
char* bytes;
char* tmp;
size_t byteslen;
/* GC Occasionally */
JS_MaybeGC(cx);
bytes = readfp(cx, stdin, &byteslen);
if(!bytes) return JS_FALSE;
/* Treat the empty string specially */
if(byteslen == 0)
{
*rval = JS_GetEmptyStringValue(cx);
JS_free(cx, bytes);
return JS_TRUE;
}
/* Shrink the buffer to the real size */
tmp = JS_realloc(cx, bytes, byteslen);
if(!tmp)
{
JS_free(cx, bytes);
return JS_FALSE;
}
bytes = tmp;
str = dec_string(cx, bytes, byteslen);
JS_free(cx, bytes);
if(!str) return JS_FALSE;
*rval = STRING_TO_JSVAL(str);
return JS_TRUE;
}
static JSBool
seal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) {
JSObject *target;
JSBool deep = JS_FALSE;
if (!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
return JS_FALSE;
if (!target)
return JS_TRUE;
return JS_SealObject(cx, target, deep);
}
static void
execute_script(JSContext *cx, JSObject *obj, const char *filename) {
FILE *file;
JSScript *script;
jsval result;
if(!filename || strcmp(filename, "-") == 0)
{
file = stdin;
}
else
{
file = fopen(filename, "r");
if (!file)
{
fprintf(stderr, "could not open script file %s\n", filename);
gExitCode = 1;
return;
}
}
script = JS_CompileFileHandle(cx, obj, filename, file);
if(script)
{
JS_ExecuteScript(cx, obj, script, &result);
JS_DestroyScript(cx, script);
}
}
static void
printerror(JSContext *cx, const char *mesg, JSErrorReport *report)
{
if(!report || !JSREPORT_IS_WARNING(report->flags))
{
fprintf(stderr, "%s\n", mesg);
}
}
static JSFunctionSpec global_functions[] = {
{"evalcx", evalcx, 0, 0, 0},
{"gc", gc, 0, 0, 0},
{"print", print, 0, 0, 0},
{"quit", quit, 0, 0, 0},
{"readline", readline, 0, 0, 0},
{"seal", seal, 0, 0, 0},
{0, 0, 0, 0, 0}
};
static JSClass global_class = {
"GlobalClass",
JSCLASS_GLOBAL_FLAGS,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
JS_FinalizeStub,
JSCLASS_NO_OPTIONAL_MEMBERS
};
int
main(int argc, const char * argv[])
{
JSRuntime* rt = NULL;
JSContext* cx = NULL;
JSObject* global = NULL;
JSFunctionSpec* sp = NULL;
int i = 0;
rt = JS_NewRuntime(64L * 1024L * 1024L);
if (!rt) return 1;
cx = JS_NewContext(rt, 8L * 1024L);
if (!cx) return 1;
JS_SetErrorReporter(cx, printerror);
JS_ToggleOptions(cx, JSOPTION_XML);
SETUP_REQUEST(cx);
global = JS_NewObject(cx, &global_class, NULL, NULL);
if (!global) return 1;
if (!JS_InitStandardClasses(cx, global)) return 1;
for(sp = global_functions; sp->name != NULL; sp++)
{
if(!JS_DefineFunction(cx, global,
sp->name, sp->call, sp->nargs, sp->flags))
{
fprintf(stderr, "Failed to create function: %s\n", sp->name);
return 1;
}
}
if(!install_http(cx, global))
{
return 1;
}
JS_SetGlobalObject(cx, global);
if(argc > 2)
{
fprintf(stderr, "incorrect number of arguments\n\n");
fprintf(stderr, "usage: %s <scriptfile>\n", argv[0]);
return 2;
}
if(argc == 0)
{
execute_script(cx, global, NULL);
}
else
{
execute_script(cx, global, argv[1]);
}
FINISH_REQUEST(cx);
JS_DestroyContext(cx);
JS_DestroyRuntime(rt);
JS_ShutDown();
return gExitCode;
}
Jump to Line
Something went wrong with that request. Please try again.