~ubuntu-branches/ubuntu/quantal/edbrowse/quantal

« back to all changes in this revision

Viewing changes to .pc/spidermonkey-2.0.patch/src/jsdom.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2010-11-29 12:06:07 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20101129120607-murkfny32efpr1nx
Tags: 3.4.5-0ubuntu1
* New upstream release
* Convert to source format 3.0
  - add debian/format/source
* Update for xulrunner-2.0
  - update debian/control
  - add debian/patches/spidermonkey-2.0.patch for the JSNative changes
  - add debian/patches/series
* Don't call the xulrunner binary to find libmozjs
  - update debian/edbrowse.sh
* Pass -lcrypto and -lreadline to the linker
  - update debian/rules

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* jsdom.c
 
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
 
9
*/
 
10
 
 
11
#include "eb.h"
 
12
 
 
13
#include "jsapi.h"
 
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. */
 
18
extern
 
19
JS_PUBLIC_API(char *)
 
20
JS_smprintf(const char *fmt, ...);
 
21
 
 
22
#define PROP_FIXED (JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
 
23
 
 
24
 
 
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 };
 
34
 
 
35
static void
 
36
my_ErrorReporter(JSContext * cx, const char *message, JSErrorReport * report)
 
37
{
 
38
    char *prefix, *tmp;
 
39
 
 
40
    if(debugLevel < 2)
 
41
        goto done;
 
42
    if(ismc)
 
43
        goto done;
 
44
 
 
45
    if(!report) {
 
46
        fprintf(gErrFile, "%s\n", message);
 
47
        goto done;
 
48
    }
 
49
 
 
50
/* Conditionally ignore reported warnings. */
 
51
    if(JSREPORT_IS_WARNING(report->flags)) {
 
52
        if(browseLocal)
 
53
            goto done;
 
54
    }
 
55
 
 
56
    prefix = NULL;
 
57
    if(report->filename)
 
58
        prefix = JS_smprintf("%s:", report->filename);
 
59
    if(report->lineno) {
 
60
        tmp = prefix;
 
61
        prefix = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno);
 
62
        if(tmp)
 
63
            JS_free(cx, tmp);
 
64
    }
 
65
    if(JSREPORT_IS_WARNING(report->flags)) {
 
66
        tmp = prefix;
 
67
        prefix = JS_smprintf("%s%swarning: ",
 
68
           tmp ? tmp : "", JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
 
69
        if(tmp)
 
70
            JS_free(cx, tmp);
 
71
    }
 
72
 
 
73
    if(prefix)
 
74
        fputs(prefix, gErrFile);
 
75
    fprintf(gErrFile, "%s\n", message);
 
76
 
 
77
    if(prefix)
 
78
        JS_free(cx, prefix);
 
79
 
 
80
  done:
 
81
    report->flags = 0;
 
82
}                               /* my_ErrorReporter */
 
83
 
 
84
 
 
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.
 
88
This is a disaster!
 
89
Create a fake name, so we can attach the element.
 
90
*********************************************************************/
 
91
 
 
92
static const char *
 
93
fakePropName(void)
 
94
{
 
95
    static char fakebuf[20];
 
96
    static int idx = 0;
 
97
    ++idx;
 
98
    sprintf(fakebuf, "gc$away%d", idx);
 
99
    return fakebuf;
 
100
}                               /*fakePropName */
 
101
 
 
102
 
 
103
/*********************************************************************
 
104
Here come the classes, and their inbuilt methods, for the document object model.
 
105
Start with window and document.
 
106
*********************************************************************/
 
107
 
 
108
static JSClass window_class = {
 
109
    "Window",
 
110
    JSCLASS_HAS_PRIVATE,
 
111
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
112
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
113
};
 
114
 
 
115
static JSBool
 
116
window_ctor(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
117
   jsval * rval)
 
