Bug 387465 - Incorrect string evaluations with Rhino 1.7R4
diff --git a/tests/org.eclipse.wst.jsdt.debug.rhino.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.wst.jsdt.debug.rhino.tests/META-INF/MANIFEST.MF
index 9ca8f25..d8a227f 100644
--- a/tests/org.eclipse.wst.jsdt.debug.rhino.tests/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.wst.jsdt.debug.rhino.tests/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-SymbolicName: org.eclipse.wst.jsdt.debug.rhino.tests;singleton:=true
-Bundle-Version: 1.0.201.qualifier
+Bundle-Version: 1.0.300.qualifier
 Require-Bundle: org.eclipse.core.runtime,
  org.junit;bundle-version="3.8.2",
  org.eclipse.wst.jsdt.debug.core,
diff --git a/tests/org.eclipse.wst.jsdt.debug.rhino.tests/scripts/bug387465.js b/tests/org.eclipse.wst.jsdt.debug.rhino.tests/scripts/bug387465.js
new file mode 100644
index 0000000..0733599
--- /dev/null
+++ b/tests/org.eclipse.wst.jsdt.debug.rhino.tests/scripts/bug387465.js
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+/*
+ * Bug 387465 - Incorrect string evaluations with Rhino 1.7R4
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=387465
+ */
+var s = "a"; //line 1
+s += "a"; // debugger shows that s is undefined here
+s = "b";
\ No newline at end of file
diff --git a/tests/org.eclipse.wst.jsdt.debug.rhino.tests/src/org/eclipse/wst/jsdt/debug/rhino/tests/RequestLookupTest.java b/tests/org.eclipse.wst.jsdt.debug.rhino.tests/src/org/eclipse/wst/jsdt/debug/rhino/tests/RequestLookupTest.java
index b22f117..b3da363 100644
--- a/tests/org.eclipse.wst.jsdt.debug.rhino.tests/src/org/eclipse/wst/jsdt/debug/rhino/tests/RequestLookupTest.java
+++ b/tests/org.eclipse.wst.jsdt.debug.rhino.tests/src/org/eclipse/wst/jsdt/debug/rhino/tests/RequestLookupTest.java
@@ -12,6 +12,8 @@
 
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 import org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine;
 import org.eclipse.wst.jsdt.debug.internal.rhino.transport.EventPacket;
@@ -87,4 +89,74 @@
 		//script + breakpoint on line 6
 		evalScript(script, 2);
 	}
+	
+	/**
+	 * Tests that the lookup produces the correct result in Rhino 1.7R4
+	 * 
+	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=387465
+	 * @throws Exception
+	 */
+	public void testLookupBug387465() throws Exception {
+		eventHandler.addSubhandler(new SetBreakpointHandler(new int[] {17}));
+
+		final Object[] success = new Object[1];
+
+		Subhandler frameCheckHandler = new Subhandler() {
+			/* (non-Javadoc)
+			 * @see org.eclipse.wst.jsdt.debug.rhino.tests.TestEventHandler.Subhandler#testName()
+			 */
+			public String testName() {
+				return getName();
+			}
+			public boolean handleEvent(DebugSession debugSession, EventPacket event) {
+				if (event.getEvent().equals(JSONConstants.BREAK)) {
+					Number threadId = (Number) event.getBody().get(JSONConstants.THREAD_ID);
+					Number contextId = (Number) event.getBody().get(JSONConstants.CONTEXT_ID);
+					RhinoRequest request = new RhinoRequest(JSONConstants.FRAMES);
+					request.getArguments().put(JSONConstants.THREAD_ID, threadId);
+					try {
+						debugSession.send(request);
+						Response response = debugSession.receiveResponse(request.getSequence(), VirtualMachine.DEFAULT_TIMEOUT);
+						assertTrue(response.isSuccess());
+						Collection frames = (Collection) response.getBody().get(JSONConstants.FRAMES);
+						assertTrue("There should be at least one frame", frames.size() > 0); //$NON-NLS-1$
+						Number frameId = (Number) frames.iterator().next();
+						
+						response = doLookup(debugSession, threadId, contextId, frameId, new Integer(0));
+						assertTrue(response.isSuccess());
+						Map map = (Map) response.getBody().get(JSONConstants.LOOKUP);
+						assertNotNull("There must be a lookup response", map); //$NON-NLS-1$
+						List props = (List) map.get(JSONConstants.PROPERTIES);
+						assertNotNull("The successful lookup should have properties", props); //$NON-NLS-1$
+						map = findVar(props, "s"); //$NON-NLS-1$
+						assertNotNull("There must be an 's' variable", map); //$NON-NLS-1$
+						Number ref = (Number) map.get(JSONConstants.REF);
+						assertNotNull("There must be a 'ref' entry in the variable map", ref); //$NON-NLS-1$
+						response = doLookup(debugSession, threadId, contextId, frameId, ref);
+						assertTrue(response.isSuccess());
+						map = (Map) response.getBody().get(JSONConstants.LOOKUP);
+						assertNotNull("There should be a lookup entry trying to lookup 's' with ref: "+ref, map); //$NON-NLS-1$
+						assertEquals("The type should be string", JSONConstants.STRING,  map.get(JSONConstants.TYPE)); //$NON-NLS-1$
+						assertEquals("The value should be 'aa'", "aa", map.get(JSONConstants.VALUE)); //$NON-NLS-1$ //$NON-NLS-2$
+						success[0] = Boolean.TRUE;
+					} catch (DisconnectedException e) {
+						e.printStackTrace();
+					} catch (TimeoutException e) {
+						e.printStackTrace();
+					}
+					catch (Exception e) {
+						fail(e.getMessage());
+					}
+					return true;
+				}
+				return false;
+			}
+		};
+		eventHandler.addSubhandler(frameCheckHandler);
+
+		String script = Util.getTestSource(Util.SRC_SCRIPTS_CONTAINER, "bug387465.js"); //$NON-NLS-1$
+		assertNotNull("The test source for [bug387465.js] must exist", script); //$NON-NLS-1$
+		//script + breakpoint on line 17
+		evalScript(script, 2);
+	}
 }
diff --git a/tests/org.eclipse.wst.jsdt.debug.rhino.tests/src/org/eclipse/wst/jsdt/debug/rhino/tests/RequestTest.java b/tests/org.eclipse.wst.jsdt.debug.rhino.tests/src/org/eclipse/wst/jsdt/debug/rhino/tests/RequestTest.java
index 16efa77..a48e284 100644
--- a/tests/org.eclipse.wst.jsdt.debug.rhino.tests/src/org/eclipse/wst/jsdt/debug/rhino/tests/RequestTest.java
+++ b/tests/org.eclipse.wst.jsdt.debug.rhino.tests/src/org/eclipse/wst/jsdt/debug/rhino/tests/RequestTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2010 IBM Corporation and others.
+ * Copyright (c) 2009, 2012 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -446,4 +446,40 @@
 	synchronized void waitForEvents(EventPacket[] events) {
 		eventHandler.waitForEvents(events);
 	}
+	
+	/**
+	 * @param props
+	 * @param varname
+	 * @return the variable map or <code>null</code>
+	 */
+	protected Map findVar(List props, String varname) {
+		if(props != null && varname != null) {
+			Map prop = null;
+			for (Iterator i = props.iterator(); i.hasNext();) {
+				prop = (Map) i.next();
+				if(varname.equals(prop.get(JSONConstants.NAME))) {
+					return prop;
+				}
+			}
+		}
+		return null;
+	}
+	
+	/**
+	 * @param session
+	 * @param threadid
+	 * @param contextid
+	 * @param frameid
+	 * @param refid
+	 * @return the response, never <code>null</code>
+	 */
+	protected Response doLookup(DebugSession session, Number threadid, Number contextid, Number frameid, Number refid) throws Exception {
+		RhinoRequest request = new RhinoRequest(JSONConstants.LOOKUP);
+		request.getArguments().put(JSONConstants.THREAD_ID, threadid);
+		request.getArguments().put(JSONConstants.CONTEXT_ID, contextid);
+		request.getArguments().put(JSONConstants.FRAME_ID, frameid);
+		request.getArguments().put(JSONConstants.REF, refid);
+		debugSession.send(request);
+		return debugSession.receiveResponse(request.getSequence(), VirtualMachine.DEFAULT_TIMEOUT);
+	}
 }