/** 11.1.2 assignment with right-hand-side identifier reference. */ @Override public void visit(ReadVariableNode n, State state) { String varname = n.getVariableName(); Value v; if (varname.equals("this")) { // 11.1.1 read 'this' from the execution context v = state.readThis(); m.visitReadThis(n, v, state, InitialStateBuilder.GLOBAL); } else { // ordinary variable int result_base_reg = n.getResultBaseRegister(); Set<ObjectLabel> base_objs = null; if (c.isScanning() || result_base_reg != AbstractNode.NO_VALUE) base_objs = newSet(); v = state.readVariable(varname, base_objs); m.visitPropertyRead(n, base_objs, Value.makeTemporaryStr(varname), state, true); m.visitVariableAsRead(n, v, state); m.visitVariableOrProperty(varname, n.getSourceLocation(), v, state.getContext(), state); m.visitReadNonThisVariable(n, v); if (v.isMaybeAbsent()) Exceptions.throwReferenceError(state, c); if (v.isNotPresent() && !Options.get().isPropagateDeadFlow()) { state.setToNone(); return; } if (result_base_reg != AbstractNode.NO_VALUE) state.writeRegister(result_base_reg, Value.makeObject(base_objs)); // see 10.1.4 m.visitRead(n, v, state); m.visitReadVariable(n, v, state); // TODO: combine some of these m.visitXYZ methods? } if (v.isNotPresent() && !Options.get().isPropagateDeadFlow()) { state.setToNone(); return; } if (n.getResultRegister() != AbstractNode.NO_VALUE) state.writeRegister(n.getResultRegister(), v.restrictToNotAbsent()); }
/** 11.13 and 11.4.3 assignment with 'typeof' operator. */ @Override public void visit(TypeofNode n, State state) { Value v; if (n.isVariable()) { Value val = state.readVariable( n.getVariableName(), null); // TODO: should also count as a variable read in Monitoring? val = UnknownValueResolver.getRealValue(val, state); v = Operators.typeof(val, val.isMaybeAbsent()); m.visitVariableOrProperty( n.getVariableName(), n.getOperandSourceLocation(), val, state.getContext(), state); } else { Value val = state.readRegister(n.getArgRegister()); val = UnknownValueResolver.getRealValue(val, state); v = Operators.typeof(val, false); } if (v.isNotPresent() && !Options.get().isPropagateDeadFlow()) { state.setToNone(); return; } if (n.getResultRegister() != AbstractNode.NO_VALUE) state.writeRegister(n.getResultRegister(), v); }