118
{
 
119
    const char *newloc = 0;
 
120
    const char *winname = 0;
 
121
    JSString *str;
 
122
    if(argc > 0 && (str = JS_ValueToString(jcx, argv[0]))) {
 
123
        newloc = JS_GetStringBytes(str);
 
124
    }
 
125
    if(argc > 1 && (str = JS_ValueToString(jcx, argv[1]))) {
 
126
        winname = JS_GetStringBytes(str);
 
127
    }
 
128
/* third argument is attributes, like window size and location, that we don't care about. */
 
129
    javaOpensWindow(newloc, winname);
 
130
    if(!parsePage)
 
131
        return JS_FALSE;
 
132
    establish_property_object(obj, "opener", jwin);
 
133
    return JS_TRUE;
 
134
}                               /* window_ctor */
 
135
 
 
136
/* window.open() instantiates a new window object */
 
137
static JSBool
 
138
win_open(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
 
139
{
 
140
    JSObject *newwin = JS_ConstructObjectWithArguments(jcx,
 
141
       &window_class, 0, jwin, argc, argv);
 
142
    *rval = OBJECT_TO_JSVAL(newwin);
 
143
}                               /* win_open */
 
144
 
 
145
/* for window.focus etc */
 
146
static JSBool
 
147
nullFunction(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
148
   jsval * rval)
 
149
{
 
150
    return JS_TRUE;
 
151
}                               /* nullFunction */
 
152
 
 
153
static JSBool
 
154
falseFunction(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
155
   jsval * rval)
 
156
{
 
157
    *rval = JSVAL_FALSE;
 
158
    return JS_TRUE;
 
159
}                               /* falseFunction */
 
160
 
 
161
static JSBool
 
162
trueFunction(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
163
   jsval * rval)
 
164
{
 
165
    *rval = JSVAL_TRUE;
 
166
    return JS_TRUE;
 
167
}                               /* trueFunction */
 
168
 
 
169
static JSBool
 
170
setAttribute(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
171
   jsval * rval)
 
172
{
 
173
    if(argc != 2 || !JSVAL_IS_STRING(argv[0])) {
 
174
        JS_ReportError(jcx, "unexpected arguments to setAttribute()");
 
175
    } else {
 
176
        const char *prop = stringize(argv[0]);
 
177
        JS_DefineProperty(jcx, obj, prop, argv[1], NULL, NULL, PROP_FIXED);
 
178
    }
 
179
    return JS_TRUE;
 
180
}                               /* setAttribute */
 
181
 
 
182
static JSBool
 
183
appendChild(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
184
   jsval * rval)
 
185
{
 
186
    JSObject *elar;             /* elements array */
 
187
    jsuint length;
 
188
    jsval v;
 
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);
 
194
    return JS_TRUE;
 
195
}                               /* appendChild */
 
196
 
 
197
static JSBool
 
198
win_close(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
199
   jsval * rval)
 
200
{
 
201
/* It's too confusing to just close the window */
 
202
    i_puts(MSG_PageDone);
 
203
    cw->jsdead = true;
 
204
    return JS_TRUE;
 
205
}                               /* win_close */
 
206
 
 
207
static JSBool
 
208
win_alert(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
209
   jsval * rval)
 
210
{
 
211
    const char *msg;
 
212
    JSString *str;
 
213
    if(argc > 0 && (str = JS_ValueToString(jcx, argv[0]))) {
 
214
        msg = JS_GetStringBytes(str);
 
215
    }
 
216
    if(msg)
 
217
        puts(msg);
 
218
    return JS_TRUE;
 
219
}                               /* win_alert */
 
220
 
 
221
static JSBool
 
222
win_prompt(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
223
   jsval * rval)
 
