示例#1
0
  public void testOneDimensionPermWithCollapse() {
    ModuleDef md = new ModuleDef("testOneDimensionPerm");
    Properties properties = md.getProperties();

    {
      BindingProperty bindingProperty = properties.createBinding("debug");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "false");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "true");
      bindingProperty.addCollapsedValues("true", "false");
    }

    // Permutations and their values are in stable alphabetical order.
    //
    PropertyCombinations permutations =
        new PropertyCombinations(md.getProperties(), md.getActiveLinkerNames());

    List<PropertyCombinations> collapsed = permutations.collapseProperties();
    assertEquals("size", 1, collapsed.size());
    permutations = collapsed.get(0);

    String[] permutation;
    Iterator<String[]> it = permutations.iterator();

    assertTrue(it.hasNext());
    permutation = it.next();
    assertEquals("false", permutation[0]);

    assertTrue(it.hasNext());
    permutation = it.next();
    assertEquals("true", permutation[0]);
  }
示例#2
0
  public void testTwoDimensionPermWithExtension() {
    // This is what you'd get with a conditional <extend-property>
    ModuleDef md = new ModuleDef("testTwoDimensionsWithConditions");
    Properties properties = md.getProperties();

    {
      BindingProperty bindingProperty = properties.createBinding("user.agent");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "moz");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "ie6");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "ie8");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "opera");
    }

    {
      BindingProperty bindingProperty = properties.createBinding("stackTraces");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "false");

      ConditionAny cond = new ConditionAny();
      cond.getConditions().add(new ConditionWhenPropertyIs("user.agent", "ie6"));
      cond.getConditions().add(new ConditionWhenPropertyIs("user.agent", "ie8"));

      bindingProperty.addDefinedValue(cond, "true");
    }

    validateTwoDimensionPerm(properties, md.getActiveLinkerNames());
  }
示例#3
0
 private static String chooseDefault(BindingProperty property, String... candidates) {
   for (String candidate : candidates) {
     if (property.isAllowedValue(candidate)) {
       return candidate;
     }
   }
   return property.getFirstAllowedValue();
 }
示例#4
0
 /** Sets a binding even if it's set to a different value in the GWT application. */
 private static void overrideBinding(ModuleDef module, String propName, String newValue) {
   BindingProperty binding = module.getProperties().findBindingProp(propName);
   if (binding != null) {
     // This sets both allowed and generated values, which is needed since the module
     // might have explicitly disallowed the value.
     // It persists over multiple compiles but that's okay since we set it the same way
     // every time.
     binding.setValues(binding.getRootCondition(), newValue);
   }
 }
示例#5
0
  /** Make sure that a cycle doesn't cause an infinite loop. */
  public void testCycle() {
    // This is what you'd get with a conditional <set-property value="false">
    ModuleDef md = new ModuleDef("testCycle");
    Properties properties = md.getProperties();

    {
      BindingProperty bindingProperty = properties.createBinding("A");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "a1");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "a2");

      bindingProperty.addDefinedValue(new ConditionWhenPropertyIs("B", "b3"), "a3");
    }

    {
      BindingProperty bindingProperty = properties.createBinding("B");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "b1");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "b2");

      bindingProperty.addDefinedValue(new ConditionWhenPropertyIs("A", "a3"), "b3");
    }

    try {
      new PropertyCombinations(properties, md.getActiveLinkerNames());
      fail();
    } catch (IllegalStateException e) {
      // OK
    }
  }
示例#6
0
  public void testTwoDimensionPerm() {
    ModuleDef md = new ModuleDef("testTwoDimensionPerm");
    Properties properties = md.getProperties();

    {
      BindingProperty bindingProperty = properties.createBinding("user.agent");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "moz");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "ie6");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "opera");
    }

    {
      BindingProperty bindingProperty = properties.createBinding("debug");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "false");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "true");
    }

    // String[]s and their values are in stable alphabetical order.
    //
    PropertyCombinations permutations =
        new PropertyCombinations(md.getProperties(), md.getActiveLinkerNames());
    String[] permutation;
    Iterator<String[]> it = permutations.iterator();

    assertTrue(it.hasNext());
    permutation = it.next();
    assertEquals("false", permutation[0]);
    assertEquals("ie6", permutation[1]);

    assertTrue(it.hasNext());
    permutation = it.next();
    assertEquals("false", permutation[0]);
    assertEquals("moz", permutation[1]);

    assertTrue(it.hasNext());
    permutation = it.next();
    assertEquals("false", permutation[0]);
    assertEquals("opera", permutation[1]);

    assertTrue(it.hasNext());
    permutation = it.next();
    assertEquals("true", permutation[0]);
    assertEquals("ie6", permutation[1]);

    assertTrue(it.hasNext());
    permutation = it.next();
    assertEquals("true", permutation[0]);
    assertEquals("moz", permutation[1]);

    assertTrue(it.hasNext());
    permutation = it.next();
    assertEquals("true", permutation[0]);
    assertEquals("opera", permutation[1]);
  }
示例#7
0
  public void testTwoDimensionPermWithCollapse() {
    ModuleDef md = new ModuleDef("testTwoDimensionPerm");
    Properties properties = md.getProperties();

    {
      BindingProperty bindingProperty = properties.createBinding("user.agent");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "moz");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "ie6");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "opera");
      bindingProperty.addCollapsedValues("moz", "ie6", "opera");
    }

    {
      BindingProperty bindingProperty = properties.createBinding("debug");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "false");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "true");
    }

    // String[]s and their values are in stable alphabetical order.
    //
    PropertyCombinations permutations =
        new PropertyCombinations(md.getProperties(), md.getActiveLinkerNames());

    List<PropertyCombinations> collapsed = permutations.collapseProperties();
    assertEquals("size", 2, collapsed.size());

    Iterator<String[]> it = collapsed.get(0).iterator();
    assertEquals(Arrays.asList("false", "ie6"), Arrays.asList(it.next()));
    assertEquals(Arrays.asList("false", "moz"), Arrays.asList(it.next()));
    assertEquals(Arrays.asList("false", "opera"), Arrays.asList(it.next()));
    assertFalse(it.hasNext());

    it = collapsed.get(1).iterator();
    assertEquals(Arrays.asList("true", "ie6"), Arrays.asList(it.next()));
    assertEquals(Arrays.asList("true", "moz"), Arrays.asList(it.next()));
    assertEquals(Arrays.asList("true", "opera"), Arrays.asList(it.next()));
    assertFalse(it.hasNext());
  }
示例#8
0
  /**
   * Attempts to set a binding property to the given value. If the value is not allowed, see if we
   * can find a value that will work. There is a special case for "locale".
   *
   * @return the value actually set, or null if unable to set the property
   */
  private static String maybeSetBinding(
      TreeLogger logger, ModuleDef module, String propName, String newValue) {

    logger = logger.branch(TreeLogger.Type.INFO, "binding: " + propName + "=" + newValue);

    BindingProperty binding = module.getProperties().findBindingProp(propName);
    if (binding == null) {
      logger.log(TreeLogger.Type.WARN, "undefined property: '" + propName + "'");
      return null;
    }

    if (!binding.isAllowedValue(newValue)) {

      String[] allowedValues = binding.getAllowedValues(binding.getRootCondition());
      logger.log(
          TreeLogger.Type.WARN, "property '" + propName + "' cannot be set to '" + newValue + "'");
      logger.log(TreeLogger.Type.INFO, "allowed values: " + Joiner.on(", ").join(allowedValues));

      // See if we can fall back on a reasonable default.
      if (allowedValues.length == 1) {
        // There is only one possibility, so use it.
        newValue = allowedValues[0];
      } else if (binding.getName().equals("locale")) {
        // TODO: come up with a more general solution. Perhaps fail
        // the compile and give the user a way to override the property?
        newValue = chooseDefault(binding, "default", "en", "en_US");
      } else {
        // There is more than one. Continue and possibly compile multiple permutations.
        logger.log(
            TreeLogger.Type.INFO, "continuing without " + propName + ". Sourcemaps may not work.");
        return null;
      }

      logger.log(TreeLogger.Type.INFO, "recovered with " + propName + "=" + newValue);
    }

    binding.setRootGeneratedValues(newValue);
    return newValue;
  }
示例#9
0
  /**
   * Given the source code to a Java class named <code>test.EntryPoint</code>, compiles it with
   * emulated stack traces turned on and returns the JavaScript.
   */
  private JsProgram compileClass(String... lines) throws UnableToCompleteException {

    // Gather the Java source code to compile.

    final String code = Joiner.on("\n").join(lines);

    MockResourceOracle sourceOracle = new MockResourceOracle();
    sourceOracle.addOrReplace(
        new MockJavaResource("test.EntryPoint") {
          @Override
          public CharSequence getContent() {
            return code;
          }
        });
    sourceOracle.add(JavaAstConstructor.getCompilerTypes());

    PrecompileTaskOptions options = new PrecompileTaskOptionsImpl();
    options.setOutput(JsOutputOption.PRETTY);
    options.setRunAsyncEnabled(false);
    CompilerContext context =
        new CompilerContext.Builder()
            .options(options)
            .minimalRebuildCache(new MinimalRebuildCache())
            .build();

    ConfigurationProperties config =
        new ConfigurationProperties(Arrays.asList(recordFileNamesProp, recordLineNumbersProp));

    CompilationState state =
        CompilationStateBuilder.buildFrom(logger, context, sourceOracle.getResources(), null);
    JProgram jProgram = AstConstructor.construct(logger, state, options, config);
    jProgram.addEntryMethod(findMethod(jProgram, "onModuleLoad"));

    if (inline) {
      MethodInliner.exec(jProgram);
    }

    CatchBlockNormalizer.exec(jProgram);
    // Construct the JavaScript AST.

    // These passes are needed by GenerateJavaScriptAST.
    ComputeCastabilityInformation.exec(jProgram, false);
    ImplementCastsAndTypeChecks.exec(jProgram, false);
    ArrayNormalizer.exec(jProgram);

    StringTypeMapper typeMapper = new StringTypeMapper(jProgram);
    ResolveRuntimeTypeReferences.exec(jProgram, typeMapper, TypeOrder.FREQUENCY);
    Map<StandardSymbolData, JsName> symbolTable =
        new TreeMap<StandardSymbolData, JsName>(new SymbolData.ClassIdentComparator());

    BindingProperty stackMode = new BindingProperty("compiler.stackMode");
    stackMode.addDefinedValue(new ConditionNone(), "EMULATED");

    PermutationProperties properties =
        new PermutationProperties(
            Arrays.asList(
                new BindingProperties(
                    new BindingProperty[] {stackMode}, new String[] {"EMULATED"}, config)));

    JsProgram jsProgram = new JsProgram();
    JavaToJavaScriptMap jjsmap =
        GenerateJavaScriptAST.exec(
                logger, jProgram, jsProgram, context, typeMapper, symbolTable, properties)
            .getLeft();

    // Finally, run the pass we care about.
    JsStackEmulator.exec(jProgram, jsProgram, properties, jjsmap);

    return jsProgram;
  }
示例#10
0
  public void testTwoDimensionPermWithExpansion() {
    ModuleDef md = new ModuleDef("testTwoDimensionsWithExpansion");
    Properties properties = md.getProperties();

    {
      BindingProperty bindingProperty = properties.createBinding("user.agent");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "moz");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "ie6");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "ie8");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "opera");
    }

    {
      BindingProperty bindingProperty = properties.createBinding("stackTraces");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "false");
      bindingProperty.addDefinedValue(bindingProperty.getRootCondition(), "true");
      // <set-property name="stackTraces" value="false" />
      bindingProperty.setValues(bindingProperty.getRootCondition(), "false");

      /*
       * <set-property name="stackTraces" value="true,false"> <when user.agent
       * is ie6 or ie 8> </set-property>
       */
      ConditionAny cond = new ConditionAny();
      cond.getConditions().add(new ConditionWhenPropertyIs("user.agent", "ie6"));
      cond.getConditions().add(new ConditionWhenPropertyIs("user.agent", "ie8"));
      bindingProperty.setValues(cond, "true", "false");
    }

    validateTwoDimensionPerm(properties, md.getActiveLinkerNames());
  }
示例#11
0
  /** Loads the module and configures it for SuperDevMode. (Does not restrict permutations.) */
  private ModuleDef loadModule(TreeLogger logger) throws UnableToCompleteException {

    // make sure we get the latest version of any modified jar
    ZipFileClassPathEntry.clearCache();
    ResourceOracleImpl.clearCache();

    ResourceLoader resources = ResourceLoaders.forClassLoader(Thread.currentThread());
    resources = ResourceLoaders.forPathAndFallback(options.getSourcePath(), resources);
    this.resourceLoader.set(resources);

    // ModuleDefLoader.loadFromResources() checks for modified .gwt.xml files.
    ModuleDef moduleDef =
        ModuleDefLoader.loadFromResources(
            logger, compilerContext, inputModuleName, resources, true);
    compilerContext = compilerContextBuilder.module(moduleDef).build();

    // Undo all permutation restriction customizations from previous compiles.
    for (BindingProperty bindingProperty : moduleDef.getProperties().getBindingProperties()) {
      String[] allowedValues = bindingProperty.getAllowedValues(bindingProperty.getRootCondition());
      bindingProperty.setRootGeneratedValues(allowedValues);
    }

    // A snapshot of the module's configuration before we modified it.
    ConfigProps config = new ConfigProps(moduleDef);

    // We need a cross-site linker. Automatically replace the default linker.
    if (IFrameLinker.class.isAssignableFrom(moduleDef.getActivePrimaryLinker())) {
      moduleDef.addLinker("xsiframe");
    }

    // Check that we have a compatible linker.
    Class<? extends Linker> linker = moduleDef.getActivePrimaryLinker();
    if (!CrossSiteIframeLinker.class.isAssignableFrom(linker)) {
      logger.log(
          TreeLogger.ERROR,
          "linkers other than CrossSiteIFrameLinker aren't supported. Found: " + linker.getName());
      throw new UnableToCompleteException();
    }

    // Deactivate precompress linker.
    if (moduleDef.deactivateLinker("precompress")) {
      logger.log(TreeLogger.WARN, "Deactivated PrecompressLinker");
    }

    // Print a nice error if the superdevmode hook isn't present
    if (config.getStrings("devModeRedirectEnabled").isEmpty()) {
      throw new RuntimeException(
          "devModeRedirectEnabled isn't set for module: " + moduleDef.getName());
    }

    // Disable the redirect hook here to make sure we don't have an infinite loop.
    // (There is another check in the JavaScript, but just in case.)
    overrideConfig(moduleDef, "devModeRedirectEnabled", "false");

    // Turn off "installCode" if it's on because it makes debugging harder.
    // (If it's already off, don't change anything.)
    if (config.getBoolean("installCode", true)) {
      overrideConfig(moduleDef, "installCode", "false");
      // Make sure installScriptJs is set to the default for compiling without installCode.
      overrideConfig(
          moduleDef,
          "installScriptJs",
          "com/google/gwt/core/ext/linker/impl/installScriptDirect.js");
    }

    // override computeScriptBase.js to enable the "Compile" button
    overrideConfig(
        moduleDef, "computeScriptBaseJs", "com/google/gwt/dev/codeserver/computeScriptBase.js");
    // Fix bug with SDM and Chrome 24+ where //@ sourceURL directives cause X-SourceMap header to be
    // ignored
    // Frustratingly, Chrome won't canonicalize a relative URL
    overrideConfig(
        moduleDef,
        "includeSourceMapUrl",
        "http://" + serverPrefix + SourceHandler.sourceMapLocationTemplate(moduleDef.getName()));

    // If present, set some config properties back to defaults.
    // (Needed for Google's server-side linker.)
    maybeOverrideConfig(moduleDef, "includeBootstrapInPrimaryFragment", "false");
    maybeOverrideConfig(
        moduleDef, "permutationsJs", "com/google/gwt/core/ext/linker/impl/permutations.js");
    maybeOverrideConfig(
        moduleDef, "propertiesJs", "com/google/gwt/core/ext/linker/impl/properties.js");

    if (options.isIncrementalCompileEnabled()) {
      // CSSResourceGenerator needs to produce stable, unique naming for its input.
      // Currently on default settings CssResourceGenerator's obfuscation depends on
      // whole world knowledge and thus will produce collision in obfuscated mode, since in
      // incremental compiles that information is not available.
      //
      // TODO(dankurka): Once we do proper stable hashing of classes in CssResourceGenerator, we
      // can probably replace / remove this.
      maybeOverrideConfig(moduleDef, "CssResource.style", "stable");
    }

    overrideBinding(moduleDef, "compiler.useSourceMaps", "true");
    overrideBinding(moduleDef, "compiler.useSymbolMaps", "false");
    overrideBinding(moduleDef, "superdevmode", "on");

    return moduleDef;
  }