Skip to content
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.
You can’t perform that action at this time.