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

Proxying the form to call the prototype methods/properties, incl Chrome 45 #6944

Merged
merged 4 commits into from Jan 10, 2017

Conversation

dvoytenko
Copy link
Contributor

Rollforward of #6720 including changes necessary for Chrome 45 and below.

The only difference from the previously rolled back #6720 is concentrated in the setupLegacyProxy method.

Copy link
Member

@cramforce cramforce left a comment

Choose a reason for hiding this comment

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

Maybe add a bit more documentation.

// Exclude constants.
name.toUpperCase() == name ||
// Exclude on-events.
name.substring(0, 2) == 'on') {
Copy link
Member

Choose a reason for hiding this comment

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

I'd use indexOf because it avoids string allocation.

Copy link
Contributor

Choose a reason for hiding this comment

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

Or startsWith, which'll avoid a full string search.

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

for (const name in proto) {
if (name in proxy ||
// Exclude constants.
name.toUpperCase() == name ||
Copy link
Member

Choose a reason for hiding this comment

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

Can't we use the correct case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What's the correct case?

Copy link
Member

Choose a reason for hiding this comment

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

Oh, never mind. I read this wrong.

const element = dev().assertElement(current);
const nextSibling = element.nextSibling;
const parent = element.parentNode;
parent.removeChild(element);
Copy link
Member

Choose a reason for hiding this comment

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

This is completely insane. Just saying.

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

if (desc.toggle) {
value = (value != null);
} else {
value = (value === 'true');
Copy link
Member

Choose a reason for hiding this comment

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

Isn't truthiness for attributes based on presence?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

}
}
if (value && desc.url) {
value = parseUrl(/** @type {string} */ (value)).href;
Copy link
Member

Choose a reason for hiding this comment

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

Maybe add a doc.

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

// Exclude constants.
name.toUpperCase() == name ||
// Exclude on-events.
name.substring(0, 2) == 'on') {
Copy link
Contributor

Choose a reason for hiding this comment

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

Or startsWith, which'll avoid a full string search.

value = (value === 'true');
}
}
if (value && desc.url) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be joined as an else if?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. I redid it to communicate exlcusivity more clearly.

dev().assert(false, 'unknown property access type: %s', desc.access);
}
} else {
// Not currently overriden by an input.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand the comment. How does not having a desc mean there's no overriding input?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated. Not sure what I was thinking, but that comment makes 0 sense.

* def: *,
* }>}
*/
const LEGACY_PROPS = {
Copy link
Contributor

Choose a reason for hiding this comment

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

How was this list compiled?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Existing properties in Node/Element/HTMLElement/HTMLFormElement prototype chain minus properties we definitely disabled in validator. For instance, this list excludes things like offsetLeft. These are always properties, not methods.

@dvoytenko
Copy link
Contributor Author

@cramforce @jridgewell PTAL.

* @param {!Object} proxy
*/
function setupLegacyProxy(form, proxy) {
const proto = form.cloneNode(/* deep */ false);
Copy link
Contributor

Choose a reason for hiding this comment

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

#cloneDeep can be overridden. HTMLFormElement.prototype.cloneNode.call(form)?

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

// Exclude constants.
name.toUpperCase() == name ||
// Exclude on-events.
name.startsWith('on')) {
Copy link
Contributor

Choose a reason for hiding this comment

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

You have to import our startsWith helper, #startsWith is only in recent ES6 browsers.

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

// A property such as `style`. The only way is to read this value
// once and use it for all subsequent calls.
let actual;
if (isElement) {
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 move the isElement variable to here?

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 dvoytenko merged commit 5443d59 into ampproject:master Jan 10, 2017
@dvoytenko dvoytenko deleted the proxy5 branch January 10, 2017 22:49
jridgewell pushed a commit to jridgewell/amphtml that referenced this pull request Jan 31, 2017
…me 45 (ampproject#6944)

* Proxying the form to call the prototype methods/properties, incl Chrome 45 support

* Support legacy properties

* review fixes

* review fixes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants