Can these tests be placed in compact profile jdk8
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 09 Aug 2014 12:15:18 +0200
branchjdk8
changeset 1648905b2a470def
parent 1647 5fb6acaa51b8
child 1650 6799184bf769
Can these tests be placed in compact profile
rt/emul/compact/src/test/java/org/apidesign/vm4brwsr/dynamic/InvokeDynamic.java
rt/emul/compact/src/test/java/org/apidesign/vm4brwsr/dynamic/InvokeDynamicTest.java
rt/emul/compact/src/test/java/org/apidesign/vm4brwsr/dynamic/TestVM.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/vm4brwsr/dynamic/InvokeDynamic.java	Sat Aug 09 12:15:18 2014 +0200
     1.3 @@ -0,0 +1,46 @@
     1.4 +/**
     1.5 + * Back 2 Browser Bytecode Translator
     1.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     1.7 + *
     1.8 + * This program is free software: you can redistribute it and/or modify
     1.9 + * it under the terms of the GNU General Public License as published by
    1.10 + * the Free Software Foundation, version 2 of the License.
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License
    1.18 + * along with this program. Look for COPYING file in the top folder.
    1.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    1.20 + */
    1.21 +package org.apidesign.vm4brwsr.dynamic;
    1.22 +
    1.23 +import java.lang.invoke.CallSite;
    1.24 +import java.lang.invoke.ConstantCallSite;
    1.25 +import java.lang.invoke.MethodHandles;
    1.26 +import java.lang.invoke.MethodType;
    1.27 +
    1.28 +public class InvokeDynamic {
    1.29 +
    1.30 +    public static String dynamicSay() {
    1.31 +        return TEST_dynamic_boot1(new InvokeDynamic());
    1.32 +    }
    1.33 +
    1.34 +    private static String TEST_dynamic_boot1(InvokeDynamic instance) {
    1.35 +        throw new IllegalStateException("Can't touch this");
    1.36 +    }
    1.37 +
    1.38 +    public static CallSite boot1(MethodHandles.Lookup lookup, String name, MethodType type) {
    1.39 +        try {
    1.40 +            return new ConstantCallSite(lookup.findVirtual(InvokeDynamic.class, "instance_sayHello", MethodType.methodType(String.class)));
    1.41 +        } catch (NoSuchMethodException | IllegalAccessException e) {
    1.42 +            throw new IllegalStateException(e);
    1.43 +        }
    1.44 +    }
    1.45 +
    1.46 +    public String instance_sayHello() {
    1.47 +        return "Hello from Dynamic!";
    1.48 +    }
    1.49 +}
    1.50 \ No newline at end of file
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/vm4brwsr/dynamic/InvokeDynamicTest.java	Sat Aug 09 12:15:18 2014 +0200
     2.3 @@ -0,0 +1,175 @@
     2.4 +/**
     2.5 + * Back 2 Browser Bytecode Translator
     2.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     2.7 + *
     2.8 + * This program is free software: you can redistribute it and/or modify
     2.9 + * it under the terms of the GNU General Public License as published by
    2.10 + * the Free Software Foundation, version 2 of the License.
    2.11 + *
    2.12 + * This program is distributed in the hope that it will be useful,
    2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.15 + * GNU General Public License for more details.
    2.16 + *
    2.17 + * You should have received a copy of the GNU General Public License
    2.18 + * along with this program. Look for COPYING file in the top folder.
    2.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    2.20 + */
    2.21 +package org.apidesign.vm4brwsr.dynamic;
    2.22 +
    2.23 +import java.io.ByteArrayInputStream;
    2.24 +import java.io.IOException;
    2.25 +import java.io.InputStream;
    2.26 +import java.lang.invoke.CallSite;
    2.27 +import java.lang.invoke.MethodHandles;
    2.28 +import java.lang.invoke.MethodType;
    2.29 +import java.lang.reflect.Method;
    2.30 +import java.net.URL;
    2.31 +import java.util.Enumeration;
    2.32 +import org.apidesign.vm4brwsr.Bck2Brwsr;
    2.33 +import org.objectweb.asm.ClassReader;
    2.34 +import org.objectweb.asm.ClassVisitor;
    2.35 +import org.objectweb.asm.ClassWriter;
    2.36 +import org.objectweb.asm.Handle;
    2.37 +import org.objectweb.asm.MethodVisitor;
    2.38 +import org.objectweb.asm.Opcodes;
    2.39 +import static org.objectweb.asm.Opcodes.ASM4;
    2.40 +import static org.objectweb.asm.Opcodes.INVOKESTATIC;
    2.41 +import static org.testng.Assert.*;
    2.42 +import org.testng.annotations.AfterClass;
    2.43 +import org.testng.annotations.BeforeClass;
    2.44 +import org.testng.annotations.Test;
    2.45 +
    2.46 +/**
    2.47 + *
    2.48 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    2.49 + */
    2.50 +public class InvokeDynamicTest {
    2.51 +    private static Class<?> invokeDynamicClass;
    2.52 +    private static byte[] invokeDynamicBytes;
    2.53 +    private static TestVM code;
    2.54 +    
    2.55 +    @Test public void simpleDynamicInJava() throws Exception {
    2.56 +        Method m = invokeDynamicClass.getMethod("dynamicSay");
    2.57 +        Object ret = m.invoke(m);
    2.58 +        assertEquals(ret, "Hello from Dynamic!");
    2.59 +    }
    2.60 +    
    2.61 +    @Test public void simpleDynamicInJS() throws Exception {
    2.62 +        code.assertExec(
    2.63 +            "Invoke dynamic can return a value", InvokeDynamic.class,
    2.64 +            "dynamic__Ljava_lang_String_2",
    2.65 +            "Hello from Dynamic!"
    2.66 +        );
    2.67 +    }
    2.68 +    
    2.69 +
    2.70 +    @AfterClass
    2.71 +    public static void releaseTheCode() {
    2.72 +        code = null;
    2.73 +    }
    2.74 +
    2.75 +    //
    2.76 +    // the following code is inspired by 
    2.77 +    // https://code.google.com/p/indy-maven-plugin/
    2.78 +    // which I don't want to use, as it is not in a public repository
    2.79 +    //
    2.80 +    @BeforeClass 
    2.81 +    public static void prepareClass() throws Exception {
    2.82 +        InputStream is = InvokeDynamic.class.getResourceAsStream("InvokeDynamic.class");
    2.83 +        assertNotNull(is, "Class found");
    2.84 +        
    2.85 +        ClassReader reader = new ClassReader(is);
    2.86 +        ClassWriter writer = new ClassWriter(reader, 0);
    2.87 +
    2.88 +        reader.accept(
    2.89 +                new ClassVisitor(ASM4, writer) {
    2.90 +                    @Override
    2.91 +                    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions
    2.92 +                    ) {
    2.93 +                        MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
    2.94 +                        return new InvokeDynamicProcessor(mv);
    2.95 +                    }
    2.96 +                },
    2.97 +                0);
    2.98 +        is.close();
    2.99 +        invokeDynamicBytes = writer.toByteArray();
   2.100 +        ClassLoader l = new ClassLoader() {
   2.101 +            @Override
   2.102 +            public Class<?> loadClass(String name) throws ClassNotFoundException {
   2.103 +                if (name.equals(InvokeDynamic.class.getName())) {
   2.104 +                    return defineClass(name, invokeDynamicBytes, 0, invokeDynamicBytes.length);
   2.105 +                }
   2.106 +                return super.loadClass(name);
   2.107 +            }
   2.108 +        };
   2.109 +        invokeDynamicClass = l.loadClass(InvokeDynamic.class.getName());
   2.110 +        
   2.111 +        code = TestVM.compileClass(
   2.112 +            null, null, new EmulationResourcesWithException(),
   2.113 +            InvokeDynamic.class.getName().replace('.', '/')
   2.114 +        );
   2.115 +    }
   2.116 +    
   2.117 +    
   2.118 +    private static class InvokeDynamicProcessor extends MethodVisitor {
   2.119 +        InvokeDynamicProcessor(MethodVisitor mv) {
   2.120 +            super(ASM4, mv);
   2.121 +        }
   2.122 +
   2.123 +        @Override
   2.124 +        public void visitMethodInsn(int opcode, String owner, String name, String desc) {
   2.125 +            if (opcode == INVOKESTATIC) {
   2.126 +                if (name.startsWith("TEST_dynamic_")) {
   2.127 +                    final String shortName = name.substring(13);
   2.128 +                    Handle mh = new Handle(
   2.129 +                        Opcodes.H_INVOKESTATIC, owner, shortName,
   2.130 +                        MethodType.methodType(
   2.131 +                            CallSite.class,
   2.132 +                            MethodHandles.Lookup.class,
   2.133 +                            String.class, 
   2.134 +                            MethodType.class
   2.135 +                        ).toMethodDescriptorString()
   2.136 +                    );
   2.137 +                    super.visitInvokeDynamicInsn(shortName, desc, mh);
   2.138 +                    return;
   2.139 +                }
   2.140 +            }
   2.141 +            super.visitMethodInsn(opcode, owner, name, desc);
   2.142 +        }
   2.143 +    }
   2.144 +    
   2.145 +    private static class EmulationResourcesWithException implements Bck2Brwsr.Resources {
   2.146 +        @Override
   2.147 +        public InputStream get(String name) throws IOException {
   2.148 +            if ("org/apidesign/vm4brwsr/InvokeDynamic.class".equals(name)) {
   2.149 +                return new ByteArrayInputStream(invokeDynamicBytes);
   2.150 +            }
   2.151 +            if ("java/net/URI.class".equals(name)) {
   2.152 +                // skip
   2.153 +                return null;
   2.154 +            }
   2.155 +            if ("java/net/URLConnection.class".equals(name)) {
   2.156 +                // skip
   2.157 +                return null;
   2.158 +            }
   2.159 +            if ("java/lang/System.class".equals(name)) {
   2.160 +                // skip
   2.161 +                return null;
   2.162 +            }
   2.163 +            Enumeration<URL> en = InvokeDynamicTest.class.getClassLoader().getResources(name);
   2.164 +            URL u = null;
   2.165 +            while (en.hasMoreElements()) {
   2.166 +                u = en.nextElement();
   2.167 +            }
   2.168 +            if (u == null) {
   2.169 +                throw new IOException("Can't find " + name);
   2.170 +            }
   2.171 +            if (u.toExternalForm().contains("rt.jar!")) {
   2.172 +                throw new IOException("No emulation for " + u);
   2.173 +            }
   2.174 +            return u.openStream();
   2.175 +        }
   2.176 +    }
   2.177 +    
   2.178 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/vm4brwsr/dynamic/TestVM.java	Sat Aug 09 12:15:18 2014 +0200
     3.3 @@ -0,0 +1,297 @@
     3.4 +/**
     3.5 + * Back 2 Browser Bytecode Translator
     3.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.7 + *
     3.8 + * This program is free software: you can redistribute it and/or modify
     3.9 + * it under the terms of the GNU General Public License as published by
    3.10 + * the Free Software Foundation, version 2 of the License.
    3.11 + *
    3.12 + * This program is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU General Public License for more details.
    3.16 + *
    3.17 + * You should have received a copy of the GNU General Public License
    3.18 + * along with this program. Look for COPYING file in the top folder.
    3.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    3.20 + */
    3.21 +package org.apidesign.vm4brwsr.dynamic;
    3.22 +
    3.23 +import java.io.ByteArrayInputStream;
    3.24 +import java.io.File;
    3.25 +import java.io.FileWriter;
    3.26 +import java.io.IOException;
    3.27 +import java.io.InputStream;
    3.28 +import java.net.URL;
    3.29 +import java.util.ArrayList;
    3.30 +import java.util.Arrays;
    3.31 +import java.util.Enumeration;
    3.32 +import java.util.HashSet;
    3.33 +import java.util.List;
    3.34 +import java.util.Set;
    3.35 +import javax.script.Invocable;
    3.36 +import javax.script.ScriptContext;
    3.37 +import javax.script.ScriptEngine;
    3.38 +import javax.script.ScriptEngineManager;
    3.39 +import javax.script.ScriptException;
    3.40 +import org.apidesign.vm4brwsr.Bck2Brwsr;
    3.41 +import org.apidesign.vm4brwsr.ObfuscationLevel;
    3.42 +import static org.testng.Assert.*;
    3.43 +
    3.44 +public final class TestVM {
    3.45 +    private final Invocable code;
    3.46 +    private final CharSequence codeSeq;
    3.47 +    private final Object bck2brwsr;
    3.48 +    
    3.49 +    
    3.50 +    private TestVM(Invocable code, CharSequence codeSeq) throws ScriptException, NoSuchMethodException {
    3.51 +        this.code = code;
    3.52 +        this.codeSeq = codeSeq;
    3.53 +        this.bck2brwsr = ((ScriptEngine)code).eval("bck2brwsr(function(n) { return loader.get(n); })");
    3.54 +        ((ScriptEngine)code).getContext().setAttribute("loader", this, ScriptContext.ENGINE_SCOPE);
    3.55 +    }
    3.56 +    
    3.57 +    public Object execCode(
    3.58 +        String msg, Class<?> clazz, String method, 
    3.59 +        Object expRes, Object... args
    3.60 +    ) throws Exception {
    3.61 +        Object ret = null;
    3.62 +        try {
    3.63 +            ret = code.invokeMethod(bck2brwsr, "loadClass", clazz.getName());
    3.64 +            List<Object> ma = new ArrayList<>();
    3.65 +            ma.add(method);
    3.66 +            ma.addAll(Arrays.asList(args));
    3.67 +            ret = code.invokeMethod(ret, "invoke", ma.toArray());
    3.68 +        } catch (ScriptException ex) {
    3.69 +            fail("Execution failed in " + dumpJS(codeSeq) + ": " + ex.getMessage(), ex);
    3.70 +        } catch (NoSuchMethodException ex) {
    3.71 +            fail("Cannot find method in " + dumpJS(codeSeq), ex);
    3.72 +        }
    3.73 +        if (ret == null && expRes == null) {
    3.74 +            return null;
    3.75 +        }
    3.76 +        if (expRes != null && expRes.equals(ret)) {
    3.77 +            return null;
    3.78 +        }
    3.79 +        if (expRes instanceof Number) {
    3.80 +            // in case of Long it is necessary convert it to number
    3.81 +            // since the Long is represented by two numbers in JavaScript
    3.82 +            try {
    3.83 +                final Object toFP = ((ScriptEngine)code).eval("Number.prototype.toFP");
    3.84 +                if (ret instanceof Long) {
    3.85 +                    ret = code.invokeMethod(toFP, "call", ret);
    3.86 +                }
    3.87 +                ret = code.invokeFunction("Number", ret);
    3.88 +            } catch (ScriptException ex) {
    3.89 +                fail("Conversion to number failed in " + dumpJS(codeSeq) + ": " + ex.getMessage(), ex);
    3.90 +            } catch (NoSuchMethodException ex) {
    3.91 +                fail("Cannot find global Number(x) function in " + dumpJS(codeSeq) + ": " + ex.getMessage(), ex);
    3.92 +            }
    3.93 +        }
    3.94 +        return ret;
    3.95 +    }
    3.96 +    
    3.97 +    void assertExec(
    3.98 +        String msg, Class clazz, String method, Object expRes, Object... args
    3.99 +    ) throws Exception {
   3.100 +        Object ret = execCode(msg, clazz, method, expRes, args);
   3.101 +        if (ret == null) {
   3.102 +            return;
   3.103 +        }
   3.104 +        if (expRes instanceof Integer && ret instanceof Double) {
   3.105 +            expRes = ((Integer)expRes).doubleValue();
   3.106 +        }
   3.107 +        if (expRes != null && expRes.equals(ret)) {
   3.108 +            return;
   3.109 +        }
   3.110 +        assertEquals(ret, expRes, msg + "was: " + ret + "\n" + dumpJS(codeSeq));
   3.111 +    }    
   3.112 +
   3.113 +    static TestVM compileClass(String... names) throws ScriptException, IOException {
   3.114 +        return compileClass(null, names);
   3.115 +    }
   3.116 +    
   3.117 +    static TestVM compileClass(StringBuilder sb, String... names) throws ScriptException, IOException {
   3.118 +        return compileClass(sb, null, names);
   3.119 +    }
   3.120 +
   3.121 +    static TestVM compileClass(StringBuilder sb, ScriptEngine[] eng, String... names) throws ScriptException, IOException {
   3.122 +        return compileClass(sb, eng, new EmulationResources(), names);
   3.123 +    }
   3.124 +    static TestVM compileClass(
   3.125 +        StringBuilder sb, 
   3.126 +        ScriptEngine[] eng, 
   3.127 +        Bck2Brwsr.Resources resources, 
   3.128 +        String... names
   3.129 +    ) throws ScriptException, IOException {
   3.130 +        if (sb == null) {
   3.131 +            sb = new StringBuilder();
   3.132 +        }
   3.133 +        Bck2Brwsr.generate(sb, resources, names);
   3.134 +        ScriptEngineManager sem = new ScriptEngineManager();
   3.135 +        ScriptEngine js = sem.getEngineByExtension("js");
   3.136 +        if (eng != null) {
   3.137 +            eng[0] = js;
   3.138 +        }
   3.139 +        try {
   3.140 +            Object res = js.eval(sb.toString());
   3.141 +            assertTrue(js instanceof Invocable, "It is invocable object: " + res);
   3.142 +            return new TestVM((Invocable) js, sb);
   3.143 +        } catch (Exception ex) {
   3.144 +            if (sb.length() > 2000) {
   3.145 +                sb = dumpJS(sb);
   3.146 +            }
   3.147 +            fail("Could not evaluate:" + ex.getClass() + ":" + ex.getMessage() + "\n" + sb, ex);
   3.148 +            return null;
   3.149 +        }
   3.150 +    }
   3.151 +    
   3.152 +    static TestVM compileClassAsExtension(
   3.153 +        StringBuilder sb, ScriptEngine[] eng, 
   3.154 +        String name, final String resourceName, final String resourceContent
   3.155 +    ) throws ScriptException, IOException {
   3.156 +        return compileClassesAsExtension(sb, eng, resourceName, resourceContent, name);
   3.157 +    }
   3.158 +    static TestVM compileClassesAsExtension(
   3.159 +        StringBuilder sb, ScriptEngine[] eng, 
   3.160 +        final String resourceName, final String resourceContent, String... names
   3.161 +    ) throws ScriptException, IOException {
   3.162 +        if (sb == null) {
   3.163 +            sb = new StringBuilder();
   3.164 +        }
   3.165 +        if (eng[0] == null) {
   3.166 +            ScriptEngineManager sem = new ScriptEngineManager();
   3.167 +            ScriptEngine js = sem.getEngineByExtension("js");
   3.168 +            eng[0] = js;
   3.169 +            Bck2Brwsr.generate(sb, new EmulationResources());
   3.170 +        }
   3.171 +        Set<String> exp = new HashSet<String>();
   3.172 +        for (String n : names) {
   3.173 +            int last = n.lastIndexOf('/');
   3.174 +            exp.add(n.substring(0, last + 1));
   3.175 +        }
   3.176 +        Bck2Brwsr b2b = Bck2Brwsr.newCompiler().
   3.177 +            resources(new EmulationResources() {
   3.178 +                @Override
   3.179 +                public InputStream get(String name) throws IOException {
   3.180 +                    if (name.equals(resourceName)) {
   3.181 +                        return new ByteArrayInputStream(resourceContent.getBytes("UTF-8"));
   3.182 +                    }
   3.183 +                    return super.get(name);
   3.184 +                }
   3.185 +            }).
   3.186 +            addClasses(names).
   3.187 +            addResources("org/apidesign/vm4brwsr/obj.js").
   3.188 +            addExported(exp.toArray(new String[0])).
   3.189 +            obfuscation(ObfuscationLevel.FULL).
   3.190 +            library();
   3.191 +        if (resourceName != null) {
   3.192 +            b2b = b2b.addResources(resourceName);
   3.193 +        }
   3.194 +        b2b.generate(sb);
   3.195 +        try {
   3.196 +            defineAtoB(eng[0]);
   3.197 +            Object res = eng[0].eval(sb.toString());
   3.198 +            assertTrue(eng[0] instanceof Invocable, "It is invocable object: " + res);
   3.199 +            return new TestVM((Invocable) eng[0], sb);
   3.200 +        } catch (Exception ex) {
   3.201 +            if (sb.length() > 2000) {
   3.202 +                sb = dumpJS(sb);
   3.203 +            }
   3.204 +            fail("Could not evaluate:" + ex.getClass() + ":" + ex.getMessage() + "\n" + sb, ex);
   3.205 +            return null;
   3.206 +        }
   3.207 +    }
   3.208 +    
   3.209 +    static TestVM compileClassAndResources(StringBuilder sb, ScriptEngine[] eng, String name, String... resources) throws ScriptException, IOException {
   3.210 +        if (sb == null) {
   3.211 +            sb = new StringBuilder();
   3.212 +        }
   3.213 +        Bck2Brwsr b2b = Bck2Brwsr.newCompiler().
   3.214 +            resources(new EmulationResources()).
   3.215 +            addRootClasses(name).
   3.216 +            addResources(resources);
   3.217 +        b2b.generate(sb);
   3.218 +        ScriptEngineManager sem = new ScriptEngineManager();
   3.219 +        ScriptEngine js = sem.getEngineByExtension("js");
   3.220 +        if (eng != null) {
   3.221 +            eng[0] = js;
   3.222 +        }
   3.223 +        try {
   3.224 +            defineAtoB(js);
   3.225 +            
   3.226 +            Object res = js.eval(sb.toString());
   3.227 +            assertTrue(js instanceof Invocable, "It is invocable object: " + res);
   3.228 +            return new TestVM((Invocable) js, sb);
   3.229 +        } catch (Exception ex) {
   3.230 +            if (sb.length() > 2000) {
   3.231 +                sb = dumpJS(sb);
   3.232 +            }
   3.233 +            fail("Could not evaluate:" + ex.getClass() + ":" + ex.getMessage() + "\n" + sb, ex);
   3.234 +            return null;
   3.235 +        }
   3.236 +    }
   3.237 +
   3.238 +    private static void defineAtoB(ScriptEngine js) throws ScriptException {
   3.239 +        js.eval("atob = function(s) { return new String(org.apidesign.vm4brwsr.ResourcesTest.parseBase64Binary(s)); }");
   3.240 +    }
   3.241 +
   3.242 +    Object invokeMethod(Object obj, String method, Object... params) throws ScriptException, NoSuchMethodException {
   3.243 +        return code.invokeMethod(obj, method, params);
   3.244 +    }
   3.245 +
   3.246 +    Object invokeFunction(String methodName, Object... args) throws ScriptException, NoSuchMethodException {
   3.247 +        return code.invokeFunction(methodName, args);
   3.248 +    }
   3.249 +
   3.250 +    static StringBuilder dumpJS(CharSequence sb) throws IOException {
   3.251 +        File f = File.createTempFile("execution", ".js");
   3.252 +        FileWriter w = new FileWriter(f);
   3.253 +        w.append(sb);
   3.254 +        w.close();
   3.255 +        return new StringBuilder(f.getPath());
   3.256 +    }
   3.257 +
   3.258 +    @Override
   3.259 +    public String toString() {
   3.260 +        try {
   3.261 +            return dumpJS(codeSeq).toString();
   3.262 +        } catch (IOException ex) {
   3.263 +            return ex.toString();
   3.264 +        }
   3.265 +    }
   3.266 +
   3.267 +    final CharSequence codeSeq() {
   3.268 +        return codeSeq;
   3.269 +    }
   3.270 +    
   3.271 +    private static class EmulationResources implements Bck2Brwsr.Resources {
   3.272 +        @Override
   3.273 +        public InputStream get(String name) throws IOException {
   3.274 +            if ("java/net/URI.class".equals(name)) {
   3.275 +                // skip
   3.276 +                return null;
   3.277 +            }
   3.278 +            if ("java/net/URLConnection.class".equals(name)) {
   3.279 +                // skip
   3.280 +                return null;
   3.281 +            }
   3.282 +            if ("java/lang/System.class".equals(name)) {
   3.283 +                // skip
   3.284 +                return null;
   3.285 +            }
   3.286 +            Enumeration<URL> en = TestVM.class.getClassLoader().getResources(name);
   3.287 +            URL u = null;
   3.288 +            while (en.hasMoreElements()) {
   3.289 +                u = en.nextElement();
   3.290 +            }
   3.291 +            if (u == null) {
   3.292 +                throw new IOException("Can't find " + name);
   3.293 +            }
   3.294 +            if (u.toExternalForm().contains("rt.jar!")) {
   3.295 +                throw new IOException("No emulation for " + u);
   3.296 +            }
   3.297 +            return u.openStream();
   3.298 +        }
   3.299 +    }
   3.300 +}