Permalink
Browse files

Strip propTypes when using the minimified/production React.

  • Loading branch information...
mihaip committed Mar 25, 2015
1 parent ca2343f commit 1ef985ed663df508471b87629289765a9337e94b
@@ -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");
+ }
}
@@ -66,6 +66,7 @@
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();
@@ -187,6 +188,8 @@ private void addTypes(Node root) {
typesNode.removeChildren();
inputNode.addChildrenToFront(typesChildren);
foundReactSource = true;
+ stripPropTypes = React.isReactMinSourceName(
+ inputNode.getSourceFileName());
break;
}
}
@@ -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) {
@@ -346,6 +351,10 @@ private void visitReactCreateType(
}
continue;
}
+ if (keyName.equals("propTypes")) {
+ propTypesNode = key;
+ continue;
+ }
if (!key.hasOneChild() || !key.getFirstChild().isFunction()) {
continue;
}
@@ -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
@@ -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());
@@ -418,22 +418,42 @@
"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.
@@ -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(
@@ -16,4 +16,11 @@
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.