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

Service cleanup: Require a constructor for all services #9212

Merged
merged 12 commits into from
May 15, 2017

Conversation

kmh287
Copy link
Contributor

@kmh287 kmh287 commented May 8, 2017

This PR removes the optional constructor or optional factory from service registration and instead requires one function that will always be called with new. Services that were previously built with factories pass those factories in as this function. These factories will work identically as before with one caveat: they must not return primitives.

const f = function() {
  return 'Hello World'
}

f()     // 'Hello World'
new f() // {}

This was only a problem in our tests, which needed to be changed to ensure fake factories always returned an object instead of primitives.

/to @dvoytenko @jridgewell I think this is more what you meant on #8946 and #9141 (comment) though I'm worried about the following scenario.

const g = () => 'Hello World'
g()     // 'Hello World'
new g() // TypeError: h is not a constructor

Is this something we should worry about? I can do this in the developer console, but as I write this all tests are passing, including ones that test services that are constructed via factory.

@kmh287 kmh287 requested review from dvoytenko and jridgewell May 8, 2017 23:14
@kmh287 kmh287 changed the title [WIP] Service cleanup: Require a constructor for all services Service cleanup: Require a constructor for all services May 8, 2017
@jridgewell
Copy link
Contributor

So the ES6 spec says you can't new an arrow function. Luckily for us, none of the compilers enforce this (it's an expensive runtime check). We might be able to add a closure type check to ensure every registered service uses a regular function.

@kmh287
Copy link
Contributor Author

kmh287 commented May 10, 2017

I've gone through the services changed in this PR and replaced all arrow functions with regular functions. One factory case still remains: there are some instances where getService is called with an optional factory, circumventing the registration codepath. I'm going to fix this first in another PR to prevent adding a bunch of new files to this review.

/* instantiate */ true);
registerServiceBuilderForDoc(ampdoc,
'viewport',
function(ampdoc) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Can this just be createViewport?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto here, as with createHistory

Copy link
Contributor Author

@kmh287 kmh287 May 11, 2017

Choose a reason for hiding this comment

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

whoops, done for both

@kmh287
Copy link
Contributor Author

kmh287 commented May 10, 2017

Blocked on #9248

src/runtime.js Outdated
@@ -525,13 +523,12 @@ function prepareAndRegisterServiceForDoc(global, extensions,
* @param {!Window} global
* @param {!./service/extensions-impl.Extensions} extensions
* @param {string} name
* @param {function(new:Object, !./service/ampdoc-impl.AmpDoc)=} opt_ctor
* @param {function(!./service/ampdoc-impl.AmpDoc):!Object=} opt_factory
* @param {!function(new:Object, !./service/ampdoc-impl.AmpDoc)} ctor
Copy link
Contributor

Choose a reason for hiding this comment

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

Oops. Do we need to think through backward compatibility? We usually provide the backward compatibility between two PROD versions. E.g. new v0.js should work with the old amp-carousel.js

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should I revert changes in runtime.js and service.js for now and then resubmit after two releases?

Copy link
Contributor

Choose a reason for hiding this comment

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

Can we figure out how to make this a bi-directional code in runtime.js only? Ideally, service doesn't need to do that. Or at the worst, you may need to preserve build() function that you had before?

Ping me to discuss if needed. It is somewhat important. It should also come with TODO and a cleanup task.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dvoytenko Okay, I think I've found a way to do that. PTAL.

@@ -866,6 +866,7 @@ export function installHistoryServiceForDoc(ampdoc) {
registerServiceBuilderForDoc(
ampdoc,
'history',
/* opt_constructor */ undefined,
ampdoc => createHistory(ampdoc));
function(ampdoc) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't this be just registerServiceBuilderForDoc(..., createHistory)? Why reclosure the function with same args?

/* instantiate */ true);
registerServiceBuilderForDoc(ampdoc,
'viewport',
function(ampdoc) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto here, as with createHistory

@dvoytenko
Copy link
Contributor

Sorry. Lost it. Looking now.

src/runtime.js Outdated
@@ -545,12 +545,18 @@ function prepareAndRegisterServiceForDocShadowMode(global, extensions,
* @param {function(!./service/ampdoc-impl.AmpDoc):!Object=} opt_factory
*/
function registerServiceForDoc(ampdoc, name, opt_ctor, opt_factory) {
// TODO(kmh287, #9292): Refactor to remove opt_factory param once #9212 has been
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks great! Please also add TODO(kmh287, #9292) with the corresponding explanation of what will be done to prepareAndRegisterServiceForDoc and prepareAndRegisterServiceForDocShadowMode.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done!

@dvoytenko
Copy link
Contributor

Looks great! Please just update more TODOs as I commented above.

@kmh287 kmh287 force-pushed the service_cleanup4 branch from 733f50e to 43e1c8e Compare May 15, 2017 18:01
@kmh287
Copy link
Contributor Author

kmh287 commented May 15, 2017

Thank you @dvoytenko and @jridgewell for the reviews. I will merge after #9248 has been merged

@kmh287 kmh287 force-pushed the service_cleanup4 branch from 43e1c8e to 0c109a1 Compare May 15, 2017 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants