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.
This commit is contained in:
rogerl%netscape.com 2000-03-02 23:21:03 +00:00
parent b811298c4b
commit 429c1db8e9
6 changed files with 156 additions and 11 deletions

View File

@ -2239,10 +2239,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
op = JSOP_CALL;
emit_call:
pn2 = pn->pn_head;
if (JSVERSION_IS_ECMA(cx->version) &&
pn2->pn_op == JSOP_NAME &&
if (pn2->pn_op == JSOP_NAME &&
pn2->pn_atom == cx->runtime->atomState.evalAtom) {
op = JSOP_EVAL;
if (JSVERSION_IS_ECMA(cx->version))
op = JSOP_EVAL;
cg->treeContext.flags |= TCF_FUN_HEAVYWEIGHT;
}

View File

@ -516,15 +516,25 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
if (attrs & JSPROP_GETTER) {
val[valcnt] = (jsval)
SPROP_GETTER((JSScopeProperty *)prop, obj2);
#ifdef OLD_GETTER_SETTER
gsop[valcnt] =
ATOM_TO_STRING(cx->runtime->atomState.getterAtom);
#else
gsop[valcnt] =
ATOM_TO_STRING(cx->runtime->atomState.getAtom);
#endif
valcnt++;
}
if (attrs & JSPROP_SETTER) {
val[valcnt] = (jsval)
SPROP_SETTER((JSScopeProperty *)prop, obj2);
#ifdef OLD_GETTER_SETTER
gsop[valcnt] =
ATOM_TO_STRING(cx->runtime->atomState.setterAtom);
#else
gsop[valcnt] =
ATOM_TO_STRING(cx->runtime->atomState.setAtom);
#endif
valcnt++;
}
} else {
@ -572,6 +582,15 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
vchars = valstr->chars;
vlength = valstr->length;
#ifndef OLD_GETTER_SETTER
/* Remove 'function ' from beginning of valstr*/
if (gsop[j]) {
int n = strlen(js_function_str) + 1;
vchars += n;
vlength -= n;
}
#endif
/* If val[j] is a non-sharp object, consider sharpening it. */
vsharp = NULL;
vsharplength = 0;
@ -619,6 +638,7 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
}
comma = ", ";
#ifdef OLD_GETTER_SETTER
js_strncpy(&chars[nchars], idstr->chars, idstr->length);
nchars += idstr->length;
#if JS_HAS_GETTER_SETTER
@ -629,7 +649,17 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
}
#endif
chars[nchars++] = ':';
#else
if (gsop[j]) {
js_strncpy(&chars[nchars], gsop[j]->chars, gsop[j]->length);
nchars += gsop[j]->length;
chars[nchars++] = ' ';
}
js_strncpy(&chars[nchars], idstr->chars, idstr->length);
nchars += idstr->length;
if (!gsop[j])
chars[nchars++] = ':';
#endif
if (vsharplength) {
js_strncpy(&chars[nchars], vsharp, vsharplength);
nchars += vsharplength;
@ -938,6 +968,55 @@ obj_propertyIsEnumerable(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
}
#endif /* JS_HAS_NEW_OBJ_METHODS */
#if JS_HAS_GETTER_SETTER
static JSBool
obj_defineGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
JSAtom *atom;
jsval fval = argv[1];
if (JS_TypeOfValue(cx, fval) != JSTYPE_FUNCTION) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_GETTER_OR_SETTER,
js_getter_str);
return JS_FALSE;
}
atom = js_ValueToStringAtom(cx, argv[0]);
if (!atom)
return JS_FALSE;
return OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID,
(JSPropertyOp) JSVAL_TO_OBJECT(fval),
NULL, JSPROP_GETTER, NULL);
}
static JSBool
obj_defineSetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
JSAtom *atom;
jsval fval = argv[1];
if (JS_TypeOfValue(cx, argv[1]) != JSTYPE_FUNCTION) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_GETTER_OR_SETTER,
js_setter_str);
return JS_FALSE;
}
atom = js_ValueToStringAtom(cx, argv[0]);
if (!atom)
return JS_FALSE;
return OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL,
(JSPropertyOp) JSVAL_TO_OBJECT(argv[1]),
JSPROP_SETTER, NULL);
}
#endif /* JS_HAS_GETTER_SETTER */
static JSFunctionSpec object_methods[] = {
#if JS_HAS_TOSOURCE
{js_toSource_str, js_obj_toSource, 0, 0, OBJ_TOSTRING_EXTRA},
@ -953,6 +1032,10 @@ static JSFunctionSpec object_methods[] = {
{"hasOwnProperty", obj_hasOwnProperty, 1,0,0},
{"isPrototypeOf", obj_isPrototypeOf, 1,0,0},
{"propertyIsEnumerable", obj_propertyIsEnumerable, 1,0,0},
#endif
#if JS_HAS_GETTER_SETTER
{"__defineGetter__", obj_defineGetter, 2,0,0},
{"__defineSetter__", obj_defineSetter, 2,0,0},
#endif
{0,0,0,0,0}
};

View File

@ -2041,16 +2041,34 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
xval = ATOM_BYTES(atom);
lval = POP_STR();
do_initprop:
todo = Sprint(&ss->sprinter, "%s%s%s%s%s:%s",
lval,
#ifdef OLD_GETTER_SETTER
todo = Sprint(&ss->sprinter, "%s%s%s%s%s:%s",
lval,
(lval[1] != '\0') ? ", " : "",
xval,
xval,
(lastop == JSOP_GETTER || lastop == JSOP_SETTER)
? " " : "",
(lastop == JSOP_GETTER) ? js_getter_str :
(lastop == JSOP_SETTER) ? js_setter_str :
"",
rval);
#else
if (lastop == JSOP_GETTER || lastop == JSOP_SETTER) {
todo = Sprint(&ss->sprinter, "%s%s%s %s%s",
lval,
(lval[1] != '\0') ? ", " : "",
(lastop == JSOP_GETTER)
? js_get_str : js_set_str,
xval,
rval + strlen(js_function_str) + 1);
} else {
todo = Sprint(&ss->sprinter, "%s%s%s:%s",
lval,
(lval[1] != '\0') ? ", " : "",
xval,
rval);
}
#endif
break;
case JSOP_INITELEM:

View File

@ -220,6 +220,13 @@ CheckGetterOrSetter(JSContext *cx, JSTokenStream *ts, JSTokenType tt)
return TOK_ERROR;
}
CURRENT_TOKEN(ts).t_op = op;
if (!js_ReportCompileErrorNumber(cx, ts,
JSREPORT_WARNING |
JSREPORT_STRICT,
JSMSG_DEPRECATED_USAGE,
ATOM_BYTES(atom))) {
return TOK_ERROR;
}
return tt;
}
#endif
@ -2360,6 +2367,8 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
JSTokenType tt;
JSParseNode *pn, *pn2, *pn3;
char *badWord;
JSAtom *atom;
JSRuntime *rt;
#if JS_HAS_SHARP_VARS
JSParseNode *defsharp;
@ -2473,6 +2482,31 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn3->pn_dval = CURRENT_TOKEN(ts).t_dval;
break;
case TOK_NAME:
#if JS_HAS_GETTER_SETTER
atom = CURRENT_TOKEN(ts).t_atom;
rt = cx->runtime;
if (atom == rt->atomState.getAtom ||
atom == rt->atomState.setAtom) {
op = (atom == rt->atomState.getAtom)
? JSOP_GETTER
: JSOP_SETTER;
if (js_MatchToken(cx, ts, TOK_NAME)) {
pn3 = NewParseNode(cx, &CURRENT_TOKEN(ts),
PN_NAME);
if (!pn3)
return NULL;
pn3->pn_atom = CURRENT_TOKEN(ts).t_atom;
pn3->pn_expr = NULL;
/* have to fake a 'function' token */
CURRENT_TOKEN(ts).t_op = JSOP_NOP;
CURRENT_TOKEN(ts).type = TOK_FUNCTION;
pn2 = FunctionDef(cx, ts, tc, JS_TRUE);
pn2 = NewBinary(cx, TOK_COLON, op, pn3, pn2);
goto skip;
}
}
/* else fall thru ... */
#endif
case TOK_STRING:
pn3 = NewParseNode(cx, &CURRENT_TOKEN(ts), PN_NULLARY);
if (pn3)
@ -2501,6 +2535,7 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
}
op = CURRENT_TOKEN(ts).t_op;
pn2 = NewBinary(cx, TOK_COLON, op, pn3, AssignExpr(cx, ts, tc));
skip:
if (!pn2)
return NULL;
PN_APPEND(pn, pn2);

