зеркало из https://github.com/mozilla/gecko-dev.git
Bug 369740: function::name extension is now implemented through a generic xml code. r=brendan
This commit is contained in:
Родитель
42a3a3f5ff
Коммит
db18ea3bb6
18
js/src/js.c
18
js/src/js.c
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче