зеркало из https://github.com/mozilla/pjs.git
Fixing bug 256317: report about invalid references during parsing, not runtime.
This commit is contained in:
Родитель
e908f13c42
Коммит
a60c5d3cb3
|
@ -1016,6 +1016,18 @@ final class IRFactory
|
||||||
|
|
||||||
Node createIncDec(int nodeType, boolean post, Node child)
|
Node createIncDec(int nodeType, boolean post, Node child)
|
||||||
{
|
{
|
||||||
|
child = makeReference(child);
|
||||||
|
if (child == null) {
|
||||||
|
String msg;
|
||||||
|
if (nodeType == Token.DEC) {
|
||||||
|
msg = "msg.bad.decr";
|
||||||
|
} else {
|
||||||
|
msg = "msg.bad.incr";
|
||||||
|
}
|
||||||
|
parser.reportError(msg);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
int childType = child.getType();
|
int childType = child.getType();
|
||||||
|
|
||||||
switch (childType) {
|
switch (childType) {
|
||||||
|
@ -1035,19 +1047,7 @@ final class IRFactory
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return createIncDec(nodeType, post, makeReferenceGet(child));
|
throw Kit.codeBug();
|
||||||
}
|
|
||||||
|
|
||||||
private Node makeReferenceGet(Node node)
|
|
||||||
{
|
|
||||||
Node ref;
|
|
||||||
if (node.getType() == Token.CALL) {
|
|
||||||
node.setType(Token.REF_CALL);
|
|
||||||
ref = node;
|
|
||||||
} else {
|
|
||||||
ref = new Node(Token.GENERIC_REF, node);
|
|
||||||
}
|
|
||||||
return new Node(Token.GET_REF, ref);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1227,6 +1227,12 @@ final class IRFactory
|
||||||
|
|
||||||
Node createAssignment(Node left, Node right)
|
Node createAssignment(Node left, Node right)
|
||||||
{
|
{
|
||||||
|
left = makeReference(left);
|
||||||
|
if (left == null) {
|
||||||
|
parser.reportError("msg.bad.assign.left");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
int nodeType = left.getType();
|
int nodeType = left.getType();
|
||||||
switch (nodeType) {
|
switch (nodeType) {
|
||||||
case Token.NAME:
|
case Token.NAME:
|
||||||
|
@ -1250,11 +1256,18 @@ final class IRFactory
|
||||||
return new Node(Token.SET_REF, ref, right);
|
return new Node(Token.SET_REF, ref, right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return createAssignment(makeReferenceGet(left), right);
|
|
||||||
|
throw Kit.codeBug();
|
||||||
}
|
}
|
||||||
|
|
||||||
Node createAssignmentOp(int assignOp, Node left, Node right)
|
Node createAssignmentOp(int assignOp, Node left, Node right)
|
||||||
{
|
{
|
||||||
|
left = makeReference(left);
|
||||||
|
if (left == null) {
|
||||||
|
parser.reportError("msg.bad.assign.left");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
int nodeType = left.getType();
|
int nodeType = left.getType();
|
||||||
switch (nodeType) {
|
switch (nodeType) {
|
||||||
case Token.NAME: {
|
case Token.NAME: {
|
||||||
|
@ -1285,7 +1298,8 @@ final class IRFactory
|
||||||
return new Node(Token.SET_REF_OP, ref, op);
|
return new Node(Token.SET_REF_OP, ref, op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return createAssignmentOp(assignOp, makeReferenceGet(left), right);
|
|
||||||
|
throw Kit.codeBug();
|
||||||
}
|
}
|
||||||
|
|
||||||
Node createUseLocal(Node localBlock)
|
Node createUseLocal(Node localBlock)
|
||||||
|
@ -1296,6 +1310,23 @@ final class IRFactory
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Node makeReference(Node node)
|
||||||
|
{
|
||||||
|
int type = node.getType();
|
||||||
|
switch (type) {
|
||||||
|
case Token.NAME:
|
||||||
|
case Token.GETPROP:
|
||||||
|
case Token.GETELEM:
|
||||||
|
case Token.GET_REF:
|
||||||
|
return node;
|
||||||
|
case Token.CALL:
|
||||||
|
node.setType(Token.REF_CALL);
|
||||||
|
return new Node(Token.GET_REF, node);
|
||||||
|
}
|
||||||
|
// Signal caller to report error
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if Node always mean true or false in boolean context
|
// Check if Node always mean true or false in boolean context
|
||||||
private static int isAlwaysDefinedBoolean(Node node)
|
private static int isAlwaysDefinedBoolean(Node node)
|
||||||
{
|
{
|
||||||
|
|
|
@ -972,7 +972,6 @@ public class Interpreter
|
||||||
}
|
}
|
||||||
|
|
||||||
case Token.XML_REF:
|
case Token.XML_REF:
|
||||||
case Token.GENERIC_REF:
|
|
||||||
visitExpression(child);
|
visitExpression(child);
|
||||||
addToken(type);
|
addToken(type);
|
||||||
break;
|
break;
|
||||||
|
@ -2839,12 +2838,6 @@ switch (op) {
|
||||||
stack[stackTop] = ScriptRuntime.xmlReference(lhs, cx, scope);
|
stack[stackTop] = ScriptRuntime.xmlReference(lhs, cx, scope);
|
||||||
continue Loop;
|
continue Loop;
|
||||||
}
|
}
|
||||||
case Token.GENERIC_REF : {
|
|
||||||
Object lhs = stack[stackTop];
|
|
||||||
if (lhs == DBL_MRK) lhs = doubleWrap(sDbl[stackTop]);
|
|
||||||
stack[stackTop] = ScriptRuntime.genericReference(lhs, cx, scope);
|
|
||||||
continue Loop;
|
|
||||||
}
|
|
||||||
case Icode_SCOPE :
|
case Icode_SCOPE :
|
||||||
stack[++stackTop] = scope;
|
stack[++stackTop] = scope;
|
||||||
continue Loop;
|
continue Loop;
|
||||||
|
|
|
@ -1616,13 +1616,6 @@ public class ScriptRuntime {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object genericReference(Object obj,
|
|
||||||
Context cx, Scriptable scope)
|
|
||||||
{
|
|
||||||
String msg = getMessage1("msg.not.ref", toString(obj));
|
|
||||||
throw constructError("ReferenceError", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The delete operator
|
* The delete operator
|
||||||
*
|
*
|
||||||
|
|
|
@ -142,87 +142,86 @@ public class Token
|
||||||
DEL_REF = 67, // delete reference
|
DEL_REF = 67, // delete reference
|
||||||
REF_CALL = 68, // f(args) = something or f(args)++
|
REF_CALL = 68, // f(args) = something or f(args)++
|
||||||
SPECIAL_REF = 69, // reference for special properties like __proto
|
SPECIAL_REF = 69, // reference for special properties like __proto
|
||||||
GENERIC_REF = 70, // generic reference to generate runtime ref errors
|
|
||||||
|
|
||||||
// For XML support:
|
// For XML support:
|
||||||
DEFAULTNAMESPACE = 71, // default xml namespace =
|
DEFAULTNAMESPACE = 70, // default xml namespace =
|
||||||
COLONCOLON = 72, // ::
|
COLONCOLON = 71, // ::
|
||||||
ESCXMLATTR = 73,
|
ESCXMLATTR = 72,
|
||||||
ESCXMLTEXT = 74,
|
ESCXMLTEXT = 73,
|
||||||
TOATTRNAME = 75,
|
TOATTRNAME = 74,
|
||||||
DESCENDANTS = 76,
|
DESCENDANTS = 75,
|
||||||
XML_REF = 77,
|
XML_REF = 76,
|
||||||
|
|
||||||
LAST_BYTECODE_TOKEN = 77,
|
LAST_BYTECODE_TOKEN = 76,
|
||||||
// End of interpreter bytecodes
|
// End of interpreter bytecodes
|
||||||
|
|
||||||
TRY = 78,
|
TRY = 77,
|
||||||
SEMI = 79, // semicolon
|
SEMI = 78, // semicolon
|
||||||
LB = 80, // left and right brackets
|
LB = 79, // left and right brackets
|
||||||
RB = 81,
|
RB = 80,
|
||||||
LC = 82, // left and right curlies (braces)
|
LC = 81, // left and right curlies (braces)
|
||||||
RC = 83,
|
RC = 82,
|
||||||
LP = 84, // left and right parentheses
|
LP = 83, // left and right parentheses
|
||||||
RP = 85,
|
RP = 84,
|
||||||
COMMA = 86, // comma operator
|
COMMA = 85, // comma operator
|
||||||
ASSIGN = 87, // simple assignment (=)
|
ASSIGN = 86, // simple assignment (=)
|
||||||
ASSIGNOP = 88, // assignment with operation (+= -= etc.)
|
ASSIGNOP = 87, // assignment with operation (+= -= etc.)
|
||||||
HOOK = 89, // conditional (?:)
|
HOOK = 88, // conditional (?:)
|
||||||
COLON = 90,
|
COLON = 89,
|
||||||
OR = 91, // logical or (||)
|
OR = 90, // logical or (||)
|
||||||
AND = 92, // logical and (&&)
|
AND = 91, // logical and (&&)
|
||||||
INC = 93, // increment/decrement (++ --)
|
INC = 92, // increment/decrement (++ --)
|
||||||
DEC = 94,
|
DEC = 93,
|
||||||
DOT = 95, // member operator (.)
|
DOT = 94, // member operator (.)
|
||||||
FUNCTION = 96, // function keyword
|
FUNCTION = 95, // function keyword
|
||||||
EXPORT = 97, // export keyword
|
EXPORT = 96, // export keyword
|
||||||
IMPORT = 98, // import keyword
|
IMPORT = 97, // import keyword
|
||||||
IF = 99, // if keyword
|
IF = 98, // if keyword
|
||||||
ELSE = 100, // else keyword
|
ELSE = 99, // else keyword
|
||||||
SWITCH = 101, // switch keyword
|
SWITCH = 100, // switch keyword
|
||||||
CASE = 102, // case keyword
|
CASE = 101, // case keyword
|
||||||
DEFAULT = 103, // default keyword
|
DEFAULT = 102, // default keyword
|
||||||
WHILE = 104, // while keyword
|
WHILE = 103, // while keyword
|
||||||
DO = 105, // do keyword
|
DO = 104, // do keyword
|
||||||
FOR = 106, // for keyword
|
FOR = 105, // for keyword
|
||||||
BREAK = 107, // break keyword
|
BREAK = 106, // break keyword
|
||||||
CONTINUE = 108, // continue keyword
|
CONTINUE = 107, // continue keyword
|
||||||
VAR = 109, // var keyword
|
VAR = 108, // var keyword
|
||||||
WITH = 110, // with keyword
|
WITH = 109, // with keyword
|
||||||
CATCH = 111, // catch keyword
|
CATCH = 110, // catch keyword
|
||||||
FINALLY = 112, // finally keyword
|
FINALLY = 111, // finally keyword
|
||||||
VOID = 113, // void keyword
|
VOID = 112, // void keyword
|
||||||
RESERVED = 114, // reserved keywords
|
RESERVED = 113, // reserved keywords
|
||||||
|
|
||||||
EMPTY = 115,
|
EMPTY = 114,
|
||||||
|
|
||||||
/* types used for the parse tree - these never get returned
|
/* types used for the parse tree - these never get returned
|
||||||
* by the scanner.
|
* by the scanner.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BLOCK = 116, // statement block
|
BLOCK = 115, // statement block
|
||||||
LABEL = 117, // label
|
LABEL = 116, // label
|
||||||
TARGET = 118,
|
TARGET = 117,
|
||||||
LOOP = 119,
|
LOOP = 118,
|
||||||
EXPR_VOID = 120, // expression statement in functions
|
EXPR_VOID = 119, // expression statement in functions
|
||||||
EXPR_RESULT = 121, // expression statement in scripts
|
EXPR_RESULT = 120, // expression statement in scripts
|
||||||
JSR = 122,
|
JSR = 121,
|
||||||
SCRIPT = 123, // top-level node for entire script
|
SCRIPT = 122, // top-level node for entire script
|
||||||
TYPEOFNAME = 124, // for typeof(simple-name)
|
TYPEOFNAME = 123, // for typeof(simple-name)
|
||||||
USE_STACK = 125,
|
USE_STACK = 124,
|
||||||
SETPROP_OP = 126, // x.y op= something
|
SETPROP_OP = 125, // x.y op= something
|
||||||
SETELEM_OP = 127, // x[y] op= something
|
SETELEM_OP = 126, // x[y] op= something
|
||||||
LOCAL_BLOCK = 128,
|
LOCAL_BLOCK = 127,
|
||||||
SET_REF_OP = 129, // *reference op= something
|
SET_REF_OP = 128, // *reference op= something
|
||||||
|
|
||||||
// For XML support:
|
// For XML support:
|
||||||
DOTDOT = 130, // member operator (..)
|
DOTDOT = 129, // member operator (..)
|
||||||
XML = 131, // XML type
|
XML = 130, // XML type
|
||||||
DOTQUERY = 132, // .() -- e.g., x.emps.emp.(name == "terry")
|
DOTQUERY = 131, // .() -- e.g., x.emps.emp.(name == "terry")
|
||||||
XMLATTR = 133, // @
|
XMLATTR = 132, // @
|
||||||
XMLEND = 134,
|
XMLEND = 133,
|
||||||
|
|
||||||
LAST_TOKEN = 134;
|
LAST_TOKEN = 133;
|
||||||
|
|
||||||
public static String name(int token)
|
public static String name(int token)
|
||||||
{
|
{
|
||||||
|
@ -306,7 +305,6 @@ public class Token
|
||||||
case DEL_REF: return "DEL_REF";
|
case DEL_REF: return "DEL_REF";
|
||||||
case REF_CALL: return "REF_CALL";
|
case REF_CALL: return "REF_CALL";
|
||||||
case SPECIAL_REF: return "SPECIAL_REF";
|
case SPECIAL_REF: return "SPECIAL_REF";
|
||||||
case GENERIC_REF: return "GENERIC_REF";
|
|
||||||
case DEFAULTNAMESPACE:return "DEFAULTNAMESPACE";
|
case DEFAULTNAMESPACE:return "DEFAULTNAMESPACE";
|
||||||
case COLONCOLON: return "COLONCOLON";
|
case COLONCOLON: return "COLONCOLON";
|
||||||
case ESCXMLTEXT: return "ESCXMLTEXT";
|
case ESCXMLTEXT: return "ESCXMLTEXT";
|
||||||
|
|
|
@ -1952,10 +1952,6 @@ class BodyCodegen
|
||||||
visitXMLRef(node, child);
|
visitXMLRef(node, child);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Token.GENERIC_REF:
|
|
||||||
visitGenericRef(node, child);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Token.DOTQUERY:
|
case Token.DOTQUERY:
|
||||||
visitDotQuery(node, child);
|
visitDotQuery(node, child);
|
||||||
break;
|
break;
|
||||||
|
@ -3815,18 +3811,6 @@ Else pass the JS object in the aReg and 0.0 in the dReg.
|
||||||
+")Ljava/lang/Object;");
|
+")Ljava/lang/Object;");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void visitGenericRef(Node node, Node child)
|
|
||||||
{
|
|
||||||
generateExpression(child, node);
|
|
||||||
cfw.addALoad(contextLocal);
|
|
||||||
cfw.addALoad(variableObjectLocal);
|
|
||||||
addScriptRuntimeInvoke("genericReference",
|
|
||||||
"(Ljava/lang/Object;"
|
|
||||||
+"Lorg/mozilla/javascript/Context;"
|
|
||||||
+"Lorg/mozilla/javascript/Scriptable;"
|
|
||||||
+")Ljava/lang/Object;");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void visitDotQuery(Node node, Node child)
|
private void visitDotQuery(Node node, Node child)
|
||||||
{
|
{
|
||||||
updateLineNumber(node);
|
updateLineNumber(node);
|
||||||
|
|
|
@ -112,6 +112,15 @@ msg.mult.index =\
|
||||||
msg.cant.convert =\
|
msg.cant.convert =\
|
||||||
Can''t convert to type "{0}".
|
Can''t convert to type "{0}".
|
||||||
|
|
||||||
|
msg.bad.assign.left =\
|
||||||
|
Invalid assignment left-hand side.
|
||||||
|
|
||||||
|
msg.bad.decr =\
|
||||||
|
Invalid decerement operand.
|
||||||
|
|
||||||
|
msg.bad.incr =\
|
||||||
|
Invalid increment operand.
|
||||||
|
|
||||||
# NativeGlobal
|
# NativeGlobal
|
||||||
msg.cant.call.indirect =\
|
msg.cant.call.indirect =\
|
||||||
Function "{0}" must be called directly, and not by way of a \
|
Function "{0}" must be called directly, and not by way of a \
|
||||||
|
@ -442,10 +451,6 @@ msg.no.ref.from.function =\
|
||||||
Function {0} can not be used as the left-hand side of assignment \
|
Function {0} can not be used as the left-hand side of assignment \
|
||||||
or as an operand of ++ or -- operator.
|
or as an operand of ++ or -- operator.
|
||||||
|
|
||||||
msg.not.ref =\
|
|
||||||
{0} can not be used as the left-hand side of assignment \
|
|
||||||
or as an operand of ++ or -- operator.
|
|
||||||
|
|
||||||
msg.bad.default.value =\
|
msg.bad.default.value =\
|
||||||
Object''s getDefaultValue() method returned an object.
|
Object''s getDefaultValue() method returned an object.
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче