Skip to content

Commit 5fd2a54

Browse files
author
rogerl%netscape.com
committed
r=brendan,rginda
Added ECMA3 compliant getter/setter syntax. Fixed bugs - #28686, mishandling of \$ in replace() - #27902, eval not detected as heavyweight indicator for non ECMA context version.
1 parent edd1f9b commit 5fd2a54

File tree

6 files changed

+156
-11
lines changed

6 files changed

+156
-11
lines changed

js/src/jsemit.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,10 +2239,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
22392239
op = JSOP_CALL;
22402240
emit_call:
22412241
pn2 = pn->pn_head;
2242-
if (JSVERSION_IS_ECMA(cx->version) &&
2243-
pn2->pn_op == JSOP_NAME &&
2242+
if (pn2->pn_op == JSOP_NAME &&
22442243
pn2->pn_atom == cx->runtime->atomState.evalAtom) {
2245-
op = JSOP_EVAL;
2244+
if (JSVERSION_IS_ECMA(cx->version))
2245+
op = JSOP_EVAL;
22462246
cg->treeContext.flags |= TCF_FUN_HEAVYWEIGHT;
22472247
}
22482248

js/src/jsobj.c

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,15 +516,25 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
516516
if (attrs & JSPROP_GETTER) {
517517
val[valcnt] = (jsval)
518518
SPROP_GETTER((JSScopeProperty *)prop, obj2);
519+
#ifdef OLD_GETTER_SETTER
519520
gsop[valcnt] =
520521
ATOM_TO_STRING(cx->runtime->atomState.getterAtom);
522+
#else
523+
gsop[valcnt] =
524+
ATOM_TO_STRING(cx->runtime->atomState.getAtom);
525+
#endif
521526
valcnt++;
522527
}
523528
if (attrs & JSPROP_SETTER) {
524529
val[valcnt] = (jsval)
525530
SPROP_SETTER((JSScopeProperty *)prop, obj2);
531+
#ifdef OLD_GETTER_SETTER
526532
gsop[valcnt] =
527533
ATOM_TO_STRING(cx->runtime->atomState.setterAtom);
534+
#else
535+
gsop[valcnt] =
536+
ATOM_TO_STRING(cx->runtime->atomState.setAtom);
537+
#endif
528538
valcnt++;
529539
}
530540
} else {
@@ -572,6 +582,15 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
572582
vchars = valstr->chars;
573583
vlength = valstr->length;
574584

585+
#ifndef OLD_GETTER_SETTER
586+
/* Remove 'function ' from beginning of valstr*/
587+
if (gsop[j]) {
588+
int n = strlen(js_function_str) + 1;
589+
vchars += n;
590+
vlength -= n;
591+
}
592+
#endif
593+
575594
/* If val[j] is a non-sharp object, consider sharpening it. */
576595
vsharp = NULL;
577596
vsharplength = 0;
@@ -619,6 +638,7 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
619638
}
620639
comma = ", ";
621640