224
{
 
225
    const char *msg = 0;
 
226
    const char *answer = 0;
 
227
    JSString *str;
 
228
    char inbuf[80];
 
229
    char *s;
 
230
    char c;
 
231
 
 
232
    if(argc > 0 && (str = JS_ValueToString(jcx, argv[0]))) {
 
233
        msg = JS_GetStringBytes(str);
 
234
    }
 
235
    if(argc > 1 && (str = JS_ValueToString(jcx, argv[1]))) {
 
236
        answer = JS_GetStringBytes(str);
 
237
    }
 
238
 
 
239
    if(!msg)
 
240
        msg = "";
 
241
    printf("%s", msg);
 
242
/* If it doesn't end in space or question mark, print a colon */
 
243
    c = 'x';
 
244
    if(*msg)
 
245
        c = msg[strlen(msg) - 1];
 
246
    if(!isspaceByte(c)) {
 
247
        if(!ispunctByte(c))
 
248
            printf(":");
 
249
        printf(" ");
 
250
    }
 
251
    if(answer)
 
252
        printf("[%s] ", answer);
 
253
    fflush(stdout);
 
254
    if(!fgets(inbuf, sizeof (inbuf), stdin))
 
255
        exit(1);
 
256
    s = inbuf + strlen(inbuf);
 
257
    if(s > inbuf && s[-1] == '\n')
 
258
        *--s = 0;
 
259
    if(inbuf[0])
 
260
        answer = inbuf;
 
261
    if(!answer)
 
262
        answer = "";
 
263
    *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(jcx, answer));
 
264
    return JS_TRUE;
 
265
}                               /* win_prompt */
 
266
 
 
267
static JSBool
 
268
win_confirm(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
269
   jsval * rval)
 
270
{
 
271
    const char *msg = 0;
 
272
    JSString *str;
 
273
    char inbuf[80];
 
274
    char *s;
 
275
    char c;
 
276
    bool first = true;
 
277
 
 
278
    if(argc > 0 && (str = JS_ValueToString(jcx, argv[0]))) {
 
279
        msg = JS_GetStringBytes(str);
 
280
    }
 
281
 
 
282
    if(!msg)
 
283
        msg = "";
 
284
    while(true) {
 
285
        printf("%s", msg);
 
286
        c = 'x';
 
287
        if(*msg)
 
288
            c = msg[strlen(msg) - 1];
 
289
        if(!isspaceByte(c)) {
 
290
            if(!ispunctByte(c))
 
291
                printf(":");
 
292
            printf(" ");
 
293
        }
 
294
        if(!first)
 
295
            printf("[y|n] ");
 
296
        first = false;
 
297
        fflush(stdout);
 
298
        if(!fgets(inbuf, sizeof (inbuf), stdin))
 
299
            exit(1);
 
300
        c = *inbuf;
 
301
        if(c && strchr("nNyY", c))
 
302
            break;
 
303
    }
 
304
 
 
305
    c = tolower(c);
 
306
    if(c == 'y')
 
307
        *rval = JSVAL_TRUE;
 
308
    else
 
309
        *rval = JSVAL_FALSE;
 
310
    return JS_TRUE;
 
311
}                               /* win_confirm */
 
312
 
 
313
static JSClass timer_class = {
 
314
    "Timer",
 
315
    JSCLASS_HAS_PRIVATE,
 
316
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
317
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
318
};
 
319
 
 
320
/* Set a timer or an interval */
 
321
static JSObject *
 
322
setTimeout(uintN argc, jsval * argv, bool isInterval)
 
