Skip to content

Commit

Permalink
Strip propTypes when using the minimified/production React.
Browse files Browse the repository at this point in the history
  • Loading branch information
mihaip committed Mar 25, 2015
1 parent ca2343f commit 1ef985e
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 9 deletions.
5 changes: 5 additions & 0 deletions src/info/persistent/react/jscomp/React.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@ public static boolean isReactSourceName(String sourceName) {
sourceName.endsWith("/react-with-addons.js") ||
sourceName.endsWith("/react-with-addons.min.js");
}

public static boolean isReactMinSourceName(String sourceName) {
return sourceName.endsWith("/react.min.js") ||
sourceName.endsWith("/react-with-addons.min.js");
}
}
22 changes: 17 additions & 5 deletions src/info/persistent/react/jscomp/ReactCompilerPass.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public class ReactCompilerPass extends AbstractPostOrderCallback
private static final String GENERATED_SOURCE_NAME = "<ReactCompilerPass-generated.js>";

private final Compiler compiler;
private boolean stripPropTypes = false;
private final Map<String, Node> reactClassesByName = Maps.newHashMap();
private final Map<String, Node> reactClassInterfacePrototypePropsByName =
Maps.newHashMap();
Expand Down Expand Up @@ -187,6 +188,8 @@ private void addTypes(Node root) {
typesNode.removeChildren();
inputNode.addChildrenToFront(typesChildren);
foundReactSource = true;
stripPropTypes = React.isReactMinSourceName(
inputNode.getSourceFileName());
break;
}
}
Expand Down Expand Up @@ -334,8 +337,10 @@ private void visitReactCreateType(
Node interfacePrototypeProps = IR.objectlit();
interfacePrototypePropsByName.put(typeName, interfacePrototypeProps);
Map<String, JSDocInfo> abstractMethodJsDocsByName = Maps.newHashMap();
Node propTypesNode = null;
for (Node key : specNode.children()) {
if (key.getString().equals("mixins")) {
String keyName = key.getString();
if (keyName.equals("mixins")) {
Set<String> mixinNames =
addMixinsToInterface(key, interfacePrototypeProps);
for (String mixinName : mixinNames) {
Expand All @@ -346,6 +351,10 @@ private void visitReactCreateType(
}
continue;
}
if (keyName.equals("propTypes")) {
propTypesNode = key;
continue;
}
if (!key.hasOneChild() || !key.getFirstChild().isFunction()) {
continue;
}
Expand All @@ -356,20 +365,19 @@ private void visitReactCreateType(
// from the ReactComponent interface method, so that it gets type checking
// (without an explicit @override annotation, which doesn't appear to work
// for interface extending interfaces in any case).
JSDocInfo componentMethodJsDoc = componentMethodJsDocs.get(key.getString());
JSDocInfo componentMethodJsDoc = componentMethodJsDocs.get(keyName);
if (componentMethodJsDoc != null) {
mergeInJsDoc(func, componentMethodJsDoc);
}
// Ditto for abstract methods from mixins.
JSDocInfo abstractMethodJsDoc =
abstractMethodJsDocsByName.get(key.getString());
JSDocInfo abstractMethodJsDoc = abstractMethodJsDocsByName.get(keyName);
if (abstractMethodJsDoc != null) {
mergeInJsDoc(func, abstractMethodJsDoc);
}

// Gather method signatures so that we can declare them where the compiler
// can see them.
addFuncToInterface(key.getString(), func, interfacePrototypeProps);
addFuncToInterface(keyName, func, interfacePrototypeProps);

// Add a @this {<type name>} annotation to all methods in the spec, to
// avoid the compiler complaining dangerous use of "this" in a global
Expand All @@ -380,6 +388,10 @@ private void visitReactCreateType(
func.setJSDocInfo(jsDocBuilder.build(func));
}

if (propTypesNode != null && stripPropTypes) {
propTypesNode.detachFromParent();
}

// Generate the interface definition.
Node interfaceTypeFunctionNode =
IR.function(IR.name(""), IR.paramList(), IR.block());
Expand Down
28 changes: 24 additions & 4 deletions test/info/persistent/react/jscomp/ReactCompilerPassTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -418,22 +418,42 @@ public class ReactCompilerPassTest {
"JSC_TYPE_MISMATCH");
}

@Test public void testPropTypesStripping() {
// propTypes should get stripped if we're using the minimized React build
// (since they're not checked).
test(
"var Comp = React.createClass({" +
"propTypes: {aProp: React.PropTypes.string}," +
"render: function() {return React.createElement(\"div\");}" +
"});" +
"React.render(React.createElement(Comp), document.body);",
"React.$render$(React.$createElement$(React.$createClass$({" +
"$render$:function(){return React.$createElement$(\"div\")}" +
"})),document.body);",
"/src/react.min.js",
null);
}

private static void test(String inputJs, String expectedJs) {
test(inputJs, expectedJs, null);
test(inputJs, expectedJs, null, null);
}

private static void testError(String inputJs, String expectedErrorName) {
test(inputJs, "", DiagnosticType.error(expectedErrorName, ""));
test(inputJs, "", null, DiagnosticType.error(expectedErrorName, ""));
}

private static void testError(String inputJs, DiagnosticType expectedError) {
test(inputJs, "", expectedError);
test(inputJs, "", null, expectedError);
}

private static void test(
String inputJs,
String expectedJs,
String reactSourceName,
DiagnosticType expectedError) {
if (reactSourceName == null) {
reactSourceName = "/src/react.js";
}
Compiler compiler = new Compiler(
new PrintStream(ByteStreams.nullOutputStream())); // Silence logging
compiler.disableThreads(); // Makes errors easier to track down.
Expand All @@ -452,7 +472,7 @@ private static void test(
CustomPassExecutionTime.BEFORE_CHECKS,
(CompilerPass) new ReactCompilerPass(compiler)));
List<SourceFile> inputs = ImmutableList.of(
SourceFile.fromCode("/src/react.js", REACT_SOURCE),
SourceFile.fromCode(reactSourceName, REACT_SOURCE),
SourceFile.fromCode("/src/test.js", inputJs)
);
List<SourceFile> externs = ImmutableList.of(
Expand Down
7 changes: 7 additions & 0 deletions test/info/persistent/react/jscomp/ReactTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@ public class ReactTest {
assertFalse(React.isReactSourceName("/src/react.max.js"));
assertTrue(React.isReactSourceName("/src/react-with-addons.js"));
}

@Test public void testIsReactMinSourceName() {
assertFalse(React.isReactMinSourceName("/src/react.js"));
assertTrue(React.isReactSourceName("/src/react.min.js"));
assertFalse(React.isReactSourceName("/src/reactmin.js"));
assertTrue(React.isReactSourceName("/src/react-with-addons.min.js"));
}
}

0 comments on commit 1ef985e

Please sign in to comment.