641+
#ifdef OLD_GETTER_SETTER
622642
js_strncpy(&chars[nchars], idstr->chars, idstr->length);
623643
nchars += idstr->length;
624644
#if JS_HAS_GETTER_SETTER
@@ -629,7 +649,17 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
629649
}
630650
#endif
631651
chars[nchars++] = ':';
632-
652+
#else
653+
if (gsop[j]) {
654+
js_strncpy(&chars[nchars], gsop[j]->chars, gsop[j]->length);
655+
nchars += gsop[j]->length;
656+
chars[nchars++] = ' ';
657+
}
658+
js_strncpy(&chars[nchars], idstr->chars, idstr->length);
659+
nchars += idstr->length;
660+
if (!gsop[j])
661+
chars[nchars++] = ':';
662+
#endif
633663
if (vsharplength) {
634664
js_strncpy(&chars[nchars], vsharp, vsharplength);
635665
nchars += vsharplength;
@@ -938,6 +968,55 @@ obj_propertyIsEnumerable(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
938968
}
939969
#endif /* JS_HAS_NEW_OBJ_METHODS */
940970

971+
#if JS_HAS_GETTER_SETTER
972+
static JSBool
973+
obj_defineGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
974+
jsval *rval)
975+
{
976+
JSAtom *atom;
977+
jsval fval = argv[1];
978+
979+
if (JS_TypeOfValue(cx, fval) != JSTYPE_FUNCTION) {
980+
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
981+
JSMSG_BAD_GETTER_OR_SETTER,
982+
js_getter_str);
983+
return JS_FALSE;
984+
}
985+
986+
atom = js_ValueToStringAtom(cx, argv[0]);
987+
if (!atom)
988+
return JS_FALSE;
989+
990+
return OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID,
991+
(JSPropertyOp) JSVAL_TO_OBJECT(fval),
992+
NULL, JSPROP_GETTER, NULL);
993+
}
994+
995+
static JSBool
996+
obj_defineSetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
997+
jsval *rval)
998+
{
999+
JSAtom *atom;
1000+
jsval fval = argv[1];
1001+
1002+
if (JS_TypeOfValue(cx, argv[1]) != JSTYPE_FUNCTION) {
1003+
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
1004+
JSMSG_BAD_GETTER_OR_SETTER,
1005+
js_setter_str);
1006+
return JS_FALSE;
1007+
}
1008+
1009+
atom = js_ValueToStringAtom(cx, argv[0]);
1010+
if (!atom)
1011+
return JS_FALSE;
1012+
1013+
return OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL,
1014+
(JSPropertyOp) JSVAL_TO_OBJECT(argv[1]),
1015+
JSPROP_SETTER, NULL);
1016+
}
1017+
#endif /* JS_HAS_GETTER_SETTER */
1018+
1019+
9411020
static JSFunctionSpec object_methods[] = {
9421021
#if JS_HAS_TOSOURCE
9431022
{js_toSource_str, js_obj_toSource, 0, 0, OBJ_TOSTRING_EXTRA},
@@ -953,6 +1032,10 @@ static JSFunctionSpec object_methods[] = {
9531032
{"hasOwnProperty", obj_hasOwnProperty, 1,0,0},
9541033
{"isPrototypeOf", obj_isPrototypeOf, 1,0,0},
9551034
{"propertyIsEnumerable", obj_propertyIsEnumerable, 1,0,0},
1035+
#endif
1036+
#if JS_HAS_GETTER_SETTER
1037+
{"__defineGetter__", obj_defineGetter, 2,0,0},
1038+
{"__defineSetter__", obj_defineSetter, 2,0,0},
9561039
#endif
9571040
{0,0,0,0,0}
9581041
};

js/src/jsopcode.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,16 +2041,34 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
20412041
xval = ATOM_BYTES(atom);
20422042
lval = POP_STR();
20432043
do_initprop:
2044-
todo = Sprint(&ss->sprinter, "%s%s%s%s%s:%s",
2045-
lval,
2044+
#ifdef OLD_GETTER_SETTER
2045+
todo = Sprint(&ss->sprinter, "%s%s%s%s%s:%s",
2046+
lval,
20462047
(lval[1] != '\0') ? ", " : "",
2047-
xval,
2048+
xval,
20482049
(lastop == JSOP_GETTER || lastop == JSOP_SETTER)
20492050
? " " : "",
20502051
(lastop == JSOP_GETTER) ? js_getter_str :
20512052
(lastop == JSOP_SETTER) ? js_setter_str :
20522053
"",
20532054
rval);
2055+
#else
2056+
if (lastop == JSOP_GETTER || lastop == JSOP_SETTER) {
2057+
todo = Sprint(&ss->sprinter, "%s%s%s %s%s",
2058+
lval,
2059+
(lval[1] != '\0') ? ", " : "",
2060+
(lastop == JSOP_GETTER)
2061+
? js_get_str : js_set_str,
2062+
xval,
2063+
rval + strlen(js_function_str) + 1);
2064+
} else {
2065+
todo = Sprint(&ss->sprinter, "%s%s%s:%s",
2066+
lval,
2067+
(lval[1] != '\0') ? ", " : "",
2068+
xval,
2069+
rval);
2070+
}
2071+
#endif
20542072
break;
20552073

20562074
case JSOP_INITELEM:

js/src/jsparse.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,13 @@ CheckGetterOrSetter(JSContext *cx, JSTokenStream *ts, JSTokenType tt)
220220
return TOK_ERROR;
221221
}
222222
CURRENT_TOKEN(ts).t_op = op;
223+
if (!js_ReportCompileErrorNumber(cx, ts,
224+
JSREPORT_WARNING |
225+
JSREPORT_STRICT,
226+
JSMSG_DEPRECATED_USAGE,
227+
ATOM_BYTES(atom))) {
228+
return TOK_ERROR;
229+
}
223230
return tt;
224231
}
225232
#endif
@@ -2360,6 +2367,8 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
23602367
JSTokenType tt;
23612368
JSParseNode *pn, *pn2, *pn3;
23622369
char *badWord;
2370+
JSAtom *atom;
2371+
JSRuntime *rt;
23632372

23642373
#if JS_HAS_SHARP_VARS
23652374
JSParseNode *defsharp;
@@ -2473,6 +2482,31 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
24732482
pn3->pn_dval = CURRENT_TOKEN(ts).t_dval;
24742483
break;
24752484
case TOK_NAME:
2485+
#if JS_HAS_GETTER_SETTER
2486+
atom = CURRENT_TOKEN(ts).t_atom;
2487+
rt = cx->runtime;
2488+
if (atom == rt->atomState.getAtom ||
2489+
atom == rt->atomState.setAtom) {
2490+
op = (atom == rt->atomState.getAtom)
2491+
? JSOP_GETTER
2492+
: JSOP_SETTER;
2493+
if (js_MatchToken(cx, ts, TOK_NAME)) {
2494+
pn3 = NewParseNode(cx, &CURRENT_TOKEN(ts),
2495+
PN_NAME);
2496+
if (!pn3)
2497+
return NULL;
2498+
pn3->pn_atom = CURRENT_TOKEN(ts).t_atom;
2499+
pn3->pn_expr = NULL;
2500+
/* have to fake a 'function' token */
2501+
CURRENT_TOKEN(ts).t_op = JSOP_NOP;
2502+
CURRENT_TOKEN(ts).type = TOK_FUNCTION;
2503+
pn2 = FunctionDef(cx, ts, tc, JS_TRUE);
2504+
pn2 = NewBinary(cx, TOK_COLON, op, pn3, pn2);
2505+
goto skip;
2506+
}
2507+
}
2508+
/* else fall thru ... */
2509+
#endif
24762510
case TOK_STRING:
24772511
pn3 = NewParseNode(cx, &CURRENT_TOKEN(ts), PN_NULLARY);
24782512
if (pn3)
@@ -2501,6 +2535,7 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
25012535
}
25022536
op = CURRENT_TOKEN(ts).t_op;
25032537
pn2 = NewBinary(cx, TOK_COLON, op, pn3, AssignExpr(cx, ts, tc));
2538+
skip:
25042539
if (!pn2)
25052540
return NULL;
25062541
PN_APPEND(pn, pn2);

js/src/jsscope.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,10 @@ struct JSScopeProperty {
146146
(((sprop)->attrs & JSPROP_SETTER) \
147147
? js_InternalCall(cx, obj, OBJECT_TO_JSVAL(SPROP_SETTER(sprop,obj2)), \
148148
1, vp, vp) \
149-
: SPROP_SETTER(sprop,obj2)(cx, OBJ_THIS_OBJECT(cx,obj), sprop->id, vp))
149+
: ((sprop)->attrs & JSPROP_GETTER) \
150+
? (JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, \
151+
JSMSG_GETTER_ONLY, NULL), JS_FALSE) \
152+
: SPROP_SETTER(sprop,obj2)(cx, OBJ_THIS_OBJECT(cx,obj), sprop->id, vp))
150153

151154
extern JSScope *
152155
js_GetMutableScope(JSContext *cx, JSObject *obj);

js/src/jsstr.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -998,10 +998,16 @@ interpret_dollar(JSContext *cx, jschar *dp, ReplaceData *rdata, size_t *skip)
998998
uintN num, tmp;
999999
JSString *str;
10001000

1001-
/* Allow a real backslash (literal "\\") to escape "$1" etc. */
10021001
JS_ASSERT(*dp == '$');
1003-
if (dp > rdata->repstr->chars && dp[-1] == '\\')
1004-
return NULL;
1002+
1003+
/*
1004+
* Allow a real backslash (literal "\\") to escape "$1" etc.
1005+
* Do this for versions less than 1.5 (ECMA 3) only
1006+
*/
1007+
if (cx->version != JSVERSION_DEFAULT &&
1008+
cx->version <= JSVERSION_1_4)
1009+
if (dp > rdata->repstr->chars && dp[-1] == '\\')
1010+
return NULL;
10051011

10061012
/* Interpret all Perl match-induced dollar variables. */
10071013
res = &cx->regExpStatics;

0 commit comments

Comments
 (0)