323
{
 
324
    jsval v0, v1;
 
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");
 
331
 
 
332
    if(!parsePage) {
 
333
        JS_ReportError(jcx,
 
334
           "cannot use %s() to delay the execution of a function", methname);
 
335
        return JSVAL_NULL;
 
336
    }
 
337
 
 
338
    if(argc != 2 || !JSVAL_IS_INT(argv[1]))
 
339
        goto badarg;
 
340
 
 
341
    v0 = argv[0];
 
342
    v1 = argv[1];
 
343
    n = JSVAL_TO_INT(v1);
 
344
 
 
345
    if(JSVAL_IS_STRING(v0) ||
 
346
       JSVAL_IS_OBJECT(v0) &&
 
347
       JS_ValueToObject(jcx, v0, &fo) && JS_ObjectIsFunction(jcx, fo)) {
 
348
 
 
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);
 
354
 
 
355
        if(fo) {
 
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"))
 
361
                s = "javascript";
 
362
            int len = strlen(s);
 
363
            if(len > sizeof (fname) - 4)
 
364
                len = sizeof (fname) - 4;
 
365
            strncpy(fname, s, len);
 
366
            fname[len] = 0;
 
367
            strcat(fname, "()");
 
368
            fstr = fname;
 
369
            establish_property_object(to, "onclick", fo);
 
370
        } else {
 
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);
 
375
        }
 
376
 
 
377
        javaSetsTimeout(n, fstr, to, isInterval);
 
378
        return to;
 
379
    }
 
380
 
 
381
  badarg:
 
382
    JS_ReportError(jcx, "invalid arguments to %s()", methname);
 
383
    return JSVAL_NULL;
 
384
}                               /* setTimeout */
 
385
 
 
386
static JSBool
 
387
win_sto(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
 
388
{
 
389
    *rval = OBJECT_TO_JSVAL(setTimeout(argc, argv, false));
 
390
    return JS_TRUE;
 
391
}                               /* win_sto */
 
392
 
 
393
static JSBool
 
394
win_intv(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
 
395
{
 
396
    *rval = OBJECT_TO_JSVAL(setTimeout(argc, argv, true));
 
397
    return JS_TRUE;
 
398
}                               /* win_intv */
 
399
 
 
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},
 
411
    {0}
 
412
};
 
413
 
 
414
static JSClass doc_class = {
 
415
    "Document",
 
416
    JSCLASS_HAS_PRIVATE,
 
417
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
418
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
419
};
 
420
 
 
421
static void
 
422
dwrite2(const char *s)
 
423
{
 
424
    if(!cw->dw) {
 
425
        cw->dw = initString(&cw->dw_l);
 
426
        stringAndString(&cw->dw, &cw->dw_l, "<docwrite>");
 
427
    }
 
428
    stringAndString(&cw->dw, &cw->dw_l, s);
 
429
}                               /* dwrite2 */
 
430
 
 
431
static void
 
432
dwrite1(uintN argc, jsval * argv, bool newline)
 
433
{
 
434
    int i;
 
435
    const char *msg;
 
436
    JSString *str;
 
437
    for(i = 0; i < argc; ++i) {
 
438
        if((str = JS_ValueToString(jcx, argv[i])) &&
 
439
           (msg = JS_GetStringBytes(str)))
 
440
            dwrite2(msg);
 
441
/* I assume I don't have to free msg?? */
 
442
    }
 
443
    if(newline)
 
444
        dwrite2("\n");
 
445
}                               /* dwrite1 */
 
446
 
 
447
static JSBool
 
448
doc_write(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
449
   jsval * rval)
 
450
{
 
451
    dwrite1(argc, argv, false);
 
452
    return JS_TRUE;
 
453
}                               /* doc_write */
 
454
 
 
455
static JSBool
 
456
setter_innerHTML(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
457
{
 
458
    const char *s = stringize(*vp);
 
459
    if(s && strlen(s)) {
 
460
        dwrite2(parsePage ? "<hr>\n" : "<html>\n");
 
461
        dwrite2(s);
 
462
        if(s[strlen(s) - 1] != '\n')
 
463
            dwrite2("\n");
 
464
    }
 
465
/* The string has already been updated in the object. */
 
466
    return JS_TRUE;
 
467
}                               /* setter_innerHTML */
 
468
 
 
469
static JSBool
 
470
setter_innerText(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
 
471
{
 
472
    jsval v = *vp;
 
473
    const char *s;
 
474
    if(!JSVAL_IS_STRING(v))
 
475
        return JS_FALSE;
 
476
    s = JS_GetStringBytes(JSVAL_TO_STRING(v));
 
477
    i_puts(MSG_InnerText);
 
478
/* The string has already been updated in the object. */
 
479
    return JS_TRUE;
 
480
}                               /* setter_innerText */
 
481
 
 
482
static JSBool
 
483
doc_writeln(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
484
   jsval * rval)
 
485
{
 
486
    dwrite1(argc, argv, true);
 
487
    return JS_TRUE;
 
488
}                               /* doc_writeln */
 
489
 
 
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},
 
497
    {0}
 
498
};
 
499
 
 
500
static JSClass element_class = {
 
501
    "Element",
 
502
    JSCLASS_HAS_PRIVATE,
 
503
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
504
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
505
};
 
506
 
 
507
static JSFunctionSpec element_methods[] = {
 
508
    {"focus", nullFunction, 0, 0, 0},
 
509
    {"blur", nullFunction, 0, 0, 0},
 
510
    {0}
 
511
};
 
512
 
 
513
static JSClass form_class = {
 
514
    "Form",
 
515
    JSCLASS_HAS_PRIVATE,
 
516
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
517
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
518
};
 
519
 
 
520
static JSBool
 
521
form_submit(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
522
   jsval * rval)
 
523
{
 
524
    javaSubmitsForm(obj, false);
 
525
    return JS_TRUE;
 
526
}                               /* form_submit */
 
527
 
 
528
static JSBool
 
529
form_reset(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
 
530
   jsval * rval)
 
531
{
 
532
    javaSubmitsForm(obj, true);
 
533
    return JS_TRUE;
 
534
}                               /* form_reset */
 
535
 
 
536
static JSFunctionSpec form_methods[] = {
 
537
    {"submit", form_submit, 0, 0, 0},
 
538
    {"reset", form_reset, 0, 0, 0},
 
539
    {0}
 
540
};
 
541
 
 
542
static JSClass body_class = {
 
543
    "Body",
 
544
    JSCLASS_HAS_PRIVATE,
 
545
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
546
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
547
};
 
548
 
 
549
static JSFunctionSpec body_methods[] = {
 
550
    {"setAttribute", setAttribute, 2, 0, 0},
 
551
    {"appendChild", appendChild, 1, 0, 0},
 
552
    {0}
 
553
};
 
554
 
 
555
static JSClass head_class = {
 
556
    "Head",
 
557
    JSCLASS_HAS_PRIVATE,
 
558
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
559
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
560
};
 
561
 
 
562
static JSFunctionSpec head_methods[] = {
 
563
    {"setAttribute", setAttribute, 2, 0, 0},
 
564
    {"appendChild", appendChild, 1, 0, 0},
 
565
    {0}
 
566
};
 
567
 
 
568
static JSClass meta_class = {
 
569
    "Meta",
 
570
    JSCLASS_HAS_PRIVATE,
 
571
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
572
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
573
};
 
574
 
 
575
/* Don't be confused; this is for <link>, not <a> */
 
576
static JSClass link_class = {
 
577
    "Link",
 
578
    JSCLASS_HAS_PRIVATE,
 
579
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
580
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
581
};
 
582
 
 
583
static JSFunctionSpec link_methods[] = {
 
584
    {"setAttribute", setAttribute, 2, 0, 0},
 
585
    {0}
 
586
};
 
587
 
 
588
static JSClass image_class = {
 
589
    "Image",
 
590
    JSCLASS_HAS_PRIVATE,
 
591
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
592
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
593
};
 
594
 
 
595
static JSClass frame_class = {
 
596
    "Frame",
 
597
    JSCLASS_HAS_PRIVATE,
 
598
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
599
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
600
};
 
601
 
 
602
static JSClass anchor_class = {
 
603
    "Anchor",
 
604
    JSCLASS_HAS_PRIVATE,
 
605
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
606
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
607
};
 
608
 
 
609
static JSClass table_class = {
 
610
    "Table",
 
611
    JSCLASS_HAS_PRIVATE,
 
612
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
613
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
614
};
 
615
 
 
616
static JSClass trow_class = {
 
617
    "Trow",
 
618
    JSCLASS_HAS_PRIVATE,
 
619
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
620
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
621
};
 
622
 
 
623
static JSClass cell_class = {
 
624
    "Cell",
 
625
    JSCLASS_HAS_PRIVATE,
 
626
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
627
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
628
};
 
629
 
 
630
static JSClass div_class = {
 
631
    "Div",
 
632
    JSCLASS_HAS_PRIVATE,
 
633
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
634
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
635
};
 
636
 
 
637
static JSClass span_class = {
 
638
    "Span",
 
639
    JSCLASS_HAS_PRIVATE,
 
640
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
641
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
642
};
 
643
 
 
644
static JSClass area_class = {
 
645
    "Area",
 
646
    JSCLASS_HAS_PRIVATE,
 
647
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
648
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
649
};
 
650
 
 
651
static JSClass option_class = {
 
652
    "Option",
 
653
    JSCLASS_HAS_PRIVATE,
 
654
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
 
655
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
 
656
};
 
657
 
 
658
struct DOMCLASS {
 
659
    JSClass *class;
 
660
    JSFunctionSpec *methods;
 
661
      JSBool(*constructor) (JSContext *, JSObject *, uintN, jsval *, jsval *);
 
662
    int nargs;
 
663
};
 
664
 
 
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},
 
670
    {&meta_class},
 
671
    {&link_class, link_methods, nullFunction, 0},
 
672
    {&image_class, 0, nullFunction, 1},
 
673
    {&frame_class},
 
674
    {&anchor_class, 0, nullFunction, 1},
 
675
    {&table_class},
 
676
    {&div_class},
 
677
    {&area_class},
 
678
    {&span_class},
 
679
    {&trow_class},
 
680
    {&cell_class},
 
681
    {&option_class},
 
682
    {0}
 
683
};
 
684
 
 
685
static const char *docarrays[] = {
 
686
    "heads", "bodies", "links", "tables", "divs", "spans",
 
687
    "forms", "images", "areas", "metas", 0
 
688
};
 
689
 
 
690
 
 
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\
 
704
\n\
 
705
document.getElementById = function(s) { \n\
 
706
return document.idMaster[s]; } \n\
 
707
\n\
 
708
document.getElementsByTagName = function(s) { \n\
 
709
return document.all.tags(s); }\n\
 
710
\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\
 
716
\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\
 
729
\n\
 
730
history.toString = function() { \n\
 
731
return 'Sorry, edbrowse does not maintain a browsing history.'; } \
 
732
";
 
733
 
 
734
void *
 
735
createJavaContext(void)
 
736
{
 
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;
 
742
    int i;
 
743
    char verx11[20];
 
744
    jsval rval;
 
745
    struct MIMETYPE *mt;
 
746
 
 
747
    if(!jrt) {
 
748
/* 4 meg js space - should this be configurable? */
 
749
        jrt = JS_NewRuntime(4L * 1024L * 1024L);
 
750
        if(!jrt)
 
751
            i_printfExit(MSG_JavaMemError);
 
752
        gOutFile = stdout;
 
753
        gErrFile = stderr;
 
754
    }
 
755
 
 
756
    jcx = JS_NewContext(jrt, gStackChunkSize);
 
757
    if(!jcx)
 
758
        i_printfExit(MSG_JavaContextError);
 
759
    JS_SetErrorReporter(jcx, my_ErrorReporter);
 
760
    JS_SetOptions(jcx, JSOPTION_VAROBJFIX);
 
761
 
 
762
/* Create the Window object, which is the global object in DOM. */
 
763
    jwin = JS_NewObject(jcx, &window_class, NULL, NULL);
 
764
    if(!jwin)
 
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);
 
771
 
 
772
/* Math, Date, Number, String, etc */
 
773
    if(!JS_InitStandardClasses(jcx, jwin))
 
774
        i_printfExit(MSG_JavaClassError);
 
775
 
 
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);
 
780
 
 
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);
 
795
 
 
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);
 
801
    }
 
802
 
 
803
    initLocationClass();
 
804
 
 
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);
 
809
    if(!jdoc)
 
810
        i_printfExit(MSG_JavaObjError);
 
811
    establish_property_object(jwin, "document", jdoc);
 
812
 
 
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);
 
820
 
 
821
/* create arrays under document */
 
822
    for(i = 0; itemname = docarrays[i]; ++i)
 
823
        establish_property_array(jdoc, itemname);
 
824
 
 
825
/* Some arrays are under window */
 
826
    establish_property_array(jwin, "frames");
 
827
 
 
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);
 
832
 
 
833
    nav = JS_NewObject(jcx, 0, 0, jwin);
 
834
    establish_property_object(jwin, "navigator", nav);
 
835
 
 
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);
 
856
 
 
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");
 
861
    mt = mimetypes;
 
862
    for(i = 0; i < maxMime; ++i, ++mt) {
 
863
/* po is the plugin object and mo is the mime object */
 
864
        JSObject *mo, *po;
 
865
        jsval mov, pov;
 
866
        int len;
 
867
 
 
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)),
 
891
           0, 0, PROP_FIXED);
 
892
    }
 
893
 
 
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);
 
902
 
 
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);
 
914
 
 
915
    hist = JS_NewObject(jcx, 0, 0, jwin);
 
916
    establish_property_object(jwin, "history", hist);
 
917
 
 
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);
 
928
 
 
929
/* Set up some things in javascript */
 
930
    JS_EvaluateScript(jcx, jwin, initScript, strlen(initScript),
 
931
       "initScript", 1, &rval);
 
932
 
 
933
    return jcx;
 
934
}                               /* createJavaContext */
 
935
 
 
936
void
 
937
freeJavaContext(void *jsc)
 
938
{
 
939
    if(jsc)
 
940
        JS_DestroyContext((JSContext *) jsc);
 
941
}                               /* freeJavaContext */
 
942
 
 
943
void
 
944
establish_innerHTML(void *jv, const char *start, const char *end, bool is_ta)
 
945
{
 
946
    JSObject *obj = jv, *o;
 
947
    jsval v;
 
948
 
 
949
    if(!obj)
 
950
        return;
 
951
 
 
952
/* null start means the pointer has been corrupted by a document.write() call */
 
953
    if(!start)
 
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);
 
959
    if(is_ta) {
 
960
        JS_DefineProperty(jcx, obj, "innerText",
 
961
           STRING_TO_JSVAL(JS_NewStringCopyN(jcx, start, end - start)),
 
962
           NULL, setter_innerText, JSPROP_ENUMERATE | JSPROP_PERMANENT);
 
963
    }
 
964
 
 
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 */
 
970
 
 
971
void
 
972
jMyContext(void)
 
973
{
 
974
    jsval oval;
 
975
    jcx = cw->jsc;
 
976
    if(jcx) {
 
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);
 
984
    } else
 
985
        jwin = jdoc = jwloc = jdloc = 0;
 
986
}                               /* jMyContext */
 
987
 
 
988
bool
 
989
javaParseExecute(void *this, const char *str, const char *filename, int lineno)
 
990
{
 
991
    JSBool ok;
 
992
    bool rc;
 
993
    jsval rval;
 
994
 
 
995
/* Sometimes Mac puts these three chars at the start of a text file. */
 
996
    if(!strncmp(str, "\xef\xbb\xbf", 3))
 
997
        str += 3;
 
998
 
 
999
    debugPrint(6, "javascript:\n%s", str);
 
1000
    ok = JS_EvaluateScript(jcx, this, str, strlen(str),
 
1001
       filename, lineno, &rval);
 
1002
    rc = true;
 
1003
    if(JSVAL_IS_BOOLEAN(rval))
 
1004
        rc = JSVAL_TO_BOOLEAN(rval);
 
1005
    JS_GC(jcx);
 
1006
    return rc;
 
1007
}                               /* javaParseExecute */
 
