Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix lots of type errors and introduces assertElement. #4885

Merged
merged 5 commits into from
Sep 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions build-system/amp.extern.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,8 @@ twttr.widgets.createTweet;

var FB;
FB.init;

// Validator
var amp;
amp.validator;
amp.validator.validateUrlAndLog = function(string, doc, filter) {}
Binary file modified build-system/runner/dist/runner.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.ampproject;

import com.google.common.collect.ImmutableList;
import com.google.javascript.jscomp.ClosureCodingConvention.AssertFunctionByTypeName;
import com.google.javascript.jscomp.CodingConvention;
import com.google.javascript.jscomp.CodingConvention.AssertionFunctionSpec;
import com.google.javascript.jscomp.CodingConventions;
Expand Down Expand Up @@ -45,9 +46,8 @@ public AmpCodingConvention(CodingConvention convention) {
return ImmutableList.of(
new AssertionFunctionSpec("user.assert", JSType.TRUTHY),
new AssertionFunctionSpec("dev.assert", JSType.TRUTHY),
new AssertionFunctionSpec("module$src$log.user.assert", JSType.TRUTHY),
new AssertionFunctionSpec("module$src$log.dev.assert", JSType.TRUTHY),
new AssertionFunctionSpec("Log$$module$src$log.prototype.assert", JSType.TRUTHY)
new AssertionFunctionSpec("Log$$module$src$log.prototype.assert", JSType.TRUTHY),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so we need to change this too to "AssertFunctionByTypeName" ?

Copy link
Member

@erwinmombay erwinmombay Sep 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah nvm, looks like that doesn't work. i was hoping AssertFunctionByTypeName solves the inference issue

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is just an utility to be able to use custom types like Element

new AssertFunctionByTypeName("Log$$module$src$log.prototype.assertElement", "Element")
);
}

