2
* Javascript support, the connection to spider monkey JS.
3
* Copyright (c) Karl Dahlke, 2008
4
* This file is part of the edbrowse project, released under GPL.
5
* This file contains the basics of the document object model.
6
* The Spider Monkey Javascript compiler/engine is released by Mozilla,
7
* under the MPL. Install and build that package under /usr/local.
8
* ftp://ftp.mozilla.org/pub/mozilla.org/js/js-1.5.tar.gz
14
/* jsprf.h is not publically visible on some systems,
15
so I can't #include it here.
16
Instead, I'll declare the needed prototype myself, and hope it is consistent
17
with whatever smjs you are using. */
20
JS_smprintf(const char *fmt, ...);
22
#define PROP_FIXED (JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
25
void *jcx; /* really JSContext */
26
void *jwin; /* window object, really JSObject */
27
void *jdoc; /* window.document, really JSObject */
28
void *jwloc; /* window.location, really JSObject */
29
void *jdloc; /* document.location, really JSObject */
30
static size_t gStackChunkSize = 8192;
31
static FILE *gOutFile, *gErrFile;
32
static const char *emptyParms[] = { 0 };
33
static jsval emptyArgs[] = { 0 };
36
my_ErrorReporter(JSContext * cx, const char *message, JSErrorReport * report)
46
fprintf(gErrFile, "%s\n", message);
50
/* Conditionally ignore reported warnings. */
51
if(JSREPORT_IS_WARNING(report->flags)) {
58
prefix = JS_smprintf("%s:", report->filename);
61
prefix = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno);
65
if(JSREPORT_IS_WARNING(report->flags)) {
67
prefix = JS_smprintf("%s%swarning: ",
68
tmp ? tmp : "", JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
74
fputs(prefix, gErrFile);
75
fprintf(gErrFile, "%s\n", message);
82
} /* my_ErrorReporter */
85
/*********************************************************************
86
When an element is created without a name, it is not linked to its
87
owner (via that name), and can be cleared via garbage collection.
89
Create a fake name, so we can attach the element.
90
*********************************************************************/
95
static char fakebuf[20];
98
sprintf(fakebuf, "gc$away%d", idx);
103
/*********************************************************************
104
Here come the classes, and their inbuilt methods, for the document object model.
105
Start with window and document.
106
*********************************************************************/
108
static JSClass window_class = {
111
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
112
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
116
window_ctor(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
119
const char *newloc = 0;
120
const char *winname = 0;
122
if(argc > 0 && (str = JS_ValueToString(jcx, argv[0]))) {
123
newloc = JS_GetStringBytes(str);
125
if(argc > 1 && (str = JS_ValueToString(jcx, argv[1]))) {
126
winname = JS_GetStringBytes(str);
128
/* third argument is attributes, like window size and location, that we don't care about. */
129
javaOpensWindow(newloc, winname);
132
establish_property_object(obj, "opener", jwin);
136
/* window.open() instantiates a new window object */
138
win_open(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
140
JSObject *newwin = JS_ConstructObjectWithArguments(jcx,
141
&window_class, 0, jwin, argc, argv);
142
*rval = OBJECT_TO_JSVAL(newwin);
145
/* for window.focus etc */
147
nullFunction(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
154
falseFunction(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
159
} /* falseFunction */
162
trueFunction(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
170
setAttribute(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
173
if(argc != 2 || !JSVAL_IS_STRING(argv[0])) {
174
JS_ReportError(jcx, "unexpected arguments to setAttribute()");
176
const char *prop = stringize(argv[0]);
177
JS_DefineProperty(jcx, obj, prop, argv[1], NULL, NULL, PROP_FIXED);
183
appendChild(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
186
JSObject *elar; /* elements array */
189
JS_GetProperty(jcx, obj, "elements", &v);
190
elar = JSVAL_TO_OBJECT(v);
191
JS_GetArrayLength(jcx, elar, &length);
192
JS_DefineElement(jcx, elar, length,
193
(argc > 0 ? argv[0] : JSVAL_NULL), NULL, NULL, JSPROP_ENUMERATE);
198
win_close(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
201
/* It's too confusing to just close the window */
202
i_puts(MSG_PageDone);
208
win_alert(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
213
if(argc > 0 && (str = JS_ValueToString(jcx, argv[0]))) {
214
msg = JS_GetStringBytes(str);
222
win_prompt(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
226
const char *answer = 0;
232
if(argc > 0 && (str = JS_ValueToString(jcx, argv[0]))) {
233
msg = JS_GetStringBytes(str);
235
if(argc > 1 && (str = JS_ValueToString(jcx, argv[1]))) {
236
answer = JS_GetStringBytes(str);
242
/* If it doesn't end in space or question mark, print a colon */
245
c = msg[strlen(msg) - 1];
246
if(!isspaceByte(c)) {
252
printf("[%s] ", answer);
254
if(!fgets(inbuf, sizeof (inbuf), stdin))
256
s = inbuf + strlen(inbuf);
257
if(s > inbuf && s[-1] == '\n')
263
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(jcx, answer));
268
win_confirm(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
278
if(argc > 0 && (str = JS_ValueToString(jcx, argv[0]))) {
279
msg = JS_GetStringBytes(str);
288
c = msg[strlen(msg) - 1];
289
if(!isspaceByte(c)) {
298
if(!fgets(inbuf, sizeof (inbuf), stdin))
301
if(c && strchr("nNyY", c))
313
static JSClass timer_class = {
316
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
317
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
320
/* Set a timer or an interval */
322
setTimeout(uintN argc, jsval * argv, bool isInterval)
325
JSObject *fo = 0; /* function object */
326
JSObject *to; /* tag object */
327
int n; /* number of milliseconds */
328
char fname[48]; /* function name */
329
const char *fstr; /* function string */
330
const char *methname = (isInterval ? "setInterval" : "setTimeout");
334
"cannot use %s() to delay the execution of a function", methname);
338
if(argc != 2 || !JSVAL_IS_INT(argv[1]))
343
n = JSVAL_TO_INT(v1);
345
if(JSVAL_IS_STRING(v0) ||
346
JSVAL_IS_OBJECT(v0) &&
347
JS_ValueToObject(jcx, v0, &fo) && JS_ObjectIsFunction(jcx, fo)) {
349
/* build the tag object and link it to window */
350
to = JS_NewObject(jcx, &timer_class, NULL, jwin);
351
v1 = OBJECT_TO_JSVAL(to);
352
JS_DefineProperty(jcx, jwin, fakePropName(), v1,
353
NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT);
356
/* Extract the function name, which requires several steps */
357
JSFunction *f = JS_ValueToFunction(jcx, OBJECT_TO_JSVAL(fo));
358
const char *s = JS_GetFunctionName(f);
359
/* Remember that unnamed functions are named anonymous. */
360
if(!s || !*s || stringEqual(s, "anonymous"))
363
if(len > sizeof (fname) - 4)
364
len = sizeof (fname) - 4;
365
strncpy(fname, s, len);
369
establish_property_object(to, "onclick", fo);
371
/* compile the function from the string */
372
fstr = stringize(v0);
373
JS_CompileFunction(jcx, to, "onclick", 0, emptyParms, /* no named parameters */
374
fstr, strlen(fstr), "onclick", 1);
377
javaSetsTimeout(n, fstr, to, isInterval);
382
JS_ReportError(jcx, "invalid arguments to %s()", methname);
387
win_sto(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
389
*rval = OBJECT_TO_JSVAL(setTimeout(argc, argv, false));
394
win_intv(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
396
*rval = OBJECT_TO_JSVAL(setTimeout(argc, argv, true));
400
static JSFunctionSpec window_methods[] = {
401
{"alert", win_alert, 1, 0, 0},
402
{"prompt", win_prompt, 2, 0, 0},
403
{"confirm", win_confirm, 1, 0, 0},
404
{"setTimeout", win_sto, 2, 0, 0},
405
{"setInterval", win_intv, 2, 0, 0},
406
{"open", win_open, 3, 0, 0},
407
{"close", win_close, 0, 0, 0},
408
{"focus", nullFunction, 0, 0, 0},
409
{"blur", nullFunction, 0, 0, 0},
410
{"scroll", nullFunction, 0, 0, 0},
414
static JSClass doc_class = {
417
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
418
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
422
dwrite2(const char *s)
425
cw->dw = initString(&cw->dw_l);
426
stringAndString(&cw->dw, &cw->dw_l, "<docwrite>");
428
stringAndString(&cw->dw, &cw->dw_l, s);
432
dwrite1(uintN argc, jsval * argv, bool newline)
437
for(i = 0; i < argc; ++i) {
438
if((str = JS_ValueToString(jcx, argv[i])) &&
439
(msg = JS_GetStringBytes(str)))
441
/* I assume I don't have to free msg?? */
448
doc_write(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
451
dwrite1(argc, argv, false);
456
setter_innerHTML(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
458
const char *s = stringize(*vp);
460
dwrite2(parsePage ? "<hr>\n" : "<html>\n");
462
if(s[strlen(s) - 1] != '\n')
465
/* The string has already been updated in the object. */
467
} /* setter_innerHTML */
470
setter_innerText(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
474
if(!JSVAL_IS_STRING(v))
476
s = JS_GetStringBytes(JSVAL_TO_STRING(v));
477
i_puts(MSG_InnerText);
478
/* The string has already been updated in the object. */
480
} /* setter_innerText */
483
doc_writeln(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
486
dwrite1(argc, argv, true);
490
static JSFunctionSpec doc_methods[] = {
491
{"focus", nullFunction, 0, 0, 0},
492
{"blur", nullFunction, 0, 0, 0},
493
{"open", nullFunction, 0, 0, 0},
494
{"close", nullFunction, 0, 0, 0},
495
{"write", doc_write, 0, 0, 0},
496
{"writeln", doc_writeln, 0, 0, 0},
500
static JSClass element_class = {
503
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
504
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
507
static JSFunctionSpec element_methods[] = {
508
{"focus", nullFunction, 0, 0, 0},
509
{"blur", nullFunction, 0, 0, 0},
513
static JSClass form_class = {
516
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
517
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
521
form_submit(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
524
javaSubmitsForm(obj, false);
529
form_reset(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
532
javaSubmitsForm(obj, true);
536
static JSFunctionSpec form_methods[] = {
537
{"submit", form_submit, 0, 0, 0},
538
{"reset", form_reset, 0, 0, 0},
542
static JSClass body_class = {
545
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
546
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
549
static JSFunctionSpec body_methods[] = {
550
{"setAttribute", setAttribute, 2, 0, 0},
551
{"appendChild", appendChild, 1, 0, 0},
555
static JSClass head_class = {
558
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
559
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
562
static JSFunctionSpec head_methods[] = {
563
{"setAttribute", setAttribute, 2, 0, 0},
564
{"appendChild", appendChild, 1, 0, 0},
568
static JSClass meta_class = {
571
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
572
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
575
/* Don't be confused; this is for <link>, not <a> */
576
static JSClass link_class = {
579
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
580
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
583
static JSFunctionSpec link_methods[] = {
584
{"setAttribute", setAttribute, 2, 0, 0},
588
static JSClass image_class = {
591
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
592
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
595
static JSClass frame_class = {
598
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
599
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
602
static JSClass anchor_class = {
605
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
606
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
609
static JSClass table_class = {
612
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
613
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
616
static JSClass trow_class = {
619
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
620
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
623
static JSClass cell_class = {
626
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
627
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
630
static JSClass div_class = {
633
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
634
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
637
static JSClass span_class = {
640
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
641
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
644
static JSClass area_class = {
647
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
648
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
651
static JSClass option_class = {
654
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
655
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
660
JSFunctionSpec *methods;
661
JSBool(*constructor) (JSContext *, JSObject *, uintN, jsval *, jsval *);
665
static struct DOMCLASS domClasses[] = {
666
{&element_class, element_methods, nullFunction, 0},
667
{&form_class, form_methods},
668
{&body_class, body_methods},
669
{&head_class, head_methods},
671
{&link_class, link_methods, nullFunction, 0},
672
{&image_class, 0, nullFunction, 1},
674
{&anchor_class, 0, nullFunction, 1},
685
static const char *docarrays[] = {
686
"heads", "bodies", "links", "tables", "divs", "spans",
687
"forms", "images", "areas", "metas", 0
691
/* Some things are just easier in javascript */
692
static const char initScript[] = "document.all.tags = function(s) { \n\
693
switch(s.toLowerCase()) { \n\
694
case 'form': return document.forms; \n\
695
case 'table': return document.tables; \n\
696
case 'div': return document.divs; \n\
697
case 'a': return document.links; \n\
698
case 'img': case 'image': return document.images; \n\
699
case 'span': return document.spans; \n\
700
case 'head': return document.heads; \n\
701
case 'meta': return document.metas; \n\
702
case 'body': return document.bodies; \n\
703
default: /* alert('all.tags default ' + s); */ return new Array(); }} \n\
705
document.getElementById = function(s) { \n\
706
return document.idMaster[s]; } \n\
708
document.getElementsByTagName = function(s) { \n\
709
return document.all.tags(s); }\n\
711
document.createElement = function(s) { \n\
712
switch(s.toLowerCase()) { \n\
713
case 'link': return new Link();\n\
714
case 'image': case 'img': return new Image();\n\
715
default: /* alert('createElement default ' + s); */ return new Object(); }} \n\
717
URL.prototype.indexOf = function(s) { \n\
718
return this.toString().indexOf(s); }\n\
719
URL.prototype.lastIndexOf = function(s) { \n\
720
return this.toString().lastIndexOf(s); }\n\
721
URL.prototype.substring = function(from, to) { \n\
722
return this.toString().substring(from, to); }\n\
723
URL.prototype.toLowerCase = function() { \n\
724
return this.toString().toLowerCase(); }\n\
725
URL.prototype.toUpperCase = function() { \n\
726
return this.toString().toUpperCase(); }\n\
727
URL.prototype.match = function(s) { \n\
728
return this.toString().match(s); }\n\
730
history.toString = function() { \n\
731
return 'Sorry, edbrowse does not maintain a browsing history.'; } \
735
createJavaContext(void)
737
static JSRuntime *jrt;
738
JSObject *o, *nav, *screen, *hist, *del;
739
/* navigator mime types and plugins */
740
JSObject *navmt, *navpi;
741
const char *itemname;
748
/* 4 meg js space - should this be configurable? */
749
jrt = JS_NewRuntime(4L * 1024L * 1024L);
751
i_printfExit(MSG_JavaMemError);
756
jcx = JS_NewContext(jrt, gStackChunkSize);
758
i_printfExit(MSG_JavaContextError);
759
JS_SetErrorReporter(jcx, my_ErrorReporter);
760
JS_SetOptions(jcx, JSOPTION_VAROBJFIX);
762
/* Create the Window object, which is the global object in DOM. */
763
jwin = JS_NewObject(jcx, &window_class, NULL, NULL);
765
i_printfExit(MSG_JavaWindowError);
766
JS_InitClass(jcx, jwin, 0, &window_class, window_ctor, 3,
767
NULL, window_methods, NULL, NULL);
768
/* Ok, but the global object was created before the class,
769
* so it doesn't have its methods yet. */
770
JS_DefineFunctions(jcx, jwin, window_methods);
772
/* Math, Date, Number, String, etc */
773
if(!JS_InitStandardClasses(jcx, jwin))
774
i_printfExit(MSG_JavaClassError);
776
establish_property_object(jwin, "window", jwin);
777
establish_property_object(jwin, "self", jwin);
778
establish_property_object(jwin, "parent", jwin);
779
establish_property_object(jwin, "top", jwin);
781
/* Some visual attributes of the window.
782
* These are just guesses.
783
* Better to have something, than to leave them undefined. */
784
establish_property_number(jwin, "height", 768, true);
785
establish_property_number(jwin, "width", 1024, true);
786
establish_property_string(jwin, "status", 0, false);
787
establish_property_string(jwin, "defaultStatus", 0, false);
788
establish_property_bool(jwin, "returnValue", true, false);
789
establish_property_bool(jwin, "menubar", true, false);
790
establish_property_bool(jwin, "scrollbars", true, false);
791
establish_property_bool(jwin, "toolbar", true, false);
792
establish_property_bool(jwin, "resizable", true, false);
793
establish_property_bool(jwin, "directories", false, false);
794
establish_property_string(jwin, "name", "unspecifiedFrame", false);
796
/* Other classes that we'll need. */
797
for(i = 0; domClasses[i].class; ++i) {
798
JS_InitClass(jcx, jwin, 0, domClasses[i].class,
799
domClasses[i].constructor, domClasses[i].nargs,
800
NULL, domClasses[i].methods, NULL, NULL);
805
/* document under window */
806
JS_InitClass(jcx, jwin, 0, &doc_class, NULL, 0,
807
NULL, doc_methods, NULL, NULL);
808
jdoc = JS_NewObject(jcx, &doc_class, NULL, jwin);
810
i_printfExit(MSG_JavaObjError);
811
establish_property_object(jwin, "document", jdoc);
813
establish_property_string(jdoc, "bgcolor", "white", false);
814
establish_property_string(jdoc, "cookie", 0, false);
815
establish_property_string(jdoc, "referrer", cw->referrer, true);
816
establish_property_url(jdoc, "URL", cw->fileName, true);
817
establish_property_url(jdoc, "location", cw->fileName, false);
818
establish_property_url(jwin, "location", cw->firstURL, false);
819
establish_property_string(jdoc, "domain", getHostURL(cw->fileName), false);
821
/* create arrays under document */
822
for(i = 0; itemname = docarrays[i]; ++i)
823
establish_property_array(jdoc, itemname);
825
/* Some arrays are under window */
826
establish_property_array(jwin, "frames");
828
o = JS_NewObject(jcx, 0, 0, jdoc);
829
establish_property_object(jdoc, "idMaster", o);
830
o = JS_NewObject(jcx, 0, 0, jdoc);
831
establish_property_object(jdoc, "all", o);
833
nav = JS_NewObject(jcx, 0, 0, jwin);
834
establish_property_object(jwin, "navigator", nav);
836
/* attributes of the navigator */
837
establish_property_string(nav, "appName", "edbrowse", true);
838
establish_property_string(nav, "appCode Name", "edbrowse C/SMJS", true);
839
/* Use X11 to indicate unix/linux. Sort of a standard */
840
sprintf(verx11, "%s%s", version, "-X11");
841
establish_property_string(nav, "appVersion", version, true);
842
establish_property_string(nav, "userAgent", currentAgent, true);
843
establish_property_string(nav, "oscpu", currentOS(), true);
844
establish_property_string(nav, "platform", currentMachine(), true);
845
establish_property_string(nav, "product", "smjs", true);
846
establish_property_string(nav, "productSub", "1.5", true);
847
establish_property_string(nav, "vendor", "eklhad", true);
848
establish_property_string(nav, "vendorSub", version, true);
849
/* We need to locale-ize the next one */
850
establish_property_string(nav, "userLanguage", "english", true);
851
establish_property_string(nav, "language", "english", true);
852
JS_DefineFunction(jcx, nav, "javaEnabled", falseFunction, 0, PROP_FIXED);
853
JS_DefineFunction(jcx, nav, "taintEnabled", falseFunction, 0, PROP_FIXED);
854
establish_property_bool(nav, "cookieEnabled", true, true);
855
establish_property_bool(nav, "onLine", true, true);
857
/* Build the array of mime types and plugins,
858
* according to the entries in the config file. */
859
navpi = establish_property_array(nav, "plugins");
860
navmt = establish_property_array(nav, "mimeTypes");
862
for(i = 0; i < maxMime; ++i, ++mt) {
863
/* po is the plugin object and mo is the mime object */
868
po = JS_NewObject(jcx, 0, 0, nav);
869
pov = OBJECT_TO_JSVAL(po);
870
JS_DefineElement(jcx, navpi, i, pov, NULL, NULL, PROP_FIXED);
871
mo = JS_NewObject(jcx, 0, 0, nav);
872
mov = OBJECT_TO_JSVAL(mo);
873
JS_DefineElement(jcx, navmt, i, mov, NULL, NULL, PROP_FIXED);
874
establish_property_object(mo, "enabledPlugin", po);
875
establish_property_string(mo, "type", mt->type, true);
876
establish_property_object(navmt, mt->type, mo);
877
establish_property_string(mo, "description", mt->desc, true);
878
establish_property_string(mo, "suffixes", mt->suffix, true);
879
/* I don't really have enough information, from the config file, to fill
880
* in the attributes of the plugin object.
881
* I'm just going to fake it.
882
* Description will be the same as that of the mime type,
883
* and the filename will be the program to run.
884
* No idea if this is right or not. */
885
establish_property_string(po, "description", mt->desc, true);
886
establish_property_string(po, "filename", mt->program, true);
887
/* For the name, how about the program without its options? */
888
len = strcspn(mt->program, " \t");
889
JS_DefineProperty(jcx, po, "name",
890
STRING_TO_JSVAL(JS_NewStringCopyN(jcx, mt->program, len)),
894
screen = JS_NewObject(jcx, 0, 0, jwin);
895
establish_property_object(jwin, "screen", screen);
896
establish_property_number(screen, "height", 768, true);
897
establish_property_number(screen, "width", 1024, true);
898
establish_property_number(screen, "availHeight", 768, true);
899
establish_property_number(screen, "availWidth", 1024, true);
900
establish_property_number(screen, "availTop", 0, true);
901
establish_property_number(screen, "availLeft", 0, true);
903
del = JS_NewObject(jcx, 0, 0, jdoc);
904
establish_property_object(jdoc, "body", del);
905
establish_property_object(jdoc, "documentElement", del);
906
establish_property_number(del, "clientHeight", 768, true);
907
establish_property_number(del, "clientWidth", 1024, true);
908
establish_property_number(del, "offsetHeight", 768, true);
909
establish_property_number(del, "offsetWidth", 1024, true);
910
establish_property_number(del, "scrollHeight", 768, true);
911
establish_property_number(del, "scrollWidth", 1024, true);
912
establish_property_number(del, "scrollTop", 0, true);
913
establish_property_number(del, "scrollLeft", 0, true);
915
hist = JS_NewObject(jcx, 0, 0, jwin);
916
establish_property_object(jwin, "history", hist);
918
/* attributes of history */
919
establish_property_string(hist, "current", cw->fileName, true);
920
/* There's no history in edbrowse. */
921
/* Only the current file is known, hence length is 1. */
922
establish_property_number(hist, "length", 1, true);
923
establish_property_string(hist, "next", 0, true);
924
establish_property_string(hist, "previous", 0, true);
925
JS_DefineFunction(jcx, hist, "back", nullFunction, 0, PROP_FIXED);
926
JS_DefineFunction(jcx, hist, "forward", nullFunction, 0, PROP_FIXED);
927
JS_DefineFunction(jcx, hist, "go", nullFunction, 0, PROP_FIXED);
929
/* Set up some things in javascript */
930
JS_EvaluateScript(jcx, jwin, initScript, strlen(initScript),
931
"initScript", 1, &rval);
934
} /* createJavaContext */
937
freeJavaContext(void *jsc)
940
JS_DestroyContext((JSContext *) jsc);
941
} /* freeJavaContext */
944
establish_innerHTML(void *jv, const char *start, const char *end, bool is_ta)
946
JSObject *obj = jv, *o;
952
/* null start means the pointer has been corrupted by a document.write() call */
954
start = end = EMPTYSTRING;
955
JS_DefineProperty(jcx, obj, "innerHTML",
956
STRING_TO_JSVAL(JS_NewStringCopyN(jcx, start, end - start)),
957
NULL, (is_ta ? setter_innerText : setter_innerHTML),
958
JSPROP_ENUMERATE | JSPROP_PERMANENT);
960
JS_DefineProperty(jcx, obj, "innerText",
961
STRING_TO_JSVAL(JS_NewStringCopyN(jcx, start, end - start)),
962
NULL, setter_innerText, JSPROP_ENUMERATE | JSPROP_PERMANENT);
965
/* Anything with an innerHTML might also have a style. */
966
o = JS_NewObject(jcx, 0, 0, obj);
967
v = OBJECT_TO_JSVAL(o);
968
JS_DefineProperty(jcx, obj, "style", v, NULL, NULL, JSPROP_ENUMERATE);
969
} /* establish_innerHTML */
977
jwin = JS_GetGlobalObject(jcx);
978
JS_GetProperty(jcx, jwin, "document", &oval);
979
jdoc = JSVAL_TO_OBJECT(oval);
980
JS_GetProperty(jcx, jwin, "location", &oval);
981
jwloc = JSVAL_TO_OBJECT(oval);
982
JS_GetProperty(jcx, jdoc, "location", &oval);
983
jdloc = JSVAL_TO_OBJECT(oval);
985
jwin = jdoc = jwloc = jdloc = 0;
989
javaParseExecute(void *this, const char *str, const char *filename, int lineno)
995
/* Sometimes Mac puts these three chars at the start of a text file. */
996
if(!strncmp(str, "\xef\xbb\xbf", 3))
999
debugPrint(6, "javascript:\n%s", str);
1000
ok = JS_EvaluateScript(jcx, this, str, strlen(str),
1001
filename, lineno, &rval);
1003
if(JSVAL_IS_BOOLEAN(rval))
1004
rc = JSVAL_TO_BOOLEAN(rval);
1007
} /* javaParseExecute */
1009
/* link a frame, span, anchor, etc to the document object model */
1011
domLink(const char *classname, /* instantiate this class */
1012
const char *symname, const char *idname, const char *href, const char *href_url, const char *list, /* next member of this array */
1013
void *owner, int radiosel)
1015
JSObject *v = 0, *w, *alist = 0, *master;
1017
jsuint length, attr = PROP_FIXED;
1019
bool dupname = false;
1025
/* find the class */
1026
for(i = 0; cp = domClasses[i].class; ++i)
1027
if(stringEqual(cp->name, classname))
1032
JS_HasProperty(jcx, owner, symname, &found);
1035
/*********************************************************************
1036
This could be a duplicate name.
1037
Yes, that really happens.
1038
Link to the first tag having this name,
1039
and link the second tag under a fake name, so gc won't throw it away.
1040
Or - it could be a duplicate name because multiple radio buttons
1041
all share the same name.
1042
The first time we create the array, and thereafter we just link
1044
Or - and this really does happen -
1045
an input tag could have the name action, colliding with form.action.
1046
I have no idea what to do here.
1047
I will assume the tag displaces the action.
1048
That means javascript cannot change the action of the form,
1049
which it rarely does anyways.
1050
When it refers to form.action, that will be the input tag.
1051
I'll check for that one first.
1053
Yeah, it makes my head spin too.
1054
*********************************************************************/
1056
if(stringEqual(symname, "action")) {
1057
JSObject *ao; /* action object */
1058
JS_GetProperty(jcx, owner, symname, &vv);
1059
ao = JSVAL_TO_OBJECT(vv);
1060
/* actioncrash tells me if we've already had this collision */
1061
JS_HasProperty(jcx, ao, "actioncrash", &found);
1063
JS_DeleteProperty(jcx, owner, symname);
1064
/* gc will clean this up later */
1065
/* advance, as though this were not found */
1071
JS_GetProperty(jcx, owner, symname, &vv);
1072
v = JSVAL_TO_OBJECT(vv);
1082
v = JS_NewArrayObject(jcx, 0, NULL);
1084
establish_property_string(v, "type", "radio", true);
1086
/* self-referencing - hope this is ok */
1087
establish_property_object(v, "options", v);
1088
establish_property_number(v, "selectedIndex", -1, false);
1089
// not the normal pathway; we have to create our own element methods here.
1090
JS_DefineFunction(jcx, v, "focus", nullFunction, 0, PROP_FIXED);
1091
JS_DefineFunction(jcx, v, "blur", nullFunction, 0, PROP_FIXED);
1094
v = JS_NewObject(jcx, cp, NULL, owner);
1096
vv = OBJECT_TO_JSVAL(v);
1098
/* if no name, then use id as name */
1099
if(!symname && idname) {
1100
JS_DefineProperty(jcx, owner, idname, vv, NULL, NULL, attr);
1101
} else if(symname && !dupname) {
1102
JS_DefineProperty(jcx, owner, symname, vv, NULL, NULL, attr);
1103
if(stringEqual(symname, "action"))
1104
establish_property_bool(v, "actioncrash", true, true);
1106
/* link to document.all */
1107
JS_GetProperty(jcx, jdoc, "all", &listv);
1108
master = JSVAL_TO_OBJECT(listv);
1109
establish_property_object(master, symname, v);
1111
/* tie this to something, to protect it from gc */
1112
JS_DefineProperty(jcx, owner, fakePropName(), vv,
1113
NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT);
1117
JS_GetProperty(jcx, owner, list, &listv);
1118
alist = JSVAL_TO_OBJECT(listv);
1121
JS_GetArrayLength(jcx, alist, &length);
1122
JS_DefineElement(jcx, alist, length, vv, NULL, NULL, attr);
1123
if(symname && !dupname)
1124
establish_property_object(alist, symname, v);
1125
if(idname && (!symname || !stringEqual(symname, idname)))
1126
establish_property_object(alist, idname, v);
1127
} /* list indicated */
1131
/* drop down to the element within the radio array, and return that element */
1132
/* w becomes the object associated with this radio button */
1133
/* v is, by assumption, an array */
1134
JS_GetArrayLength(jcx, v, &length);
1135
w = JS_NewObject(jcx, &element_class, NULL, owner);
1136
vv = OBJECT_TO_JSVAL(w);
1137
JS_DefineElement(jcx, v, length, vv, NULL, NULL, attr);
1142
establish_property_string(v, "name", symname, true);
1144
/* v.id becomes idname, and idMaster.idname becomes v */
1145
establish_property_string(v, "id", idname, true);
1146
JS_GetProperty(jcx, jdoc, "idMaster", &listv);
1147
master = JSVAL_TO_OBJECT(listv);
1148
establish_property_object(master, idname, v);
1150
establish_property_string(v, "id", EMPTYSTRING, true);
1153
if(href && href_url) {
1154
establish_property_url(v, href, href_url, false);
1157
if(cp == &element_class) {
1158
/* link back to the form that owns the element */
1159
establish_property_object(v, "form", owner);