Bug 461841: Use configure-defined macros in #ifdefs for WinCE in js/src. r=crowder
[mozilla-central.git] / js / src / xpconnect / shell / xpcshell.cpp
blob322755d1fd99359bfcc495f165fef20fd2442fd3
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=2 sw=4 et tw=80:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
17 * The Original Code is Mozilla Communicator client code, released
18 * March 31, 1998.
20 * The Initial Developer of the Original Code is
21 * Netscape Communications Corporation.
22 * Portions created by the Initial Developer are Copyright (C) 1998
23 * the Initial Developer. All Rights Reserved.
25 * Contributor(s):
26 * John Bandhauer <jband@netscape.com>
27 * Pierre Phaneuf <pp@ludusdesign.com>
28 * IBM Corp.
29 * Dan Mosedale <dan.mosedale@oracle.com>
31 * Alternatively, the contents of this file may be used under the terms of
32 * either of the GNU General Public License Version 2 or later (the "GPL"),
33 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
34 * in which case the provisions of the GPL or the LGPL are applicable instead
35 * of those above. If you wish to allow use of your version of this file only
36 * under the terms of either the GPL or the LGPL, and not to allow others to
37 * use your version of this file under the terms of the MPL, indicate your
38 * decision by deleting the provisions above and replace them with the notice
39 * and other provisions required by the GPL or the LGPL. If you do not delete
40 * the provisions above, a recipient may use your version of this file under
41 * the terms of any one of the MPL, the GPL or the LGPL.
43 * ***** END LICENSE BLOCK ***** */
45 /* XPConnect JavaScript interactive shell. */
47 #include <stdio.h>
48 #include "nsServiceManagerUtils.h"
49 #include "nsComponentManagerUtils.h"
50 #include "nsIXPConnect.h"
51 #include "nsIXPCScriptable.h"
52 #include "nsIInterfaceInfo.h"
53 #include "nsIInterfaceInfoManager.h"
54 #include "nsIXPCScriptable.h"
55 #include "nsIServiceManager.h"
56 #include "nsIComponentManager.h"
57 #include "nsIComponentRegistrar.h"
58 #include "jsapi.h"
59 #include "jsdbgapi.h"
60 #include "jsprf.h"
61 #include "nscore.h"
62 #include "nsMemory.h"
63 #include "nsIGenericFactory.h"
64 #include "nsIJSRuntimeService.h"
65 #include "nsCOMPtr.h"
66 #include "nsAutoPtr.h"
67 #include "nsIXPCSecurityManager.h"
68 #ifdef XP_MACOSX
69 #include "xpcshellMacUtils.h"
70 #endif
72 #ifndef XPCONNECT_STANDALONE
73 #include "nsIScriptSecurityManager.h"
74 #include "nsIPrincipal.h"
75 #endif
77 // all this crap is needed to do the interactive shell stuff
78 #include <stdlib.h>
79 #include <errno.h>
80 #ifdef HAVE_IO_H
81 #include <io.h> /* for isatty() */
82 #endif
83 #ifdef HAVE_UNISTD_H
84 #include <unistd.h> /* for isatty() */
85 #endif
87 #include "nsIJSContextStack.h"
89 /***************************************************************************/
91 #ifdef JS_THREADSAFE
92 #define DoBeginRequest(cx) JS_BeginRequest((cx))
93 #define DoEndRequest(cx) JS_EndRequest((cx))
94 #else
95 #define DoBeginRequest(cx) ((void)0)
96 #define DoEndRequest(cx) ((void)0)
97 #endif
99 /***************************************************************************/
101 #define EXITCODE_RUNTIME_ERROR 3
102 #define EXITCODE_FILE_NOT_FOUND 4
104 FILE *gOutFile = NULL;
105 FILE *gErrFile = NULL;
106 FILE *gInFile = NULL;
108 int gExitCode = 0;
109 JSBool gQuitting = JS_FALSE;
110 static JSBool reportWarnings = JS_TRUE;
111 static JSBool compileOnly = JS_FALSE;
113 JSPrincipals *gJSPrincipals = nsnull;
115 static JSBool
116 GetLine(JSContext *cx, char *bufp, FILE *file, const char *prompt) {
117 #ifdef EDITLINE
119 * Use readline only if file is stdin, because there's no way to specify
120 * another handle. Are other filehandles interactive?
122 if (file == stdin) {
123 char *linep = readline(prompt);
124 if (!linep)
125 return JS_FALSE;
126 if (*linep)
127 add_history(linep);
128 strcpy(bufp, linep);
129 JS_free(cx, linep);
130 bufp += strlen(bufp);
131 *bufp++ = '\n';
132 *bufp = '\0';
133 } else
134 #endif
136 char line[256];
137 fprintf(gOutFile, prompt);
138 fflush(gOutFile);
139 if (!fgets(line, sizeof line, file))
140 return JS_FALSE;
141 strcpy(bufp, line);
143 return JS_TRUE;
146 static void
147 my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
149 int i, j, k, n;
150 char *prefix = NULL, *tmp;
151 const char *ctmp;
152 JSStackFrame * fp = nsnull;
153 nsCOMPtr<nsIXPConnect> xpc;
155 // Don't report an exception from inner JS frames as the callers may intend
156 // to handle it.
157 while ((fp = JS_FrameIterator(cx, &fp))) {
158 if (!JS_IsNativeFrame(cx, fp)) {
159 return;
163 // In some cases cx->fp is null here so use XPConnect to tell us about inner
164 // frames.
165 if ((xpc = do_GetService(nsIXPConnect::GetCID()))) {
166 nsAXPCNativeCallContext *cc = nsnull;
167 xpc->GetCurrentNativeCallContext(&cc);
168 if (cc) {
169 nsAXPCNativeCallContext *prev = cc;
170 while (NS_SUCCEEDED(prev->GetPreviousCallContext(&prev)) && prev) {
171 PRUint16 lang;
172 if (NS_SUCCEEDED(prev->GetLanguage(&lang)) &&
173 lang == nsAXPCNativeCallContext::LANG_JS) {
174 return;
180 if (!report) {
181 fprintf(gErrFile, "%s\n", message);
182 return;
185 /* Conditionally ignore reported warnings. */
186 if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings)
187 return;
189 if (report->filename)
190 prefix = JS_smprintf("%s:", report->filename);
191 if (report->lineno) {
192 tmp = prefix;
193 prefix = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno);
194 JS_free(cx, tmp);
196 if (JSREPORT_IS_WARNING(report->flags)) {
197 tmp = prefix;
198 prefix = JS_smprintf("%s%swarning: ",
199 tmp ? tmp : "",
200 JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
201 JS_free(cx, tmp);
204 /* embedded newlines -- argh! */
205 while ((ctmp = strchr(message, '\n')) != 0) {
206 ctmp++;
207 if (prefix) fputs(prefix, gErrFile);
208 fwrite(message, 1, ctmp - message, gErrFile);
209 message = ctmp;
211 /* If there were no filename or lineno, the prefix might be empty */
212 if (prefix)
213 fputs(prefix, gErrFile);
214 fputs(message, gErrFile);
216 if (!report->linebuf) {
217 fputc('\n', gErrFile);
218 goto out;
221 fprintf(gErrFile, ":\n%s%s\n%s", prefix, report->linebuf, prefix);
222 n = report->tokenptr - report->linebuf;
223 for (i = j = 0; i < n; i++) {
224 if (report->linebuf[i] == '\t') {
225 for (k = (j + 8) & ~7; j < k; j++) {
226 fputc('.', gErrFile);
228 continue;
230 fputc('.', gErrFile);
231 j++;
233 fputs("^\n", gErrFile);
234 out:
235 if (!JSREPORT_IS_WARNING(report->flags))
236 gExitCode = EXITCODE_RUNTIME_ERROR;
237 JS_free(cx, prefix);
240 static JSBool
241 ReadLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
243 // While 4096 might be quite arbitrary, this is something to be fixed in
244 // bug 105707. It is also the same limit as in ProcessFile.
245 char buf[4096];
246 JSString *str;
248 /* If a prompt was specified, construct the string */
249 if (argc > 0) {
250 str = JS_ValueToString(cx, argv[0]);
251 if (!str)
252 return JS_FALSE;
253 argv[0] = STRING_TO_JSVAL(str);
254 } else {
255 str = JSVAL_TO_STRING(JS_GetEmptyStringValue(cx));
258 /* Get a line from the infile */
259 if (!GetLine(cx, buf, gInFile, JS_GetStringBytes(str)))
260 return JS_FALSE;
262 /* Strip newline character added by GetLine() */
263 unsigned int buflen = strlen(buf);
264 if (buflen == 0) {
265 if (feof(gInFile)) {
266 *rval = JSVAL_NULL;
267 return JS_TRUE;
269 } else if (buf[buflen - 1] == '\n') {
270 --buflen;
273 /* Turn buf into a JSString */
274 str = JS_NewStringCopyN(cx, buf, buflen);
275 if (!str)
276 return JS_FALSE;
278 *rval = STRING_TO_JSVAL(str);
279 return JS_TRUE;
282 static JSBool
283 Print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
285 uintN i, n;
286 JSString *str;
288 for (i = n = 0; i < argc; i++) {
289 str = JS_ValueToString(cx, argv[i]);
290 if (!str)
291 return JS_FALSE;
292 fprintf(gOutFile, "%s%s", i ? " " : "", JS_GetStringBytes(str));
294 n++;
295 if (n)
296 fputc('\n', gOutFile);
297 return JS_TRUE;
300 static JSBool
301 Dump(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
303 JSString *str;
304 if (!argc)
305 return JS_TRUE;
307 str = JS_ValueToString(cx, argv[0]);
308 if (!str)
309 return JS_FALSE;
311 char *bytes = JS_GetStringBytes(str);
312 bytes = strdup(bytes);
314 fputs(bytes, gOutFile);
315 free(bytes);
316 return JS_TRUE;
319 static JSBool
320 Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
322 uintN i;
323 JSString *str;
324 const char *filename;
325 JSScript *script;
326 JSBool ok;
327 jsval result;
328 FILE *file;
330 for (i = 0; i < argc; i++) {
331 str = JS_ValueToString(cx, argv[i]);
332 if (!str)
333 return JS_FALSE;
334 argv[i] = STRING_TO_JSVAL(str);
335 filename = JS_GetStringBytes(str);
336 file = fopen(filename, "r");
337 script = JS_CompileFileHandleForPrincipals(cx, obj, filename, file,
338 gJSPrincipals);
339 if (!script)
340 ok = JS_FALSE;
341 else {
342 ok = !compileOnly
343 ? JS_ExecuteScript(cx, obj, script, &result)
344 : JS_TRUE;
345 JS_DestroyScript(cx, script);
347 if (!ok)
348 return JS_FALSE;
350 return JS_TRUE;
353 static JSBool
354 Version(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
356 if (argc > 0 && JSVAL_IS_INT(argv[0]))
357 *rval = INT_TO_JSVAL(JS_SetVersion(cx, JSVersion(JSVAL_TO_INT(argv[0]))));
358 else
359 *rval = INT_TO_JSVAL(JS_GetVersion(cx));
360 return JS_TRUE;
363 static JSBool
364 BuildDate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
366 fprintf(gOutFile, "built on %s at %s\n", __DATE__, __TIME__);
367 return JS_TRUE;
370 static JSBool
371 Quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
373 #ifdef LIVECONNECT
374 JSJ_SimpleShutdown();
375 #endif
377 gExitCode = 0;
378 JS_ConvertArguments(cx, argc, argv,"/ i", &gExitCode);
380 gQuitting = JS_TRUE;
381 // exit(0);
382 return JS_FALSE;
385 static JSBool
386 DumpXPC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
388 int32 depth = 2;
390 if (argc > 0) {
391 if (!JS_ValueToInt32(cx, argv[0], &depth))
392 return JS_FALSE;
395 nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
396 if(xpc)
397 xpc->DebugDump((int16)depth);
398 return JS_TRUE;
401 /* XXX needed only by GC() */
402 #include "jscntxt.h"
404 static JSBool
405 GC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
407 JSRuntime *rt;
408 uint32 preBytes;
410 rt = cx->runtime;
411 preBytes = rt->gcBytes;
412 JS_GC(cx);
413 fprintf(gOutFile, "before %lu, after %lu, break %08lx\n",
414 (unsigned long)preBytes, (unsigned long)rt->gcBytes,
415 #ifdef XP_UNIX
416 (unsigned long)sbrk(0)
417 #else
419 #endif
421 #ifdef JS_GCMETER
422 js_DumpGCStats(rt, stdout);
423 #endif
424 return JS_TRUE;
427 #ifdef DEBUG
429 static JSBool
430 DumpHeap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
432 char *fileName = NULL;
433 void* startThing = NULL;
434 uint32 startTraceKind = 0;
435 void *thingToFind = NULL;
436 size_t maxDepth = (size_t)-1;
437 void *thingToIgnore = NULL;
438 jsval *vp;
439 FILE *dumpFile;
440 JSBool ok;
442 vp = &argv[0];
443 if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
444 JSString *str;
446 str = JS_ValueToString(cx, *vp);
447 if (!str)
448 return JS_FALSE;
449 *vp = STRING_TO_JSVAL(str);
450 fileName = JS_GetStringBytes(str);
453 vp = &argv[1];
454 if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
455 if (!JSVAL_IS_TRACEABLE(*vp))
456 goto not_traceable_arg;
457 startThing = JSVAL_TO_TRACEABLE(*vp);
458 startTraceKind = JSVAL_TRACE_KIND(*vp);
461 vp = &argv[2];
462 if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
463 if (!JSVAL_IS_TRACEABLE(*vp))
464 goto not_traceable_arg;
465 thingToFind = JSVAL_TO_TRACEABLE(*vp);
468 vp = &argv[3];
469 if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
470 uint32 depth;
472 if (!JS_ValueToECMAUint32(cx, *vp, &depth))
473 return JS_FALSE;
474 maxDepth = depth;
477 vp = &argv[4];
478 if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
479 if (!JSVAL_IS_TRACEABLE(*vp))
480 goto not_traceable_arg;
481 thingToIgnore = JSVAL_TO_TRACEABLE(*vp);
484 if (!fileName) {
485 dumpFile = gOutFile;
486 } else {
487 dumpFile = fopen(fileName, "w");
488 if (!dumpFile) {
489 fprintf(gErrFile, "dumpHeap: can't open %s: %s\n",
490 fileName, strerror(errno));
491 return JS_FALSE;
495 ok = JS_DumpHeap(cx, dumpFile, startThing, startTraceKind, thingToFind,
496 maxDepth, thingToIgnore);
497 if (dumpFile != gOutFile)
498 fclose(dumpFile);
499 return ok;
501 not_traceable_arg:
502 fprintf(gErrFile,
503 "dumpHeap: argument %u is not null or a heap-allocated thing\n",
504 (unsigned)(vp - argv));
505 return JS_FALSE;
508 #endif /* DEBUG */
510 static JSBool
511 Clear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
513 if (argc > 0 && !JSVAL_IS_PRIMITIVE(argv[0])) {
514 JS_ClearScope(cx, JSVAL_TO_OBJECT(argv[0]));
515 } else {
516 JS_ReportError(cx, "'clear' requires an object");
517 return JS_FALSE;
519 return JS_TRUE;
522 static JSFunctionSpec glob_functions[] = {
523 {"print", Print, 0,0,0},
524 {"readline", ReadLine, 1,0,0},
525 {"load", Load, 1,0,0},
526 {"quit", Quit, 0,0,0},
527 {"version", Version, 1,0,0},
528 {"build", BuildDate, 0,0,0},
529 {"dumpXPC", DumpXPC, 1,0,0},
530 {"dump", Dump, 1,0,0},
531 {"gc", GC, 0,0,0},
532 {"clear", Clear, 1,0,0},
533 #ifdef DEBUG
534 {"dumpHeap", DumpHeap, 5,0,0},
535 #endif
536 #ifdef MOZ_SHARK
537 {"startShark", js_StartShark, 0,0,0},
538 {"stopShark", js_StopShark, 0,0,0},
539 {"connectShark", js_ConnectShark, 0,0,0},
540 {"disconnectShark", js_DisconnectShark, 0,0,0},
541 #endif
542 #ifdef MOZ_CALLGRIND
543 {"startCallgrind", js_StartCallgrind, 0,0,0},
544 {"stopCallgrind", js_StopCallgrind, 0,0,0},
545 {"dumpCallgrind", js_DumpCallgrind, 1,0,0},
546 #endif
547 {nsnull,nsnull,0,0,0}
550 JSClass global_class = {
551 "global", 0,
552 JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
553 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
556 static JSBool
557 env_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
559 /* XXX porting may be easy, but these don't seem to supply setenv by default */
560 #if !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS
561 JSString *idstr, *valstr;
562 const char *name, *value;
563 int rv;
565 idstr = JS_ValueToString(cx, id);
566 valstr = JS_ValueToString(cx, *vp);
567 if (!idstr || !valstr)
568 return JS_FALSE;
569 name = JS_GetStringBytes(idstr);
570 value = JS_GetStringBytes(valstr);
571 #if defined XP_WIN || defined HPUX || defined OSF1 || defined IRIX \
572 || defined SCO
574 char *waste = JS_smprintf("%s=%s", name, value);
575 if (!waste) {
576 JS_ReportOutOfMemory(cx);
577 return JS_FALSE;
579 rv = putenv(waste);
580 #ifdef XP_WIN
582 * HPUX9 at least still has the bad old non-copying putenv.
584 * Per mail from <s.shanmuganathan@digital.com>, OSF1 also has a putenv
585 * that will crash if you pass it an auto char array (so it must place
586 * its argument directly in the char *environ[] array).
588 free(waste);
589 #endif
591 #else
592 rv = setenv(name, value, 1);
593 #endif
594 if (rv < 0) {
595 JS_ReportError(cx, "can't set envariable %s to %s", name, value);
596 return JS_FALSE;
598 *vp = STRING_TO_JSVAL(valstr);
599 #endif /* !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS */
600 return JS_TRUE;
603 static JSBool
604 env_enumerate(JSContext *cx, JSObject *obj)
606 static JSBool reflected;
607 char **evp, *name, *value;
608 JSString *valstr;
609 JSBool ok;
611 if (reflected)
612 return JS_TRUE;
614 for (evp = (char **)JS_GetPrivate(cx, obj); (name = *evp) != NULL; evp++) {
615 value = strchr(name, '=');
616 if (!value)
617 continue;
618 *value++ = '\0';
619 valstr = JS_NewStringCopyZ(cx, value);
620 if (!valstr) {
621 ok = JS_FALSE;
622 } else {
623 ok = JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr),
624 NULL, NULL, JSPROP_ENUMERATE);
626 value[-1] = '=';
627 if (!ok)
628 return JS_FALSE;
631 reflected = JS_TRUE;
632 return JS_TRUE;
635 static JSBool
636 env_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
637 JSObject **objp)
639 JSString *idstr, *valstr;
640 const char *name, *value;
642 if (flags & JSRESOLVE_ASSIGNING)
643 return JS_TRUE;
645 idstr = JS_ValueToString(cx, id);
646 if (!idstr)
647 return JS_FALSE;
648 name = JS_GetStringBytes(idstr);
649 value = getenv(name);
650 if (value) {
651 valstr = JS_NewStringCopyZ(cx, value);
652 if (!valstr)
653 return JS_FALSE;
654 if (!JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr),
655 NULL, NULL, JSPROP_ENUMERATE)) {
656 return JS_FALSE;
658 *objp = obj;
660 return JS_TRUE;
663 static JSClass env_class = {
664 "environment", JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
665 JS_PropertyStub, JS_PropertyStub,
666 JS_PropertyStub, env_setProperty,
667 env_enumerate, (JSResolveOp) env_resolve,
668 JS_ConvertStub, JS_FinalizeStub
671 /***************************************************************************/
673 typedef enum JSShellErrNum {
674 #define MSG_DEF(name, number, count, exception, format) \
675 name = number,
676 #include "jsshell.msg"
677 #undef MSG_DEF
678 JSShellErr_Limit
679 #undef MSGDEF
680 } JSShellErrNum;
682 JSErrorFormatString jsShell_ErrorFormatString[JSErr_Limit] = {
683 #define MSG_DEF(name, number, count, exception, format) \
684 { format, count } ,
685 #include "jsshell.msg"
686 #undef MSG_DEF
689 static const JSErrorFormatString *
690 my_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber)
692 if ((errorNumber > 0) && (errorNumber < JSShellErr_Limit))
693 return &jsShell_ErrorFormatString[errorNumber];
694 else
695 return NULL;
698 #ifdef EDITLINE
699 extern "C" {
700 extern char *readline(const char *prompt);
701 extern void add_history(char *line);
703 #endif
706 static void
707 ProcessFile(JSContext *cx, JSObject *obj, const char *filename, FILE *file,
708 JSBool forceTTY)
710 JSScript *script;
711 jsval result;
712 int lineno, startline;
713 JSBool ok, hitEOF;
714 char *bufp, buffer[4096];
715 JSString *str;
717 if (forceTTY) {
718 file = stdin;
720 #ifdef HAVE_ISATTY
721 else if (!isatty(fileno(file))) {
723 * It's not interactive - just execute it.
725 * Support the UNIX #! shell hack; gobble the first line if it starts
726 * with '#'. TODO - this isn't quite compatible with sharp variables,
727 * as a legal js program (using sharp variables) might start with '#'.
728 * But that would require multi-character lookahead.
730 int ch = fgetc(file);
731 if (ch == '#') {
732 while((ch = fgetc(file)) != EOF) {
733 if(ch == '\n' || ch == '\r')
734 break;
737 ungetc(ch, file);
738 DoBeginRequest(cx);
740 script = JS_CompileFileHandleForPrincipals(cx, obj, filename, file,
741 gJSPrincipals);
743 if (script) {
744 if (!compileOnly)
745 (void)JS_ExecuteScript(cx, obj, script, &result);
746 JS_DestroyScript(cx, script);
748 DoEndRequest(cx);
750 return;
752 #endif
754 /* It's an interactive filehandle; drop into read-eval-print loop. */
755 lineno = 1;
756 hitEOF = JS_FALSE;
757 do {
758 bufp = buffer;
759 *bufp = '\0';
762 * Accumulate lines until we get a 'compilable unit' - one that either
763 * generates an error (before running out of source) or that compiles
764 * cleanly. This should be whenever we get a complete statement that
765 * coincides with the end of a line.
767 startline = lineno;
768 do {
769 if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) {
770 hitEOF = JS_TRUE;
771 break;
773 bufp += strlen(bufp);
774 lineno++;
775 } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
777 DoBeginRequest(cx);
778 /* Clear any pending exception from previous failed compiles. */
779 JS_ClearPendingException(cx);
780 script = JS_CompileScriptForPrincipals(cx, obj, gJSPrincipals, buffer,
781 strlen(buffer), "typein", startline);
782 if (script) {
783 JSErrorReporter older;
785 if (!compileOnly) {
786 ok = JS_ExecuteScript(cx, obj, script, &result);
787 if (ok && result != JSVAL_VOID) {
788 /* Suppress error reports from JS_ValueToString(). */
789 older = JS_SetErrorReporter(cx, NULL);
790 str = JS_ValueToString(cx, result);
791 JS_SetErrorReporter(cx, older);
793 if (str)
794 fprintf(gOutFile, "%s\n", JS_GetStringBytes(str));
795 else
796 ok = JS_FALSE;
799 JS_DestroyScript(cx, script);
801 DoEndRequest(cx);
802 } while (!hitEOF && !gQuitting);
804 fprintf(gOutFile, "\n");
807 static void
808 Process(JSContext *cx, JSObject *obj, const char *filename, JSBool forceTTY)
810 FILE *file;
812 if (forceTTY || !filename || strcmp(filename, "-") == 0) {
813 file = stdin;
814 } else {
815 file = fopen(filename, "r");
816 if (!file) {
817 JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
818 JSSMSG_CANT_OPEN,
819 filename, strerror(errno));
820 gExitCode = EXITCODE_FILE_NOT_FOUND;
821 return;
825 ProcessFile(cx, obj, filename, file, forceTTY);
828 static int
829 usage(void)
831 fprintf(gErrFile, "%s\n", JS_GetImplementationVersion());
832 fprintf(gErrFile, "usage: xpcshell [-PswWxCij] [-v version] [-f scriptfile] [-e script] [scriptfile] [scriptarg...]\n");
833 return 2;
836 extern JSClass global_class;
838 static int
839 ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
841 const char rcfilename[] = "xpcshell.js";
842 FILE *rcfile;
843 int i, j, length;
844 JSObject *argsObj;
845 char *filename = NULL;
846 JSBool isInteractive = JS_TRUE;
847 JSBool forceTTY = JS_FALSE;
849 rcfile = fopen(rcfilename, "r");
850 if (rcfile) {
851 printf("[loading '%s'...]\n", rcfilename);
852 ProcessFile(cx, obj, rcfilename, rcfile, JS_FALSE);
856 * Scan past all optional arguments so we can create the arguments object
857 * before processing any -f options, which must interleave properly with
858 * -v and -w options. This requires two passes, and without getopt, we'll
859 * have to keep the option logic here and in the second for loop in sync.
861 for (i = 0; i < argc; i++) {
862 if (argv[i][0] != '-' || argv[i][1] == '\0') {
863 ++i;
864 break;
866 switch (argv[i][1]) {
867 case 'v':
868 case 'f':
869 case 'e':
870 ++i;
871 break;
872 default:;
877 * Create arguments early and define it to root it, so it's safe from any
878 * GC calls nested below, and so it is available to -f <file> arguments.
880 argsObj = JS_NewArrayObject(cx, 0, NULL);
881 if (!argsObj)
882 return 1;
883 if (!JS_DefineProperty(cx, obj, "arguments", OBJECT_TO_JSVAL(argsObj),
884 NULL, NULL, 0)) {
885 return 1;
888 length = argc - i;
889 for (j = 0; j < length; j++) {
890 JSString *str = JS_NewStringCopyZ(cx, argv[i++]);
891 if (!str)
892 return 1;
893 if (!JS_DefineElement(cx, argsObj, j, STRING_TO_JSVAL(str),
894 NULL, NULL, JSPROP_ENUMERATE)) {
895 return 1;
899 for (i = 0; i < argc; i++) {
900 if (argv[i][0] != '-' || argv[i][1] == '\0') {
901 filename = argv[i++];
902 isInteractive = JS_FALSE;
903 break;
905 switch (argv[i][1]) {
906 case 'v':
907 if (++i == argc) {
908 return usage();
910 JS_SetVersion(cx, JSVersion(atoi(argv[i])));
911 break;
912 case 'W':
913 reportWarnings = JS_FALSE;
914 break;
915 case 'w':
916 reportWarnings = JS_TRUE;
917 break;
918 case 's':
919 JS_ToggleOptions(cx, JSOPTION_STRICT);
920 break;
921 case 'x':
922 JS_ToggleOptions(cx, JSOPTION_XML);
923 break;
924 case 'P':
925 if (JS_GET_CLASS(cx, JS_GetPrototype(cx, obj)) != &global_class) {
926 JSObject *gobj;
928 if (!JS_SealObject(cx, obj, JS_TRUE))
929 return JS_FALSE;
930 gobj = JS_NewObject(cx, &global_class, NULL, NULL);
931 if (!gobj)
932 return JS_FALSE;
933 if (!JS_SetPrototype(cx, gobj, obj))
934 return JS_FALSE;
935 JS_SetParent(cx, gobj, NULL);
936 JS_SetGlobalObject(cx, gobj);
937 obj = gobj;
939 break;
940 case 'f':
941 if (++i == argc) {
942 return usage();
944 Process(cx, obj, argv[i], JS_FALSE);
946 * XXX: js -f foo.js should interpret foo.js and then
947 * drop into interactive mode, but that breaks test
948 * harness. Just execute foo.js for now.
950 isInteractive = JS_FALSE;
951 break;
952 case 'i':
953 isInteractive = forceTTY = JS_TRUE;
954 break;
955 case 'e':
957 jsval rval;
959 if (++i == argc) {
960 return usage();
963 JS_EvaluateScript(cx, obj, argv[i], strlen(argv[i]),
964 "-e", 1, &rval);
966 isInteractive = JS_FALSE;
967 break;
969 case 'C':
970 compileOnly = JS_TRUE;
971 isInteractive = JS_FALSE;
972 break;
973 case 'j':
974 JS_ToggleOptions(cx, JSOPTION_JIT);
975 break;
976 #ifdef MOZ_SHARK
977 case 'k':
978 JS_ConnectShark();
979 break;
980 #endif
981 default:
982 return usage();
986 if (filename || isInteractive)
987 Process(cx, obj, filename, forceTTY);
988 return gExitCode;
991 /***************************************************************************/
993 class FullTrustSecMan
994 #ifndef XPCONNECT_STANDALONE
995 : public nsIScriptSecurityManager
996 #else
997 : public nsIXPCSecurityManager
998 #endif
1000 public:
1001 NS_DECL_ISUPPORTS
1002 NS_DECL_NSIXPCSECURITYMANAGER
1003 #ifndef XPCONNECT_STANDALONE
1004 NS_DECL_NSISCRIPTSECURITYMANAGER
1005 #endif
1007 FullTrustSecMan();
1008 virtual ~FullTrustSecMan();
1010 #ifndef XPCONNECT_STANDALONE
1011 void SetSystemPrincipal(nsIPrincipal *aPrincipal) {
1012 mSystemPrincipal = aPrincipal;
1015 private:
1016 nsCOMPtr<nsIPrincipal> mSystemPrincipal;
1017 #endif
1020 NS_INTERFACE_MAP_BEGIN(FullTrustSecMan)
1021 NS_INTERFACE_MAP_ENTRY(nsIXPCSecurityManager)
1022 #ifndef XPCONNECT_STANDALONE
1023 NS_INTERFACE_MAP_ENTRY(nsIScriptSecurityManager)
1024 #endif
1025 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCSecurityManager)
1026 NS_INTERFACE_MAP_END
1028 NS_IMPL_ADDREF(FullTrustSecMan)
1029 NS_IMPL_RELEASE(FullTrustSecMan)
1031 FullTrustSecMan::FullTrustSecMan()
1033 #ifndef XPCONNECT_STANDALONE
1034 mSystemPrincipal = nsnull;
1035 #endif
1038 FullTrustSecMan::~FullTrustSecMan()
1042 NS_IMETHODIMP
1043 FullTrustSecMan::CanCreateWrapper(JSContext * aJSContext, const nsIID & aIID,
1044 nsISupports *aObj, nsIClassInfo *aClassInfo,
1045 void * *aPolicy)
1047 return NS_OK;
1050 NS_IMETHODIMP
1051 FullTrustSecMan::CanCreateInstance(JSContext * aJSContext, const nsCID & aCID)
1053 return NS_OK;
1056 NS_IMETHODIMP
1057 FullTrustSecMan::CanGetService(JSContext * aJSContext, const nsCID & aCID)
1059 return NS_OK;
1062 #ifndef XPCONNECT_STANDALONE
1063 /* void CanAccess (in PRUint32 aAction, in nsIXPCNativeCallContext aCallContext, in JSContextPtr aJSContext, in JSObjectPtr aJSObject, in nsISupports aObj, in nsIClassInfo aClassInfo, in JSVal aName, inout voidPtr aPolicy); */
1064 NS_IMETHODIMP
1065 FullTrustSecMan::CanAccess(PRUint32 aAction,
1066 nsAXPCNativeCallContext *aCallContext,
1067 JSContext * aJSContext, JSObject * aJSObject,
1068 nsISupports *aObj, nsIClassInfo *aClassInfo,
1069 jsval aName, void * *aPolicy)
1071 return NS_OK;
1074 /* [noscript] void checkPropertyAccess (in JSContextPtr aJSContext, in JSObjectPtr aJSObject, in string aClassName, in JSVal aProperty, in PRUint32 aAction); */
1075 NS_IMETHODIMP
1076 FullTrustSecMan::CheckPropertyAccess(JSContext * aJSContext,
1077 JSObject * aJSObject,
1078 const char *aClassName,
1079 jsval aProperty, PRUint32 aAction)
1081 return NS_OK;
1084 /* [noscript] void checkConnect (in JSContextPtr aJSContext, in nsIURI aTargetURI, in string aClassName, in string aProperty); */
1085 NS_IMETHODIMP
1086 FullTrustSecMan::CheckConnect(JSContext * aJSContext, nsIURI *aTargetURI,
1087 const char *aClassName, const char *aProperty)
1089 return NS_OK;
1092 /* [noscript] void checkLoadURIFromScript (in JSContextPtr cx, in nsIURI uri); */
1093 NS_IMETHODIMP
1094 FullTrustSecMan::CheckLoadURIFromScript(JSContext * cx, nsIURI *uri)
1096 return NS_OK;
1099 /* void checkLoadURIWithPrincipal (in nsIPrincipal aPrincipal, in nsIURI uri, in unsigned long flags); */
1100 NS_IMETHODIMP
1101 FullTrustSecMan::CheckLoadURIWithPrincipal(nsIPrincipal *aPrincipal,
1102 nsIURI *uri, PRUint32 flags)
1104 return NS_OK;
1107 /* void checkLoadURI (in nsIURI from, in nsIURI uri, in unsigned long flags); */
1108 NS_IMETHODIMP
1109 FullTrustSecMan::CheckLoadURI(nsIURI *from, nsIURI *uri, PRUint32 flags)
1111 return NS_OK;
1114 /* void checkLoadURIStrWithPrincipal (in nsIPrincipal aPrincipal, in AUTF8String uri, in unsigned long flags); */
1115 NS_IMETHODIMP
1116 FullTrustSecMan::CheckLoadURIStrWithPrincipal(nsIPrincipal *aPrincipal,
1117 const nsACString & uri,
1118 PRUint32 flags)
1120 return NS_OK;
1123 /* void checkLoadURIStr (in AUTF8String from, in AUTF8String uri, in unsigned long flags); */
1124 NS_IMETHODIMP
1125 FullTrustSecMan::CheckLoadURIStr(const nsACString & from,
1126 const nsACString & uri, PRUint32 flags)
1128 return NS_OK;
1131 /* [noscript] void checkFunctionAccess (in JSContextPtr cx, in voidPtr funObj, in voidPtr targetObj); */
1132 NS_IMETHODIMP
1133 FullTrustSecMan::CheckFunctionAccess(JSContext * cx, void * funObj,
1134 void * targetObj)
1136 return NS_OK;
1139 /* [noscript] boolean canExecuteScripts (in JSContextPtr cx, in nsIPrincipal principal); */
1140 NS_IMETHODIMP
1141 FullTrustSecMan::CanExecuteScripts(JSContext * cx, nsIPrincipal *principal,
1142 PRBool *_retval)
1144 *_retval = PR_TRUE;
1145 return NS_OK;
1148 /* [noscript] nsIPrincipal getSubjectPrincipal (); */
1149 NS_IMETHODIMP
1150 FullTrustSecMan::GetSubjectPrincipal(nsIPrincipal **_retval)
1152 NS_IF_ADDREF(*_retval = mSystemPrincipal);
1153 return *_retval ? NS_OK : NS_ERROR_FAILURE;
1156 /* [noscript] nsIPrincipal getSystemPrincipal (); */
1157 NS_IMETHODIMP
1158 FullTrustSecMan::GetSystemPrincipal(nsIPrincipal **_retval)
1160 NS_IF_ADDREF(*_retval = mSystemPrincipal);
1161 return *_retval ? NS_OK : NS_ERROR_FAILURE;
1164 /* [noscript] nsIPrincipal getCertificatePrincipal (in AUTF8String aCertFingerprint, in AUTF8String aSubjectName, in AUTF8String aPrettyName, in nsISupports aCert, in nsIURI aURI); */
1165 NS_IMETHODIMP
1166 FullTrustSecMan::GetCertificatePrincipal(const nsACString & aCertFingerprint,
1167 const nsACString & aSubjectName,
1168 const nsACString & aPrettyName,
1169 nsISupports *aCert, nsIURI *aURI,
1170 nsIPrincipal **_retval)
1172 NS_IF_ADDREF(*_retval = mSystemPrincipal);
1173 return *_retval ? NS_OK : NS_ERROR_FAILURE;
1176 /* [noscript] nsIPrincipal getCodebasePrincipal (in nsIURI aURI); */
1177 NS_IMETHODIMP
1178 FullTrustSecMan::GetCodebasePrincipal(nsIURI *aURI, nsIPrincipal **_retval)
1180 NS_IF_ADDREF(*_retval = mSystemPrincipal);
1181 return *_retval ? NS_OK : NS_ERROR_FAILURE;
1184 /* [noscript] short requestCapability (in nsIPrincipal principal, in string capability); */
1185 NS_IMETHODIMP
1186 FullTrustSecMan::RequestCapability(nsIPrincipal *principal,
1187 const char *capability, PRInt16 *_retval)
1189 *_retval = nsIPrincipal::ENABLE_GRANTED;
1190 return NS_OK;
1193 /* boolean isCapabilityEnabled (in string capability); */
1194 NS_IMETHODIMP
1195 FullTrustSecMan::IsCapabilityEnabled(const char *capability, PRBool *_retval)
1197 *_retval = PR_TRUE;
1198 return NS_OK;
1201 /* void enableCapability (in string capability); */
1202 NS_IMETHODIMP
1203 FullTrustSecMan::EnableCapability(const char *capability)
1205 return NS_OK;;
1208 /* void revertCapability (in string capability); */
1209 NS_IMETHODIMP
1210 FullTrustSecMan::RevertCapability(const char *capability)
1212 return NS_OK;
1215 /* void disableCapability (in string capability); */
1216 NS_IMETHODIMP
1217 FullTrustSecMan::DisableCapability(const char *capability)
1219 return NS_OK;
1222 /* void setCanEnableCapability (in AUTF8String certificateFingerprint, in string capability, in short canEnable); */
1223 NS_IMETHODIMP
1224 FullTrustSecMan::SetCanEnableCapability(const nsACString & certificateFingerprint,
1225 const char *capability,
1226 PRInt16 canEnable)
1228 return NS_OK;
1231 /* [noscript] nsIPrincipal getObjectPrincipal (in JSContextPtr cx, in JSObjectPtr obj); */
1232 NS_IMETHODIMP
1233 FullTrustSecMan::GetObjectPrincipal(JSContext * cx, JSObject * obj,
1234 nsIPrincipal **_retval)
1236 NS_IF_ADDREF(*_retval = mSystemPrincipal);
1237 return *_retval ? NS_OK : NS_ERROR_FAILURE;
1240 /* [noscript] boolean subjectPrincipalIsSystem (); */
1241 NS_IMETHODIMP
1242 FullTrustSecMan::SubjectPrincipalIsSystem(PRBool *_retval)
1244 *_retval = PR_TRUE;
1245 return NS_OK;
1248 /* [noscript] void checkSameOrigin (in JSContextPtr aJSContext, in nsIURI aTargetURI); */
1249 NS_IMETHODIMP
1250 FullTrustSecMan::CheckSameOrigin(JSContext * aJSContext, nsIURI *aTargetURI)
1252 return NS_OK;
1255 /* void checkSameOriginURI (in nsIURI aSourceURI, in nsIURI aTargetURI); */
1256 NS_IMETHODIMP
1257 FullTrustSecMan::CheckSameOriginURI(nsIURI *aSourceURI, nsIURI *aTargetURI,
1258 PRBool reportError)
1260 return NS_OK;
1263 /* [noscript] nsIPrincipal getPrincipalFromContext (in JSContextPtr cx); */
1264 NS_IMETHODIMP
1265 FullTrustSecMan::GetPrincipalFromContext(JSContext * cx, nsIPrincipal **_retval)
1267 NS_IF_ADDREF(*_retval = mSystemPrincipal);
1268 return *_retval ? NS_OK : NS_ERROR_FAILURE;
1271 /* [noscript] nsIPrincipal getChannelPrincipal (in nsIChannel aChannel); */
1272 NS_IMETHODIMP
1273 FullTrustSecMan::GetChannelPrincipal(nsIChannel *aChannel, nsIPrincipal **_retval)
1275 NS_IF_ADDREF(*_retval = mSystemPrincipal);
1276 return *_retval ? NS_OK : NS_ERROR_FAILURE;
1279 /* boolean isSystemPrincipal (in nsIPrincipal aPrincipal); */
1280 NS_IMETHODIMP
1281 FullTrustSecMan::IsSystemPrincipal(nsIPrincipal *aPrincipal, PRBool *_retval)
1283 *_retval = aPrincipal == mSystemPrincipal;
1284 return NS_OK;
1287 NS_IMETHODIMP_(nsIPrincipal *)
1288 FullTrustSecMan::GetCxSubjectPrincipal(JSContext *cx)
1290 return mSystemPrincipal;
1293 NS_IMETHODIMP_(nsIPrincipal *)
1294 FullTrustSecMan::GetCxSubjectPrincipalAndFrame(JSContext *cx, JSStackFrame **fp)
1296 *fp = nsnull;
1297 return mSystemPrincipal;
1300 #endif
1302 /***************************************************************************/
1304 // #define TEST_InitClassesWithNewWrappedGlobal
1306 #ifdef TEST_InitClassesWithNewWrappedGlobal
1307 // XXX hacky test code...
1308 #include "xpctest.h"
1310 class TestGlobal : public nsIXPCTestNoisy, public nsIXPCScriptable
1312 public:
1313 NS_DECL_ISUPPORTS
1314 NS_DECL_NSIXPCTESTNOISY
1315 NS_DECL_NSIXPCSCRIPTABLE
1317 TestGlobal(){}
1320 NS_IMPL_ISUPPORTS2(TestGlobal, nsIXPCTestNoisy, nsIXPCScriptable)
1322 // The nsIXPCScriptable map declaration that will generate stubs for us...
1323 #define XPC_MAP_CLASSNAME TestGlobal
1324 #define XPC_MAP_QUOTED_CLASSNAME "TestGlobal"
1325 #define XPC_MAP_FLAGS nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY |\
1326 nsIXPCScriptable::USE_JSSTUB_FOR_DELPROPERTY |\
1327 nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY
1328 #include "xpc_map_end.h" /* This will #undef the above */
1330 NS_IMETHODIMP TestGlobal::Squawk() {return NS_OK;}
1332 #endif
1334 // uncomment to install the test 'this' translator
1335 // #define TEST_TranslateThis
1337 #ifdef TEST_TranslateThis
1339 #include "xpctest.h"
1341 class nsXPCFunctionThisTranslator : public nsIXPCFunctionThisTranslator
1343 public:
1344 NS_DECL_ISUPPORTS
1345 NS_DECL_NSIXPCFUNCTIONTHISTRANSLATOR
1347 nsXPCFunctionThisTranslator();
1348 virtual ~nsXPCFunctionThisTranslator();
1349 /* additional members */
1352 /* Implementation file */
1353 NS_IMPL_ISUPPORTS1(nsXPCFunctionThisTranslator, nsIXPCFunctionThisTranslator)
1355 nsXPCFunctionThisTranslator::nsXPCFunctionThisTranslator()
1357 /* member initializers and constructor code */
1360 nsXPCFunctionThisTranslator::~nsXPCFunctionThisTranslator()
1362 /* destructor code */
1363 #ifdef DEBUG_jband
1364 printf("destroying nsXPCFunctionThisTranslator\n");
1365 #endif
1368 /* nsISupports TranslateThis (in nsISupports aInitialThis, in nsIInterfaceInfo aInterfaceInfo, in PRUint16 aMethodIndex, out PRBool aHideFirstParamFromJS, out nsIIDPtr aIIDOfResult); */
1369 NS_IMETHODIMP
1370 nsXPCFunctionThisTranslator::TranslateThis(nsISupports *aInitialThis,
1371 nsIInterfaceInfo *aInterfaceInfo,
1372 PRUint16 aMethodIndex,
1373 PRBool *aHideFirstParamFromJS,
1374 nsIID * *aIIDOfResult,
1375 nsISupports **_retval)
1377 NS_IF_ADDREF(aInitialThis);
1378 *_retval = aInitialThis;
1379 *aHideFirstParamFromJS = JS_FALSE;
1380 *aIIDOfResult = nsnull;
1381 return NS_OK;
1384 #endif
1386 // ContextCallback calls are chained
1387 static JSContextCallback gOldJSContextCallback;
1389 static JSBool
1390 ContextCallback(JSContext *cx, uintN contextOp)
1392 if (gOldJSContextCallback && !gOldJSContextCallback(cx, contextOp))
1393 return JS_FALSE;
1395 if (contextOp == JSCONTEXT_NEW) {
1396 JS_SetErrorReporter(cx, my_ErrorReporter);
1397 JS_SetVersion(cx, JSVERSION_LATEST);
1399 return JS_TRUE;
1403 main(int argc, char **argv, char **envp)
1405 #ifdef XP_MACOSX
1406 InitAutoreleasePool();
1407 #endif
1408 JSRuntime *rt;
1409 JSContext *cx;
1410 JSObject *glob, *envobj;
1411 int result;
1412 nsresult rv;
1414 #ifdef HAVE_SETBUF
1415 // unbuffer stdout so that output is in the correct order; note that stderr
1416 // is unbuffered by default
1417 setbuf(stdout, 0);
1418 #endif
1420 gErrFile = stderr;
1421 gOutFile = stdout;
1422 gInFile = stdin;
1424 nsCOMPtr<nsIServiceManager> servMan;
1425 rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
1426 if (NS_FAILED(rv)) {
1427 printf("NS_InitXPCOM failed!\n");
1428 return 1;
1431 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
1432 NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
1433 if (registrar)
1434 registrar->AutoRegister(nsnull);
1437 nsCOMPtr<nsIJSRuntimeService> rtsvc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
1438 // get the JSRuntime from the runtime svc
1439 if (!rtsvc) {
1440 printf("failed to get nsJSRuntimeService!\n");
1441 return 1;
1444 if (NS_FAILED(rtsvc->GetRuntime(&rt)) || !rt) {
1445 printf("failed to get JSRuntime from nsJSRuntimeService!\n");
1446 return 1;
1449 gOldJSContextCallback = JS_SetContextCallback(rt, ContextCallback);
1451 cx = JS_NewContext(rt, 8192);
1452 if (!cx) {
1453 printf("JS_NewContext failed!\n");
1454 return 1;
1457 nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
1458 if (!xpc) {
1459 printf("failed to get nsXPConnect service!\n");
1460 return 1;
1463 // Since the caps security system might set a default security manager
1464 // we will be sure that the secman on this context gives full trust.
1465 nsRefPtr<FullTrustSecMan> secman = new FullTrustSecMan();
1466 xpc->SetSecurityManagerForJSContext(cx, secman, 0xFFFF);
1468 #ifndef XPCONNECT_STANDALONE
1469 // Fetch the system principal and store it away in a global, to use for
1470 // script compilation in Load() and ProcessFile() (including interactive
1471 // eval loop)
1473 nsCOMPtr<nsIPrincipal> princ;
1475 nsCOMPtr<nsIScriptSecurityManager> securityManager =
1476 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
1477 if (NS_SUCCEEDED(rv) && securityManager) {
1478 rv = securityManager->GetSystemPrincipal(getter_AddRefs(princ));
1479 if (NS_FAILED(rv)) {
1480 fprintf(gErrFile, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n");
1481 } else {
1482 // fetch the JS principals and stick in a global
1483 rv = princ->GetJSPrincipals(cx, &gJSPrincipals);
1484 if (NS_FAILED(rv)) {
1485 fprintf(gErrFile, "+++ Failed to obtain JS principals from SystemPrincipal.\n");
1487 secman->SetSystemPrincipal(princ);
1489 } else {
1490 fprintf(gErrFile, "+++ Failed to get ScriptSecurityManager service, running without principals");
1493 #endif
1495 #ifdef TEST_TranslateThis
1496 nsCOMPtr<nsIXPCFunctionThisTranslator>
1497 translator(new nsXPCFunctionThisTranslator);
1498 xpc->SetFunctionThisTranslator(NS_GET_IID(nsITestXPCFunctionCallback), translator, nsnull);
1499 #endif
1501 nsCOMPtr<nsIJSContextStack> cxstack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
1502 if (!cxstack) {
1503 printf("failed to get the nsThreadJSContextStack service!\n");
1504 return 1;
1507 if(NS_FAILED(cxstack->Push(cx))) {
1508 printf("failed to push the current JSContext on the nsThreadJSContextStack!\n");
1509 return 1;
1512 nsCOMPtr<nsIXPCScriptable> backstagePass;
1513 nsresult rv = rtsvc->GetBackstagePass(getter_AddRefs(backstagePass));
1514 if (NS_FAILED(rv)) {
1515 fprintf(gErrFile, "+++ Failed to get backstage pass from rtsvc: %8x\n",
1516 rv);
1517 return 1;
1520 nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
1521 rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass,
1522 NS_GET_IID(nsISupports),
1523 nsIXPConnect::
1524 FLAG_SYSTEM_GLOBAL_OBJECT,
1525 getter_AddRefs(holder));
1526 if (NS_FAILED(rv))
1527 return 1;
1529 rv = holder->GetJSObject(&glob);
1530 if (NS_FAILED(rv)) {
1531 NS_ASSERTION(glob == nsnull, "bad GetJSObject?");
1532 return 1;
1535 JS_BeginRequest(cx);
1537 if (!JS_DefineFunctions(cx, glob, glob_functions)) {
1538 JS_EndRequest(cx);
1539 return 1;
1542 envobj = JS_DefineObject(cx, glob, "environment", &env_class, NULL, 0);
1543 if (!envobj || !JS_SetPrivate(cx, envobj, envp)) {
1544 JS_EndRequest(cx);
1545 return 1;
1548 argc--;
1549 argv++;
1551 result = ProcessArgs(cx, glob, argv, argc);
1554 //#define TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN 1
1556 #ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN
1557 // test of late call and release (see below)
1558 nsCOMPtr<nsIJSContextStack> bogus;
1559 xpc->WrapJS(cx, glob, NS_GET_IID(nsIJSContextStack),
1560 (void**) getter_AddRefs(bogus));
1561 #endif
1563 JSPRINCIPALS_DROP(cx, gJSPrincipals);
1564 JS_ClearScope(cx, glob);
1565 JS_GC(cx);
1566 JSContext *oldcx;
1567 cxstack->Pop(&oldcx);
1568 NS_ASSERTION(oldcx == cx, "JS thread context push/pop mismatch");
1569 cxstack = nsnull;
1570 JS_GC(cx);
1571 JS_DestroyContext(cx);
1572 } // this scopes the nsCOMPtrs
1573 // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
1574 rv = NS_ShutdownXPCOM( NULL );
1575 NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
1577 #ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN
1578 // test of late call and release (see above)
1579 JSContext* bogusCX;
1580 bogus->Peek(&bogusCX);
1581 bogus = nsnull;
1582 #endif
1584 #ifdef XP_MACOSX
1585 FinishAutoreleasePool();
1586 #endif
1588 return result;