View File

@ -146,7 +146,10 @@ struct JSScopeProperty {
(((sprop)->attrs & JSPROP_SETTER) \
? js_InternalCall(cx, obj, OBJECT_TO_JSVAL(SPROP_SETTER(sprop,obj2)), \
1, vp, vp) \
: SPROP_SETTER(sprop,obj2)(cx, OBJ_THIS_OBJECT(cx,obj), sprop->id, vp))
: ((sprop)->attrs & JSPROP_GETTER) \
? (JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, \
JSMSG_GETTER_ONLY, NULL), JS_FALSE) \
: SPROP_SETTER(sprop,obj2)(cx, OBJ_THIS_OBJECT(cx,obj), sprop->id, vp))
extern JSScope *
js_GetMutableScope(JSContext *cx, JSObject *obj);

View File

@ -998,10 +998,16 @@ interpret_dollar(JSContext *cx, jschar *dp, ReplaceData *rdata, size_t *skip)
uintN num, tmp;
JSString *str;
/* Allow a real backslash (literal "\\") to escape "$1" etc. */
JS_ASSERT(*dp == '$');
if (dp > rdata->repstr->chars && dp[-1] == '\\')
return NULL;
/*
* Allow a real backslash (literal "\\") to escape "$1" etc.
* Do this for versions less than 1.5 (ECMA 3) only
*/
if (cx->version != JSVERSION_DEFAULT &&
cx->version <= JSVERSION_1_4)
if (dp > rdata->repstr->chars && dp[-1] == '\\')
return NULL;
/* Interpret all Perl match-induced dollar variables. */
res = &cx->regExpStatics;