Expand Down
5 changes: 3 additions & 2 deletions src/event-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,10 @@ export function isLoaded(element) {
* Returns a promise that will resolve or fail based on the element's 'load'
* and 'error' events. Optionally this method takes a timeout, which will reject
* the promise if the resource has not loaded by then.
* @param {!Element} element
* @param {T} element
* @param {number=} opt_timeout
* @return {!Promise<!Element>}
* @return {!Promise<T>}
* @template T
*/
export function loadPromise(element, opt_timeout) {
let unlistenLoad;
Expand Down
2 changes: 1 addition & 1 deletion src/json.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export function getValueForExpr(obj, expr) {
* Parses the given `json` string without throwing an exception if not valid.
* Returns `undefined` if parsing fails.
* Returns the `Object` corresponding to the JSON string when parsing succeeds.
* @param {string} json JSON string to parse
* @param {*} json JSON string to parse
* @param {function(!Error)=} opt_onFailed Optional function that will be called with
* the error if parsing fails.
* @return {?JSONValueDef|undefined}
Expand Down
18 changes: 18 additions & 0 deletions src/log.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,24 @@ export class Log {
}
return shouldBeTrueish;
}

/**
* Throws an error if the first argument isn't an Element
*
* Otherwise see `assert` for usage
*
* @param {*} shouldBeElement
* @param {string=} opt_message The assertion message
* @return {!Element} The value of shouldBeTrueish.
* @template T
*/
/*eslint "google-camelcase/google-camelcase": 2*/
assertElement(shouldBeElement, opt_message) {
const shouldBeTrueish = shouldBeElement && shouldBeElement.nodeType == 1;
this.assert(shouldBeTrueish, (opt_message || 'Element expected') + ': %s',
shouldBeElement);
return /** @type {!Element} */ (shouldBeElement);
}

/**
* Asserts and returns the enum value. If the enum doesn't contain such a value,
Expand All @@ -261,6 +278,7 @@ export class Log {
* @return T
* @template T
*/
/*eslint "google-camelcase/google-camelcase": 2*/
assertEnumValue(enumObj, s, opt_enumName) {
for (const k in enumObj) {
if (enumObj[k] == s) {
Expand Down
5 changes: 3 additions & 2 deletions src/performance.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ import {getExistingServiceForWindow} from './service';

/**
* @param {!Window} window
* @return {!Performance}
* @return {!./service/performance-impl.Performance}
*/
export function performanceFor(window) {
return getExistingServiceForWindow(window, 'performance');
return /** @type {!./service/performance-impl.Performance}*/ (
getExistingServiceForWindow(window, 'performance'));
};
19 changes: 10 additions & 9 deletions src/service/url-replacements-impl.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class UrlReplacements {
/** @private {!RegExp|undefined} */
this.replacementExpr_ = undefined;

/** @private @const {!Object<string, function(*):*>} */
/** @private @const {!Object<string, function(*, *):*>} */
this.replacements_ = this.win_.Object.create(null);

/** @private @const {function():!Promise<?AccessService>} */
Expand Down Expand Up @@ -426,7 +426,7 @@ export class UrlReplacements {
* @template T
*/
getAccessValue_(getter, expr) {
return this.getAccessService_(this.win_).then(accessService => {
return this.getAccessService_().then(accessService => {
if (!accessService) {
// Access service is not installed.
user().error(TAG, 'Access service is not installed to access: ', expr);
Expand All @@ -441,8 +441,8 @@ export class UrlReplacements {
* The data for the timing events is retrieved from performance.timing API.
* If start and end events are both given, the result is the difference between the two.
* If only start event is given, the result is the timing value at start event.
* @param {string} startEvent
* @param {string=} endEvent
* @param {*} startEvent
* @param {*=} endEvent
* @return {!Promise<string|undefined>}
* @private
*/
Expand Down Expand Up @@ -472,14 +472,15 @@ export class UrlReplacements {
: String(metric);
});
} else {
return Promise.resolve(String(metric));
return /** @type {!Promise<(string|undefined)>} */ (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be !Promise<string>.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same reason. Unfortunately CC doesn't support complex type equivalencies on generics.

Promise.resolve(String(metric)));
}
}

/**
* Returns navigation information from the current browsing context.
* @param {string} attribute
* @return {!Promise<string|undefined>}
* @return {!Promise<undefined>|string}
* @private
*/
getNavigationData_(attribute) {
Expand All @@ -497,7 +498,7 @@ export class UrlReplacements {
* Sets the value resolver for the variable with the specified name. The
* value resolver may optionally take an extra parameter.
* @param {string} varName
* @param {function(*):*} resolver
* @param {function(*, *):*} resolver
* @return {!UrlReplacements}
* @private
*/
Expand Down Expand Up @@ -604,7 +605,7 @@ export class UrlReplacements {
/**
* Method exists to assist stubbing in tests.
* @param {string} name
* @return {function(*):*}
* @return {function(*, *):*}
*/
getReplacement_(name) {
return this.replacements_[name];
Expand All @@ -620,7 +621,7 @@ export class UrlReplacements {
if (additionalKeys && additionalKeys.length > 0) {
const allKeys = Object.keys(this.replacements_);
additionalKeys.forEach(key => {
if (allKeys[key] === undefined) {
if (this.replacements_[key] === undefined) {
allKeys.push(key);
}
});
Expand Down
47 changes: 25 additions & 22 deletions src/service/viewer-impl.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export class Viewer {
/** @private {boolean} */
this.overtakeHistory_ = false;

/** @private {string} */
/** @private {!VisibilityState} */
this.visibilityState_ = VisibilityState.VISIBLE;

/** @private {string} */
Expand Down Expand Up @@ -164,6 +164,15 @@ export class Viewer {
/** @private {?time} */
this.firstVisibleTime_ = null;

/** @private {?Function} */
this.messagingReadyResolver_ = null;

/** @private {?Function} */
this.viewerOriginResolver_ = null;

/** @private {?Function} */
this.trustedViewerResolver_ = null;

/**
* This promise might be resolved right away if the current
* document is already visible. See end of this constructor where we call
Expand All @@ -188,8 +197,8 @@ export class Viewer {
this.isRuntimeOn_ = !parseInt(this.params_['off'], 10);
dev().fine(TAG_, '- runtimeOn:', this.isRuntimeOn_);

this.overtakeHistory_ = !!(parseInt(this.params_['history'], 10)) ||
this.overtakeHistory_;
this.overtakeHistory_ = !!(parseInt(this.params_['history'], 10) ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merged my changes, this should be the only line that has a conflict

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh theres another conflict at the bottom i completely missed on line 1102

this.overtakeHistory_);
dev().fine(TAG_, '- history:', this.overtakeHistory_);

this.setVisibilityState_(this.params_['visibilityState']);
Expand Down Expand Up @@ -237,9 +246,6 @@ export class Viewer {
// Wait for document to become visible.
this.docState_.onVisibilityChanged(this.recheckVisibilityState_.bind(this));

/** @private {function()|undefined} */
this.messagingReadyResolver_ = undefined;

/**
* This promise will resolve when communications channel has been
* established or timeout in 20 seconds. The timeout is needed to avoid
Expand Down Expand Up @@ -287,9 +293,6 @@ export class Viewer {
this.isTrustedViewerOrigin_(this.win.location.ancestorOrigins[0]));
trustedViewerPromise = Promise.resolve(trustedViewerResolved);
} else {

/** @private {!function(boolean)|undefined} */
this.trustedViewerResolver_ = undefined;
// Wait for comms channel to confirm the origin.
trustedViewerResolved = undefined;
trustedViewerPromise = new Promise(resolve => {
Expand All @@ -300,9 +303,6 @@ export class Viewer {
/** @const @private {!Promise<boolean>} */
this.isTrustedViewer_ = trustedViewerPromise;

/** @private {!function(string)|undefined} */
this.viewerOriginResolver_ = undefined;

/** @const @private {!Promise<string>} */
this.viewerOrigin_ = new Promise(resolve => {
if (!this.isEmbedded()) {
Expand Down Expand Up @@ -775,7 +775,8 @@ export class Viewer {
* @return {!Promise}
*/
requestFullOverlay() {
return this.sendMessageUnreliable_('requestFullOverlay', {}, true);
return /** @type {!Promise} */ (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to be typecast?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because CC is bad at templates and this message can return null. Unfortunately the assert cannot produce the right type here.

this.sendMessageUnreliable_('requestFullOverlay', {}, true));
}

/**
Expand All @@ -784,7 +785,8 @@ export class Viewer {
* @return {!Promise}
*/
cancelFullOverlay() {
return this.sendMessageUnreliable_('cancelFullOverlay', {}, true);
return /** @type {!Promise} */ (
this.sendMessageUnreliable_('cancelFullOverlay', {}, true));
}

/**
Expand All @@ -793,8 +795,8 @@ export class Viewer {
* @return {!Promise}
*/
postPushHistory(stackIndex) {
return this.sendMessageUnreliable_(
'pushHistory', {stackIndex}, true);
return /** @type {!Promise} */ (this.sendMessageUnreliable_(
'pushHistory', {stackIndex}, true));
}

/**
Expand All @@ -803,8 +805,8 @@ export class Viewer {
* @return {!Promise}
*/
postPopHistory(stackIndex) {
return this.sendMessageUnreliable_(
'popHistory', {stackIndex}, true);
return /** @type {!Promise} */ (this.sendMessageUnreliable_(
'popHistory', {stackIndex}, true));
}

/**
Expand Down Expand Up @@ -833,7 +835,7 @@ export class Viewer {
// it should resolve in milli seconds.
return timerFor(this.win).timeoutPromise(10000, cidPromise, 'base cid')
.catch(error => {
dev().error(error);
dev().error(TAG_, error);
return undefined;
});
});
Expand Down Expand Up @@ -921,7 +923,8 @@ export class Viewer {
return Promise.resolve();
}
if (eventType == 'broadcast') {
this.broadcastObservable_.fire(data);
this.broadcastObservable_.fire(
/** @type {!JSONType|undefined} */ (data));
return Promise.resolve();
}
dev().fine(TAG_, 'unknown message:', eventType);
Expand Down Expand Up @@ -1014,7 +1017,7 @@ export class Viewer {
* @param {string} eventType
* @param {*} data
* @param {boolean} awaitResponse
* @return {!Promise<*>|undefined}
* @return {?Promise<*>|undefined}
* @private
*/
sendMessageUnreliable_(eventType, data, awaitResponse) {
Expand Down Expand Up @@ -1090,7 +1093,7 @@ function parseParams_(str, allParams) {

/**
* Creates an error for the case where a channel cannot be established.
* @param {!Error|string=} opt_reason
* @param {*=} opt_reason
* @return {!Error}
*/
function getChannelError(opt_reason) {
Expand Down
20 changes: 11 additions & 9 deletions src/service/viewport-impl.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export class Viewport {
/** @private @const {!Observable} */
this.scrollObservable_ = new Observable();

/** @private {?HTMLMetaElement|undefined} */
/** @private {?Element|undefined} */
this.viewportMeta_ = undefined;

/** @private {string|undefined} */
Expand Down Expand Up @@ -491,7 +491,7 @@ export class Viewport {
}

/**
* @return {?HTMLMetaElement}
* @return {?Element}
* @private
*/
getViewportMeta_() {
Expand Down Expand Up @@ -627,9 +627,7 @@ export class ViewportBindingDef {
* independent fixed layer.
* @return {boolean}
*/
requiresFixedLayerTransfer() {
return false;
}
requiresFixedLayerTransfer() {}

/**
* Register a callback for scroll events.
Expand Down Expand Up @@ -908,6 +906,9 @@ export class ViewportBindingNaturalIosEmbed_ {
/** @private {?Element} */
this.scrollMoveEl_ = null;

/** @private {?Element} */
this.endPosEl_ = null;

/** @private {!{x: number, y: number}} */
this.pos_ = {x: 0, y: 0};

Expand Down Expand Up @@ -936,7 +937,8 @@ export class ViewportBindingNaturalIosEmbed_ {
/** @private */
setup_() {
const documentElement = this.win.document.documentElement;
const documentBody = this.win.document.body;
const documentBody = /** @type {!Element} */ (
this.win.document.body);

// Embedded scrolling on iOS is rather complicated. IFrames cannot be sized
// and be scrollable. Sizing iframe by scrolling height has a big negative
Expand Down Expand Up @@ -1185,7 +1187,7 @@ export class ViewportBindingNaturalIosEmbed_ {
* width=device-width,initial-scale=1,minimum-scale=1
* ```
* @param {string} content
* @return {!Object<string, string>}
* @return {!Object<string, (string|undefined)>}
* @private Visible for testing only.
*/
export function parseViewportMeta(content) {
Expand Down Expand Up @@ -1288,7 +1290,7 @@ function createViewport_(window) {
* @return {!Viewport}
*/
export function installViewportService(window) {
return getService(window, 'viewport', () => {
return /** @type !Viewport} */ (getService(window, 'viewport', () => {
return createViewport_(window);
});
}));
};
Loading