Skip to content

Commit d8a4800

Browse files
lauraharkercopybara-github
authored andcommitted
Fix some Polymer + Closure typechecking bugs
* fix compiler assuming return type of "undefined" for behavior methods w/o JSDoc * copy "readOnly" behavior properties into .i.js, as the PolymerPass will then generate a setter method for them. PiperOrigin-RevId: 623516886
1 parent b87fe4c commit d8a4800

File tree

4 files changed

+31
-10
lines changed

4 files changed

+31
-10
lines changed

src/com/google/javascript/jscomp/PolymerClassRewriter.java

+7
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,13 @@ private void appendBehaviorMembersToBlock(final PolymerClassDefinition cls, Node
928928
makeParamSafe(param, paramIndex++);
929929
param = next;
930930
}
931+
if (behaviorFunction.info == null || behaviorFunction.info.getReturnType() == null) {
932+
// Record a return type of ? to avoid the type inferencer assuming this function returns
933+
// 'undefined' just because it's a stub.
934+
info.recordReturnType(
935+
new JSTypeExpression(
936+
new Node(Token.QMARK).srcref(fnValue), fnValue.getSourceFileName()));
937+
}
931938
}
932939

933940
exprResult.getFirstChild().setJSDocInfo(info.build());

src/com/google/javascript/jscomp/ijs/PotentialDeclaration.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,8 @@ Node getRemovableNode() {
499499
* foo: String,
500500
* bar: {
501501
* type: Number,
502-
* value: 123
502+
* value: 123,
503+
* readOnly: true
503504
* }
504505
* },
505506
* baz: function() {}
@@ -530,13 +531,13 @@ void simplify(AbstractCompiler compiler) {
530531
propKey = propKey.getNext()) {
531532
Node propDef = propKey.getOnlyChild();
532533
// A property definition is either a function reference (e.g. String, Number), or another
533-
// object literal. If it's an object literal, only the "type" sub-property matters for type
534-
// checking, so we can delete everything else (which may include e.g. a "value" sub-property
535-
// with a function expression).
534+
// object literal. If it's an object literal, only the "type" and "readOnly" sub-properties
535+
// matters for type checking, so we can delete everything else (which may include e.g. a
536+
// "value" sub-property with a function expression).
536537
if (propDef.isObjectLit()) {
537538
for (Node subProp = propDef.getFirstChild(); subProp != null; ) {
538539
final Node next = subProp.getNext();
539-
if (!subProp.getString().equals("type")) {
540+
if (!subProp.getString().equals("type") && !subProp.getString().equals("readOnly")) {
540541
NodeUtil.deleteNode(subProp, compiler);
541542
}
542543
subProp = next;

test/com/google/javascript/jscomp/PolymerPassTest.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -1774,7 +1774,10 @@ public void testArrowFunctionDefinitionInIifeBehavior() {
17741774
" * @implements {Polymeres6_TestInterface0} ",
17751775
" */",
17761776
"es6.Test = function() {};",
1777-
"/** @suppress {unusedPrivateMembers} */",
1777+
"/**",
1778+
" * @suppress {unusedPrivateMembers}",
1779+
" * @return {?}",
1780+
" */",
17781781
"es6.Test.prototype.sayHi = () => void 0;",
17791782
"",
17801783
"es6.Test = Polymer(/** @lends {es6.Test.prototype} */ {",
@@ -3408,6 +3411,7 @@ public void testBehaviorInIIFE() {
34083411
"/**",
34093412
" * @param {string} funAmount",
34103413
" * @suppress {unusedPrivateMembers}",
3414+
" * @return {?}",
34113415
" */",
34123416
"A.prototype.doSomethingFun = function(funAmount) {};",
34133417
"/** @type {string} */",
@@ -3574,16 +3578,19 @@ public void testBehaviorInModule() {
35743578
"/**",
35753579
" * @param {string} funAmount",
35763580
" * @suppress {unusedPrivateMembers}",
3581+
" * @return {?}",
35773582
" */",
35783583
"A.prototype.doSomethingFun = function(funAmount) {};",
35793584
"/**",
35803585
" * @suppress {unusedPrivateMembers}",
3586+
" * @return {?}",
35813587
" */",
35823588
"A.prototype.doSomethingVeryFun =",
35833589
" function(a, param$polymer$1, c, veryFun = void 0) {};",
35843590
"/**",
35853591
" * @param {string} coolAmount",
35863592
" * @suppress {unusedPrivateMembers}",
3593+
" * @return {?}",
35873594
" */",
35883595
"A.prototype.doSomethingCool = function(coolAmount) {};",
35893596
"A = Polymer(/** @lends {A.prototype} */ {",
@@ -3647,7 +3654,10 @@ public void testBehaviorInModule_destructuringRestParams() {
36473654
"/** @constructor @extends {PolymerElement} @implements {PolymerAInterface0}*/",
36483655
"var A = function() {};",
36493656
"/** @type {string} */ A.prototype.name;",
3650-
"/** @suppress {unusedPrivateMembers} */",
3657+
"/**",
3658+
" * @suppress {unusedPrivateMembers}",
3659+
" * @return {?}",
3660+
" */",
36513661
"A.prototype.doSomethingCool =",
36523662
" function(param$polymer$0 = void 0, ...param$polymer$1) {};",
36533663
"A = Polymer(/** @lends {A.prototype} */ {",

test/com/google/javascript/jscomp/ijs/ConvertToTypedInterfaceTest.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -2325,7 +2325,8 @@ public void testPolymerBehavior() {
23252325
" return \"foo\";",
23262326
" },",
23272327
" reflectToAttribute: true,",
2328-
" observer: \"bazChanged\"",
2328+
" observer: \"bazChanged\",",
2329+
" readOnly: true",
23292330
" }",
23302331
" },",
23312332
" observers: [",
@@ -2365,8 +2366,10 @@ public void testPolymerBehavior() {
23652366
" bar: Number,",
23662367
" /** @type {string|number} */",
23672368
" baz: {",
2368-
// If the property definition is an object, only the "type" sub-property matters.
2369-
" type: String",
2369+
// If the property definition is an object, only the "type" and "readOnly"
2370+
// sub-properties matter.
2371+
" type: String,",
2372+
" readOnly: true",
23702373
" }",
23712374
" },",
23722375
// The "observers" configuration doesn't matter.

0 commit comments

Comments
 (0)