Bug 369740: function::name extension is now implemented through a generic xml code. r=brendan

This commit is contained in:
igor.bukanov%gmail.com 2007-02-21 20:30:50 +00:00
Родитель 42a3a3f5ff
Коммит db18ea3bb6
9 изменённых файлов: 66 добавлений и 118 удалений

Просмотреть файл

@ -942,12 +942,6 @@ GetSwitchTableBounds(JSScript *script, uintN offset,
}
/*
* SrcNotes assumes that SRC_METHODBASE should be distinguished from SRC_LABEL
* using the bytecode the source note points to.
*/
JS_STATIC_ASSERT(SRC_LABEL == SRC_METHODBASE);
static void
SrcNotes(JSContext *cx, JSScript *script)
{
@ -955,7 +949,6 @@ SrcNotes(JSContext *cx, JSScript *script)
jssrcnote *notes, *sn;
JSSrcNoteType type;
const char *name;
JSOp op;
jsatomid atomIndex;
JSAtom *atom;
@ -969,18 +962,11 @@ SrcNotes(JSContext *cx, JSScript *script)
type = (JSSrcNoteType) SN_TYPE(sn);
name = js_SrcNoteSpec[type].name;
if (type == SRC_LABEL) {
/* Heavily overloaded case. */
/* Check if the source note is for a switch case. */
if (switchTableStart <= offset && offset < switchTableEnd) {
name = "case";
} else {
op = script->code[offset];
if (op == JSOP_GETMETHOD || op == JSOP_SETMETHOD) {
/* This is SRC_METHODBASE which we print as SRC_PCBASE. */
type = SRC_PCBASE;
name = "methodbase";
} else {
JS_ASSERT(op == JSOP_NOP);
}
JS_ASSERT(script->code[offset] == JSOP_NOP);
}
}
fprintf(gOutFile, "%3u: %5u [%4u] %-8s",

Просмотреть файл

@ -2276,25 +2276,6 @@ CheckSideEffects(JSContext *cx, JSTreeContext *tc, JSParseNode *pn,
return ok;
}
/*
* Secret handshake with js_EmitTree's TOK_LP/TOK_NEW case logic, to flag all
* uses of JSOP_GETMETHOD that implicitly qualify the method property's name
* with a function:: prefix. All other JSOP_GETMETHOD and JSOP_SETMETHOD uses
* must be explicit, so we need a distinct source note (SRC_METHODBASE rather
* than SRC_PCBASE) for round-tripping through the beloved decompiler.
*/
#define JSPROP_IMPLICIT_FUNCTION_NAMESPACE 0x100
static jssrcnote
SrcNoteForPropOp(JSParseNode *pn, JSOp op)
{
return ((op == JSOP_GETMETHOD &&
!(pn->pn_attrs & JSPROP_IMPLICIT_FUNCTION_NAMESPACE)) ||
op == JSOP_SETMETHOD)
? SRC_METHODBASE
: SRC_PCBASE;
}
static JSBool
EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
{
@ -2374,7 +2355,7 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
do {
/* Walk back up the list, emitting annotated name ops. */
if (js_NewSrcNote2(cx, cg, SrcNoteForPropOp(pndot, pndot->pn_op),
if (js_NewSrcNote2(cx, cg, SRC_PCBASE,
CG_OFFSET(cg) - pndown->pn_offset) < 0) {
return JS_FALSE;
}
@ -2391,7 +2372,7 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
return JS_FALSE;
}
if (js_NewSrcNote2(cx, cg, SrcNoteForPropOp(pn, op),
if (js_NewSrcNote2(cx, cg, SRC_PCBASE,
CG_OFFSET(cg) - pn2->pn_offset) < 0) {
return JS_FALSE;
}
@ -5396,8 +5377,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
pn2->pn_type != TOK_RB &&
pn2->pn_type != TOK_RC &&
#endif
js_NewSrcNote2(cx, cg, SrcNoteForPropOp(pn2, pn2->pn_op),
CG_OFFSET(cg) - top) < 0) {
js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) {
return JS_FALSE;
}
@ -5832,16 +5812,15 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
* constructable object expression.
*
* For E4X, if this expression is a dotted member reference, select
* JSOP_GETMETHOD instead of JSOP_GETPROP. ECMA-357 separates XML
* JSOP_CALLPROP instead of JSOP_GETPROP. ECMA-357 separates XML
* method lookup from the normal property id lookup done for native
* objects.
*/
pn2 = pn->pn_head;
#if JS_HAS_XML_SUPPORT
if (pn2->pn_type == TOK_DOT && pn2->pn_op != JSOP_GETMETHOD) {
if (pn2->pn_type == TOK_DOT) {
JS_ASSERT(pn2->pn_op == JSOP_GETPROP);
pn2->pn_op = JSOP_GETMETHOD;
pn2->pn_attrs |= JSPROP_IMPLICIT_FUNCTION_NAMESPACE;
pn2->pn_op = JSOP_CALLPROP;
}
#endif
if (!js_EmitTree(cx, cg, pn2))

Просмотреть файл

@ -549,9 +549,6 @@ typedef enum JSSrcNoteType {
SRC_PCBASE = 12, /* distance back from annotated getprop or
setprop op to left-most obj.prop.subprop
bytecode -- always a backward delta */
SRC_METHODBASE = 13, /* SRC_PCBASE variant for obj.function::foo
gets and sets; disjoint from SRC_LABEL by
bytecode to which it applies */
SRC_LABEL = 13, /* JSOP_NOP for label: with atomid immediate */
SRC_LABELBRACE = 14, /* JSOP_NOP for label: {...} begin brace */
SRC_ENDBRACE = 15, /* JSOP_NOP for label: {...} end brace */

Просмотреть файл

@ -639,7 +639,7 @@ NoSuchMethod(JSContext *cx, JSStackFrame *fp, jsval *vp, uint32 flags,
case JSOP_NAME:
case JSOP_GETPROP:
#if JS_HAS_XML_SUPPORT
case JSOP_GETMETHOD:
case JSOP_CALLPROP:
#endif
atom = js_GetAtomFromBytecode(fp->script, pc, 0);
argc = *argcp;
@ -1965,11 +1965,19 @@ InternNonIntElementId(JSContext *cx, jsval idval, jsid *idp)
}
#if JS_HAS_XML_SUPPORT
static JSBool
InternNonXmlObjectId(JSContext *cx, JSObject *obj, jsid *idp)
{
if (!js_IsFunctionQName(cx, obj, idp))
return JS_FALSE;
return *idp != 0 || InternStringElementId(cx, OBJECT_TO_JSVAL(obj), idp);
}
#define CHECK_ELEMENT_ID(obj, id) \
JS_BEGIN_MACRO \
if (JSID_IS_OBJECT(id) && !OBJECT_IS_XML(cx, obj)) { \
SAVE_SP_AND_PC(fp); \
ok = InternStringElementId(cx, OBJECT_JSID_TO_JSVAL(id), &id); \
ok = InternNonXmlObjectId(cx, JSID_TO_OBJECT(id), &id); \
if (!ok) \
goto out; \
} \
@ -5760,7 +5768,7 @@ interrupt:
STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
END_CASE(JSOP_XMLPI)
BEGIN_CASE(JSOP_GETMETHOD)
BEGIN_CASE(JSOP_CALLPROP)
/* Get an immediate atom naming the property. */
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
@ -5806,31 +5814,7 @@ interrupt:
if (!ok)
goto out;
STORE_OPND(-1, rval);
END_CASE(JSOP_GETMETHOD)
BEGIN_CASE(JSOP_SETMETHOD)
/* Get an immediate atom naming the property. */
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
rval = FETCH_OPND(-1);
FETCH_OBJECT(cx, -2, lval, obj);
SAVE_SP_AND_PC(fp);
/* Special-case XML object method lookup, per ECMA-357. */
if (OBJECT_IS_XML(cx, obj)) {
JSXMLObjectOps *ops;
ops = (JSXMLObjectOps *) obj->map->ops;
ok = ops->setMethod(cx, obj, id, &rval);
} else {
ok = OBJ_SET_PROPERTY(cx, obj, id, &rval);
}
if (!ok)
goto out;
--sp;
STORE_OPND(-1, rval);
obj = NULL;
END_CASE(JSOP_SETMETHOD)
END_CASE(JSOP_CALLPROP)
BEGIN_CASE(JSOP_GETFUNNS)
SAVE_SP_AND_PC(fp);
@ -6063,6 +6047,7 @@ interrupt:
#if JS_THREADED_INTERP
L_JSOP_BACKPATCH:
L_JSOP_BACKPATCH_POP:
L_JSOP_UNUSED194:
L_JSOP_UNUSED197:
#else
default:

Просмотреть файл

@ -3273,14 +3273,15 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
(void) PopOff(ss, lastop);
/* FALL THROUGH */
#if JS_HAS_XML_SUPPORT
case JSOP_CALLPROP:
#endif
case JSOP_GETPROP:
case JSOP_GETXPROP:
LOAD_ATOM(0);
do_getprop:
GET_QUOTE_AND_FMT(index_format, dot_format, rval);
do_getprop_lval:
lval = POP_STR();
todo = Sprint(&ss->sprinter, fmt, lval, rval);
break;
@ -3311,31 +3312,9 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
return NULL;
goto do_getprop;
#if JS_HAS_XML_SUPPORT
BEGIN_LITOPX_CASE(JSOP_GETMETHOD, 0)
sn = js_GetSrcNote(jp->script, pc);
if (sn && SN_TYPE(sn) == SRC_PCBASE)
goto do_getprop;
GET_QUOTE_AND_FMT("%s.function::[%s]", "%s.function::%s", rval);
goto do_getprop_lval;
BEGIN_LITOPX_CASE(JSOP_SETMETHOD, 0)
sn = js_GetSrcNote(jp->script, pc);
if (sn && SN_TYPE(sn) == SRC_PCBASE)
goto do_setprop;
GET_QUOTE_AND_FMT("%s.function::[%s] %s= %s",
"%s.function::%s %s= %s",
xval);
goto do_setprop_rval;
#endif
case JSOP_SETPROP:
LOAD_ATOM(0);
do_setprop:
GET_QUOTE_AND_FMT("%s[%s] %s= %s", "%s.%s %s= %s", xval);
do_setprop_rval:
rval = POP_STR();
/*

Просмотреть файл

@ -401,7 +401,7 @@ OPDEF(JSOP_XMLOBJECT, 180,"xmlobject", NULL, 3, 0, 1, 19, JOF_CONST)
OPDEF(JSOP_XMLCDATA, 181,"xmlcdata", NULL, 3, 0, 1, 19, JOF_CONST)
OPDEF(JSOP_XMLCOMMENT, 182,"xmlcomment", NULL, 3, 0, 1, 19, JOF_CONST)
OPDEF(JSOP_XMLPI, 183,"xmlpi", NULL, 3, 1, 1, 19, JOF_CONST)
OPDEF(JSOP_GETMETHOD, 184,"getmethod", NULL, 3, 1, 1, 18, JOF_CONST|JOF_PROP)
OPDEF(JSOP_CALLPROP, 184,"callprop", NULL, 3, 1, 1, 18, JOF_CONST|JOF_PROP)
OPDEF(JSOP_GETFUNNS, 185,"getfunns", NULL, 1, 0, 1, 19, JOF_BYTE)
OPDEF(JSOP_FOREACH, 186,"foreach", NULL, 1, 1, 1, 0, JOF_BYTE)
OPDEF(JSOP_DELDESC, 187,"deldesc", NULL, 1, 2, 1, 17, JOF_BYTE |JOF_ELEM|JOF_DEL)
@ -426,7 +426,7 @@ OPDEF(JSOP_RESETBASE0, 191,"resetbase0", NULL, 1, 0, 0, 0, JOF_BYTE)
*/
OPDEF(JSOP_STARTXML, 192,"startxml", NULL, 1, 0, 0, 0, JOF_BYTE)
OPDEF(JSOP_STARTXMLEXPR, 193,"startxmlexpr",NULL, 1, 0, 0, 0, JOF_BYTE)
OPDEF(JSOP_SETMETHOD, 194,"setmethod", NULL, 3, 2, 1, 3, JOF_CONST|JOF_PROP|JOF_SET|JOF_ASSIGNING|JOF_DETECTING)
OPDEF(JSOP_UNUSED194, 194,"", NULL, 1, 0, 0, 0, 0)
/*
* Stop interpretation, emitted at end of script to save the threaded bytecode

Просмотреть файл

@ -3810,9 +3810,7 @@ AssignExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
tc->flags |= TCF_FUN_HEAVYWEIGHT;
break;
case TOK_DOT:
pn2->pn_op = (pn2->pn_op == JSOP_GETMETHOD)
? JSOP_SETMETHOD
: JSOP_SETPROP;
pn2->pn_op = JSOP_SETPROP;
break;
case TOK_LB:
pn2->pn_op = JSOP_SETELEM;
@ -4315,11 +4313,8 @@ MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
if (!pn3)
return NULL;
tt = pn3->pn_type;
if (tt == TOK_NAME ||
(tt == TOK_DBLCOLON &&
pn3->pn_arity == PN_NAME &&
pn3->pn_expr->pn_type == TOK_FUNCTION)) {
pn2->pn_op = (tt == TOK_NAME) ? JSOP_GETPROP : JSOP_GETMETHOD;
if (tt == TOK_NAME) {
pn2->pn_op = JSOP_GETPROP;
pn2->pn_expr = pn;
pn2->pn_atom = pn3->pn_atom;
RecycleTree(pn3, tc);

Просмотреть файл

@ -3110,6 +3110,34 @@ ReportBadXMLName(JSContext *cx, jsval id)
js_ReportValueError(cx, JSMSG_BAD_XML_NAME, JSDVG_IGNORE_STACK, id, NULL);
}
static JSBool
IsFunctionQName(JSContext *cx, JSXMLQName *qn, jsid *funidp)
{
JSAtom *atom;
atom = cx->runtime->atomState.lazy.functionNamespaceURIAtom;
if (qn->uri && atom &&
(qn->uri == ATOM_TO_STRING(atom) ||
js_EqualStrings(qn->uri, ATOM_TO_STRING(atom)))) {
return JS_ValueToId(cx, STRING_TO_JSVAL(qn->localName), funidp);
}
*funidp = 0;
return JS_TRUE;
}
JSBool
js_IsFunctionQName(JSContext *cx, JSObject *obj, jsid *funidp)
{
JSXMLQName *qn;
if (OBJ_GET_CLASS(cx, obj) == &js_QNameClass.base) {
qn = (JSXMLQName *) JS_GetPrivate(cx, obj);
return IsFunctionQName(cx, qn, funidp);
}
*funidp = 0;
return JS_TRUE;
}
static JSXMLQName *
ToXMLName(JSContext *cx, jsval v, jsid *funidp)
{
@ -3118,7 +3146,6 @@ ToXMLName(JSContext *cx, jsval v, jsid *funidp)
JSClass *clasp;
uint32 index;
JSXMLQName *qn;
JSAtom *atom;
if (JSVAL_IS_STRING(v)) {
name = JSVAL_TO_STRING(v);
@ -3173,15 +3200,8 @@ construct:
out:
qn = (JSXMLQName *) JS_GetPrivate(cx, obj);
atom = cx->runtime->atomState.lazy.functionNamespaceURIAtom;
if (qn->uri && atom &&
(qn->uri == ATOM_TO_STRING(atom) ||
js_EqualStrings(qn->uri, ATOM_TO_STRING(atom)))) {
if (!JS_ValueToId(cx, STRING_TO_JSVAL(qn->localName), funidp))
return NULL;
} else {
*funidp = 0;
}
if (!IsFunctionQName(cx, qn, funidp))
return NULL;
return qn;
bad:

Просмотреть файл

@ -253,6 +253,13 @@ js_InitXMLClasses(JSContext *cx, JSObject *obj);
extern JSBool
js_GetFunctionNamespace(JSContext *cx, jsval *vp);
/*
* If obj is QName corresponding to function::name, set *funidp to name's id,
* otherwise set *funidp to 0.
*/
JSBool
js_IsFunctionQName(JSContext *cx, JSObject *obj, jsid *funidp);
extern JSBool
js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp);