@Override public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) { // handle debugger statement final Node expression = expressionStatement.getExpression(); if (expression instanceof RuntimeNode) { expression.accept(this); return false; } enterDefault(expressionStatement); type("ExpressionStatement"); comma(); property("expression"); expression.accept(this); return leave(); }
private Node leaveTYPEOF(final UnaryNode unaryNode) { final Expression rhs = unaryNode.getExpression(); final List<Expression> args = new ArrayList<>(); if (rhs instanceof IdentNode && !isParamOrVar((IdentNode)rhs)) { args.add(compilerConstantIdentifier(SCOPE)); args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null } else { args.add(rhs); args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this' } final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args).accept(this); end(unaryNode); return runtimeNode; }
private Node leaveTYPEOF(final UnaryNode unaryNode) { final Expression rhs = unaryNode.getExpression(); final List<Expression> args = new ArrayList<>(); if (rhs instanceof IdentNode && !isParamOrVar((IdentNode)rhs)) { args.add(compilerConstantIdentifier(SCOPE)); args.add(LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName())); //null } else { args.add(rhs); args.add(LiteralNode.newInstance(unaryNode)); //null, do not reuse token of identifier rhs, it can be e.g. 'this' } final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args); end(unaryNode); return runtimeNode; }
/** * Add is a special binary, as it works not only on arithmetic, but for * strings etc as well. */ @Override public Expression leaveADD(final BinaryNode binaryNode) { final Expression lhs = binaryNode.lhs(); final Expression rhs = binaryNode.rhs(); final Type type = binaryNode.getType(); if (type.isObject()) { if (!isAddString(binaryNode)) { return new RuntimeNode(binaryNode, Request.ADD); } } return binaryNode.setLHS(convert(lhs, type)).setRHS(convert(rhs, type)); }
/** * DebuggerStatement : * debugger ; * * See 12.15 * * Parse debugger statement. */ private void debuggerStatement() { // Capture DEBUGGER token. final int debuggerLine = line; final long debuggerToken = token; // DEBUGGER tested in caller. next(); endOfLine(); appendStatement(new ExpressionStatement(debuggerLine, debuggerToken, finish, new RuntimeNode(debuggerToken, finish, RuntimeNode.Request.DEBUGGER, new ArrayList<Expression>()))); }
private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) { if (earlyError) { throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken()); } final ArrayList<Expression> args = new ArrayList<>(); args.add(lhs); if (rhs == null) { args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish())); } else { args.add(rhs); } args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString())); return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args); }
@Override public boolean enterRuntimeNode(final RuntimeNode runtimeNode) { final RuntimeNode.Request req = runtimeNode.getRequest(); if (req == RuntimeNode.Request.DEBUGGER) { enterDefault(runtimeNode); type("DebuggerStatement"); return leave(); } return false; }
/** * Generate a dynamic call for a runtime node * * @param name tag for the invoke dynamic for this runtime node * @param returnType return type * @param request RuntimeNode request * * @return the method emitter */ MethodEmitter dynamicRuntimeCall(final String name, final Type returnType, final RuntimeNode.Request request) { debug("dynamic_runtime_call", name, "args=", request.getArity(), "returnType=", returnType); final String signature = getDynamicSignature(returnType, request.getArity()); debug(" signature", signature); method.visitInvokeDynamicInsn(name, signature, RUNTIMEBOOTSTRAP); pushType(returnType); return this; }
@Override public Node leaveRuntimeNode(final RuntimeNode runtimeNode) { final Request request = runtimeNode.getRequest(); final boolean isEqStrict = request == Request.EQ_STRICT; if(isEqStrict || request == Request.NE_STRICT) { return createIsUndefined(runtimeNode, runtimeNode.getArgs().get(0), runtimeNode.getArgs().get(1), isEqStrict ? Request.IS_UNDEFINED : Request.IS_NOT_UNDEFINED); } return runtimeNode; }
private void loadRuntimeNode(final RuntimeNode runtimeNode) { final List<Expression> args = new ArrayList<>(runtimeNode.getArgs()); if (nullCheck(runtimeNode, args)) { return; } else if(undefinedCheck(runtimeNode, args)) { return; } // Revert a false undefined check to a strict equality check final RuntimeNode newRuntimeNode; final Request request = runtimeNode.getRequest(); if (Request.isUndefinedCheck(request)) { newRuntimeNode = runtimeNode.setRequest(request == Request.IS_UNDEFINED ? Request.EQ_STRICT : Request.NE_STRICT); } else { newRuntimeNode = runtimeNode; } new OptimisticOperation(newRuntimeNode, TypeBounds.UNBOUNDED) { @Override void loadStack() { for (final Expression arg : args) { loadExpression(arg, TypeBounds.OBJECT); } } @Override void consumeStack() { method.invokestatic( CompilerConstants.className(ScriptRuntime.class), newRuntimeNode.getRequest().toString(), new FunctionSignature( false, false, newRuntimeNode.getType(), args.size()).toString()); } }.emit(); method.convert(newRuntimeNode.getType()); }
private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) { if (env._parse_only || earlyError) { throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken()); } final ArrayList<Expression> args = new ArrayList<>(); args.add(lhs); if (rhs == null) { args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish())); } else { args.add(rhs); } args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString())); return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args); }
@Override public boolean enterDebuggerNode(final DebuggerNode debuggerNode) { final int line = debuggerNode.getLineNumber(); final long token = debuggerNode.getToken(); final int finish = debuggerNode.getFinish(); addStatement(new ExpressionStatement(line, token, finish, new RuntimeNode(token, finish, RuntimeNode.Request.DEBUGGER, new ArrayList<Expression>()))); return false; }
private void loadRuntimeNode(final RuntimeNode runtimeNode) { final List<Expression> args = new ArrayList<>(runtimeNode.getArgs()); if (nullCheck(runtimeNode, args)) { return; } else if(undefinedCheck(runtimeNode, args)) { return; } // Revert a false undefined check to a strict equality check final RuntimeNode newRuntimeNode; final Request request = runtimeNode.getRequest(); if (Request.isUndefinedCheck(request)) { newRuntimeNode = runtimeNode.setRequest(request == Request.IS_UNDEFINED ? Request.EQ_STRICT : Request.NE_STRICT); } else { newRuntimeNode = runtimeNode; } for (final Expression arg : args) { loadExpression(arg, TypeBounds.OBJECT); } method.invokestatic( CompilerConstants.className(ScriptRuntime.class), newRuntimeNode.getRequest().toString(), new FunctionSignature( false, false, newRuntimeNode.getType(), args.size()).toString()); method.convert(newRuntimeNode.getType()); }