@Override public CompileResult call() throws Exception { // Create the options anew. Passing in the parent options, even cloning it, is not thread safe. CompileResult result = doCompileContent(content, getCompilerOptions(jsUri), buildExterns(externs)); synchronized (compiling) { // Other threads should pick this up in the cache now. cache.addElement(cacheKey, result); compiling.remove(cacheKey); } return result; } });
@Inject(optional = true) public void setThreadPoolSize( @Named("shindig.closure.compile.threadPoolSize") Integer threadPoolSize) { if (threadPoolSize != null && threadPoolSize != this.threadPoolSize) { ExecutorService compilerPool = this.compilerPool; this.threadPoolSize = threadPoolSize; this.compilerPool = createThreadPool(); compilerPool.shutdown(); } }
@VisibleForTesting protected CompilerOptions getCompilerOptions(JsUri uri) { CompilerOptions options = defaultCompilerOptions(); return options; }
public JsResponse compile(JsUri jsUri, Iterable<JsContent> content, String externs) { JsResponseBuilder builder = new JsResponseBuilder(); CompilerOptions options = getCompilerOptions(jsUri); StringBuilder compiled = new StringBuilder(); StringBuilder exports = new StringBuilder(); String cacheKey = makeCacheKey(defaultCompiled.toJsString(), externs, jsUri, options); future = getCompileFuture(cacheKey, code, jsUri, externs); compiling.put(cacheKey, future); return returnErrorResult(builder, HttpResponse.SC_NOT_FOUND, ((CompilerException)cause).getErrors()); } else { return returnErrorResult(builder, HttpResponse.SC_NOT_FOUND, Lists.newArrayList(e.getMessage()));
public Iterable<JsContent> getJsContent(JsUri jsUri, FeatureBundle bundle) { jsUri = new JsUri(jsUri) { @Override public boolean isDebug() { // Force debug JS in the raw JS content retrieved. return true; } }; List<JsContent> builder = Lists.newLinkedList(defaultCompiler.getJsContent(jsUri, bundle)); CompilerOptions options = getCompilerOptions(jsUri); if (options.isExternExportsEnabled()) { List<String> exports = Lists.newArrayList(bundle.getApis(ApiDirective.Type.JS, true)); Collections.sort(exports); String prevExport = null; for (String export : exports) { if (!export.equals(prevExport)) { builder.add(JsContent.fromText( "goog.exportSymbol('" + StringEscapeUtils.escapeEcmaScript(export) + "', " + export + ");\n", "[export-symbol]")); prevExport = export; } } } return builder; }
@Ignore("This class was not being run and when I ran it this test did not pass. Not familiar enough to enable it.") @Test public void testCompileErrorOpt() throws Exception { jsUriMock = mockJsUri(false); // opt realCompMock = mockRealJsCompiler(JS_ERROR, realResultMock, ACTUAL_COMPILER_OUTPUT); realOptionsMock = mockRealJsCompilerOptions(true); // force compiler to run compiler = newClosureJsCompiler(realCompMock, realOptionsMock, compilerMock, cacheMock); JsResponse actual = compiler.compile(jsUriMock, EXPORT_COMPILER_CONTENTS, EXTERN); assertTrue(actual.getErrors().get(0).contains(ERROR_NAME)); assertEquals(1, actual.getErrors().size()); }
@Ignore("This class was not being run and when I ran it this test did not pass. Not familiar enough to enable it.") @Test public void testGetJsContentWithGoogSymbolExports() throws Exception { realOptionsMock = mockRealJsCompilerOptions(true); // with compiler = newClosureJsCompiler(null, realOptionsMock, compilerMock, cacheMock); FeatureBundle bundle = mockBundle(EXPORTS); Iterable<JsContent> actual = compiler.getJsContent(mockJsUri(false), bundle); assertEquals(EXPORT_COMPILER_STRING + "goog.exportSymbol('bar', bar);\n" + "goog.exportSymbol('foo', foo);\n", getContent(actual)); }
protected CompileResult doCompileContent(JsContent content, CompilerOptions options, List<SourceFile> externs) throws CompilerException { Compiler compiler = new Compiler(getErrorManager()); // We shouldn't reuse compilers // disable JS Closure Compiler internal thread compiler.disableThreads(); SourceFile source = SourceFile.fromCode(content.getSource(), content.get()); Result result = compiler.compile(externs, Lists.newArrayList(source), options); if (result.errors.length > 0) { throw new CompilerException(result.errors); } return new CompileResult(compiler, result); }
private ClosureJsCompiler newClosureJsCompiler(final Compiler realComp, CompilerOptions realOptions, DefaultJsCompiler defaultComp, CacheProvider cache) throws InterruptedException, ExecutionException { Future<CompileResult> mockFuture = EasyMock.createMock(Future.class); expect(mockFuture.get()).andReturn(new CompileResult(realComp, realResultMock)).anyTimes(); replay(mockFuture); expect(executorServiceMock.submit(isA(Callable.class))).andReturn(mockFuture); replay(executorServiceMock); ClosureJsCompiler compiler = createMockBuilder(ClosureJsCompiler.class) .addMockedMethods("getCompilerOptions") .withConstructor(defaultComp, cache, "simple", executorServiceMock) .createMock(); expect(compiler.getCompilerOptions(isA(JsUri.class))).andReturn(realOptionsMock).anyTimes(); replay(compiler); return compiler; }
@Ignore("This class was not being run and when I ran it this test did not pass. Not familiar enough to enable it.") @Test public void testCompileErrorOpt() throws Exception { jsUriMock = mockJsUri(false); // opt realCompMock = mockRealJsCompiler(JS_ERROR, realResultMock, ACTUAL_COMPILER_OUTPUT); realOptionsMock = mockRealJsCompilerOptions(true); // force compiler to run compiler = newClosureJsCompiler(realCompMock, realOptionsMock, compilerMock, cacheMock); JsResponse actual = compiler.compile(jsUriMock, EXPORT_COMPILER_CONTENTS, EXTERN); assertTrue(actual.getErrors().get(0).contains(ERROR_NAME)); assertEquals(1, actual.getErrors().size()); }
@Ignore("This class was not being run and when I ran it this test did not pass. Not familiar enough to enable it.") @Test public void testGetJsContentWithoutGoogSymbolExports() throws Exception { realOptionsMock = mockRealJsCompilerOptions(false); // without compiler = newClosureJsCompiler(null, realOptionsMock, compilerMock, cacheMock); FeatureBundle bundle = mockBundle(EXPORTS); Iterable<JsContent> actual = compiler.getJsContent(mockJsUri(false), bundle); assertEquals(EXPORT_COMPILER_STRING, getContent(actual)); }
private ClosureJsCompiler newClosureJsCompiler(final Compiler realComp, CompilerOptions realOptions, DefaultJsCompiler defaultComp, CacheProvider cache) throws InterruptedException, ExecutionException { Future<CompileResult> mockFuture = EasyMock.createMock(Future.class); expect(mockFuture.get()).andReturn(new CompileResult(realComp, realResultMock)).anyTimes(); replay(mockFuture); expect(executorServiceMock.submit(isA(Callable.class))).andReturn(mockFuture); replay(executorServiceMock); ClosureJsCompiler compiler = createMockBuilder(ClosureJsCompiler.class) .addMockedMethods("getCompilerOptions") .withConstructor(defaultComp, cache, "simple", executorServiceMock) .createMock(); expect(compiler.getCompilerOptions(isA(JsUri.class))).andReturn(realOptionsMock).anyTimes(); replay(compiler); return compiler; }
@Ignore("This class was not being run and when I ran it this test did not pass. Not familiar enough to enable it.") @Test public void testCompileErrorDeb() throws Exception { jsUriMock = mockJsUri(true); // debug realCompMock = mockRealJsCompiler(JS_ERROR, realResultMock, ACTUAL_COMPILER_OUTPUT); realOptionsMock = mockRealJsCompilerOptions(true); // force compiler to run realResultMock = mockRealJsResult(); compiler = newClosureJsCompiler(realCompMock, realOptionsMock, compilerMock, cacheMock); JsResponse actual = compiler.compile(jsUriMock, EXPORT_COMPILER_CONTENTS, EXTERN); assertTrue(actual.getErrors().get(0).contains(ERROR_NAME)); assertEquals(1, actual.getErrors().size()); }
@Ignore("This class was not being run and when I ran it this test did not pass. Not familiar enough to enable it.") @Test public void testGetJsContentWithoutGoogSymbolExports() throws Exception { realOptionsMock = mockRealJsCompilerOptions(false); // without compiler = newClosureJsCompiler(null, realOptionsMock, compilerMock, cacheMock); FeatureBundle bundle = mockBundle(EXPORTS); Iterable<JsContent> actual = compiler.getJsContent(mockJsUri(false), bundle); assertEquals(EXPORT_COMPILER_STRING, getContent(actual)); }
public ClosureJsCompiler(DefaultJsCompiler defaultCompiler, CacheProvider cacheProvider, String level, ExecutorService executorService) { this.cache = cacheProvider.createCache(CACHE_NAME); this.defaultCompiler = defaultCompiler; List<SourceFile> externs = null; try { externs = Collections.unmodifiableList(CommandLineRunner.getDefaultExterns()); } catch(IOException e) { if (LOG.isLoggable(Level.WARNING)) { LOG.log(Level.WARNING, "Unable to load default closure externs: " + e.getMessage(), e); } } defaultExterns = externs; compileLevel = level.toLowerCase().trim(); if(executorService != null) { compilerPool = executorService; }else { compilerPool = createThreadPool(); } Map<String, Future<CompileResult>> map = Maps.newHashMap(); compiling = new ConcurrentHashMap<String, Future<CompileResult>>(map); }
private ClosureJsCompiler newProfilingClosureJsCompiler(CompilerOptions realOptions, DefaultJsCompiler defaultComp, CacheProvider cache) { ClosureJsCompiler compiler = createMockBuilder(ClosureJsCompiler.class) .addMockedMethods("getCompilerOptions") .withConstructor(defaultComp, cache, "simple").createMock(); expect(compiler.getCompilerOptions(isA(JsUri.class))).andReturn(realOptions).anyTimes(); replay(compiler); return compiler; }
@Ignore("This class was not being run and when I ran it this test did not pass. Not familiar enough to enable it.") @Test public void testCompileErrorDeb() throws Exception { jsUriMock = mockJsUri(true); // debug realCompMock = mockRealJsCompiler(JS_ERROR, realResultMock, ACTUAL_COMPILER_OUTPUT); realOptionsMock = mockRealJsCompilerOptions(true); // force compiler to run realResultMock = mockRealJsResult(); compiler = newClosureJsCompiler(realCompMock, realOptionsMock, compilerMock, cacheMock); JsResponse actual = compiler.compile(jsUriMock, EXPORT_COMPILER_CONTENTS, EXTERN); assertTrue(actual.getErrors().get(0).contains(ERROR_NAME)); assertEquals(1, actual.getErrors().size()); }
@Ignore("This class was not being run and when I ran it this test did not pass. Not familiar enough to enable it.") @Test public void testGetJsContentWithGoogSymbolExports() throws Exception { realOptionsMock = mockRealJsCompilerOptions(true); // with compiler = newClosureJsCompiler(null, realOptionsMock, compilerMock, cacheMock); FeatureBundle bundle = mockBundle(EXPORTS); Iterable<JsContent> actual = compiler.getJsContent(mockJsUri(false), bundle); assertEquals(EXPORT_COMPILER_STRING + "goog.exportSymbol('bar', bar);\n" + "goog.exportSymbol('foo', foo);\n", getContent(actual)); }
private ClosureJsCompiler newProfilingClosureJsCompiler(CompilerOptions realOptions, DefaultJsCompiler defaultComp, CacheProvider cache) { ClosureJsCompiler compiler = createMockBuilder(ClosureJsCompiler.class) .addMockedMethods("getCompilerOptions") .withConstructor(defaultComp, cache, "simple").createMock(); expect(compiler.getCompilerOptions(isA(JsUri.class))).andReturn(realOptions).anyTimes(); replay(compiler); return compiler; }
@Ignore("This class was not being run and when I ran it this test did not pass. Not familiar enough to enable it.") @SuppressWarnings("unchecked") @Test public void testCompileSuccessOptWithProfiling() throws Exception { jsUriMock = mockJsUri(false); // opt realOptionsMock = new CompilerOptions(); realOptionsMock.enableExternExports(false); realOptionsMock.sourceMapOutputPath = "test.out"; realOptionsMock.sourceMapFormat = Format.V2; realOptionsMock.sourceMapDetailLevel = SourceMap.DetailLevel.ALL; realOptionsMock.ideMode = false; realOptionsMock.convertToDottedProperties = true; for (Map.Entry<String, String> compilerTest : COMPILER_IO.entrySet()) { List<JsContent> content = newJsContents(compilerTest.getKey()); exportResponseMock = mockJsResponse(compilerTest.getKey()); compilerMock = mockDefaultJsCompiler(exportResponseMock, content); compiler = newProfilingClosureJsCompiler(realOptionsMock, compilerMock, cacheMock); JsResponse actual = compiler.compile(jsUriMock, content, EXTERN); assertEquals(compilerTest.getValue(), actual.toJsString()); assertTrue(actual.getErrors().isEmpty()); } }