1008
 
 
1009
/* link a frame, span, anchor, etc to the document object model */
 
1010
void *
 
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)
 
1014
{
 
1015
    JSObject *v = 0, *w, *alist = 0, *master;
 
1016
    jsval vv, listv;
 
1017
    jsuint length, attr = PROP_FIXED;
 
1018
    JSClass *cp;
 
1019
    bool dupname = false;
 
1020
    int i;
 
1021
 
 
1022
    if(cw->jsdead)
 
1023
        return 0;
 
1024
 
 
1025
/* find the class */
 
1026
    for(i = 0; cp = domClasses[i].class; ++i)
 
1027
        if(stringEqual(cp->name, classname))
 
1028
            break;
 
1029
 
 
1030
    if(symname) {
 
1031
        JSBool found;
 
1032
        JS_HasProperty(jcx, owner, symname, &found);
 
1033
        if(found) {
 
1034
 
 
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
 
1043
under that array.
 
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.
 
1052
Ok???
 
1053
Yeah, it makes my head spin too.
 
1054
*********************************************************************/
 
1055
 
 
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);
 
1062
                if(!found) {
 
1063
                    JS_DeleteProperty(jcx, owner, symname);
 
1064
/* gc will clean this up later */
 
1065
/* advance, as though this were not found */
 
1066
                    goto afterfound;
 
1067
                }
 
1068
            }
 
1069
 
 
1070
            if(radiosel == 1) {
 
1071
                JS_GetProperty(jcx, owner, symname, &vv);
 
1072
                v = JSVAL_TO_OBJECT(vv);
 
1073
            } else {
 
1074
                dupname = true;
 
1075
            }
 
1076
        }
 
1077
    }
 
1078
 
 
1079
  afterfound:
 
1080
    if(!v) {
 
1081
        if(radiosel) {
 
1082
            v = JS_NewArrayObject(jcx, 0, NULL);
 
1083
            if(radiosel == 1) {
 
1084
                establish_property_string(v, "type", "radio", true);
 
1085
            } else {
 
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);
 
1092
            }
 
1093
        } else {
 
1094
            v = JS_NewObject(jcx, cp, NULL, owner);
 
1095
        }
 
1096
        vv = OBJECT_TO_JSVAL(v);
 
1097
 
 
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);
 
1105
 
 
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);
 
1110
        } else {
 
1111
/* tie this to something, to protect it from gc */
 
1112
            JS_DefineProperty(jcx, owner, fakePropName(), vv,
 
1113
               NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT);
 
1114
        }
 
1115
 
 
1116
        if(list) {
 
1117
            JS_GetProperty(jcx, owner, list, &listv);
 
1118
            alist = JSVAL_TO_OBJECT(listv);
 
1119
        }
 
1120
        if(alist) {
 
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 */
 
1128
    }
 
1129
 
 
1130
    if(radiosel == 1) {
 
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);
 
1138
        v = w;
 
1139
    }
 
1140
 
 
1141
    if(symname)
 
1142
        establish_property_string(v, "name", symname, true);
 
1143
    if(idname) {
 
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);
 
1149
    } else {
 
1150
        establish_property_string(v, "id", EMPTYSTRING, true);
 
1151
    }
 
1152
 
 
1153
    if(href && href_url) {
 
1154
        establish_property_url(v, href, href_url, false);
 
1155
    }
 
1156
 
 
1157
    if(cp == &element_class) {
 
1158
/* link back to the form that owns the element */
 
1159
        establish_property_object(v, "form", owner);
 
1160
    }
 
1161
 
 
1162
    return v;
 
1163
}                               /* domLink */