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

🚀♻️ Custom Elements V1 Polyfill #17205

Merged
merged 28 commits into from
Aug 3, 2018
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8b525a7
tmp
jridgewell Jul 26, 2018
94d836a
Fixes
jridgewell Jul 26, 2018
f09eebf
Wrap HTMLElement if Reflect.construct is available
jridgewell Jul 26, 2018
c6f0c7e
Completely isolate code from globals
jridgewell Jul 27, 2018
ad2c0eb
Install in child win
jridgewell Jul 27, 2018
68cf92f
Fix
jridgewell Jul 27, 2018
01d7530
Remove document-register-element
jridgewell Jul 27, 2018
70a70ff
Rename file
jridgewell Jul 27, 2018
dc51611
Fix types
jridgewell Jul 27, 2018
f821d00
Experimentally use new custom elements polyfill
jridgewell Jul 30, 2018
35ebc6d
Register custom-elements-v1 experiment
jridgewell Jul 30, 2018
b5072fc
Fix comment
jridgewell Jul 31, 2018
16ac093
Include custom elements polyfill with module build
jridgewell Jul 31, 2018
6b7a687
Fix build system
jridgewell Jul 31, 2018
ba171aa
Bump build size
jridgewell Jul 31, 2018
eaf7422
tmp
jridgewell Jul 31, 2018
873f0b0
Copious comments
jridgewell Jul 31, 2018
81da198
Use CustomElementsV1 in all tests
jridgewell Jul 31, 2018
e3eeafe
Defer MutationObserver start
jridgewell Aug 1, 2018
72ab68f
Remove unused code
jridgewell Aug 1, 2018
50660bb
Add todos
jridgewell Aug 1, 2018
6a7477b
Fix describes
jridgewell Aug 1, 2018
ecab91f
Update form-proxy inheritance to account for polyfill
jridgewell Aug 1, 2018
f46cee0
Fix "dangerous use of global this"
jridgewell Aug 1, 2018
036cf0d
Review comments
jridgewell Aug 1, 2018
4d47bff
Use V1 in tests
jridgewell Aug 2, 2018
005637d
Merge branch 'master' into custom-elements-v1
jridgewell Aug 3, 2018
6653195
Merge branch 'master' into custom-elements-v1
jridgewell Aug 3, 2018
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
2 changes: 2 additions & 0 deletions build-system/dep-check-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ exports.rules = [
'src/polyfills.js->src/polyfills/object-assign.js',
'src/polyfills.js->src/polyfills/promise.js',
'src/polyfills.js->src/polyfills/array-includes.js',
'src/polyfills.js->src/polyfills/custom-elements.js',
'src/service/extensions-impl.js->src/polyfills/custom-elements.js',
'src/service/extensions-impl.js->src/polyfills/document-contains.js',
'src/service/extensions-impl.js->src/polyfills/domtokenlist-toggle.js',
],
Expand Down
2 changes: 1 addition & 1 deletion build-system/tasks/bundle-size.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const log = require('fancy-log');
const {getStdout} = require('../exec');

const runtimeFile = './dist/v0.js';
const maxSize = '79.28KB';
const maxSize = '80.60KB';
Copy link
Contributor

Choose a reason for hiding this comment

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

Did the maxSize increase because we are shipping both polyfills in this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup.


const {green, red, cyan, yellow} = colors;

Expand Down
16 changes: 7 additions & 9 deletions build-system/tasks/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,21 +282,19 @@ function compile(entryModuleFilenames, outputDir,
// once. Since all files automatically wait for the main binary to load
// this works fine.
if (options.includeOnlyESMLevelPolyfills) {
const polyfillsShadowList = [
'array-includes.js',
'document-contains.js',
'domtokenlist-toggle.js',
'math-sign.js',
'object-assign.js',
'promise.js',
];
const polyfills = fs.readdirSync('src/polyfills');
const polyfillsShadowList = polyfills.filter(p => {
// custom-elements polyfill must be included.
return p !== 'custom-elements.js';
});
srcs.push(
'!build/fake-module/src/polyfills.js',
'!build/fake-module/src/polyfills/**/*.js',
'!build/fake-polyfills/src/polyfills.js',
'!src/polyfills/*.js',
'src/polyfills/custom-elements.js',
'build/fake-polyfills/**/*.js');
polyfillsShadowList.forEach(polyfillFile => {
srcs.push(`!src/polyfills/${polyfillFile}`);
fs.writeFileSync('build/fake-polyfills/src/polyfills/' + polyfillFile,
'export function install() {}');
});
Expand Down
1 change: 1 addition & 0 deletions build-system/tasks/presubmit-checks.js
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@ const forbiddenTerms = {
whitelist: [
'src/log.js', // Has actual implementation of assertElement.
'dist.3p/current/integration.js', // Includes the previous.
'src/polyfills/custom-elements.js',
],
},
'startupChunk\\(': {
Expand Down
37 changes: 24 additions & 13 deletions extensions/amp-form/0.1/form-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,28 +88,39 @@ function createFormProxyConstr(win) {
}

const FormProxyProto = FormProxy.prototype;
const {Object} = win;
const ObjectProto = Object.prototype;

// Hierarchy:
// Node <== Element <== HTMLElement <== HTMLFormElement
// EventTarget <== HTMLFormElement
const inheritance = [
const baseClasses = [
win.HTMLFormElement,
win.HTMLElement,
win.Element,
win.Node,
win.EventTarget,
];
inheritance.forEach(function(klass) {
const prototype = klass && klass.prototype;
for (const name in prototype) {
const property = win.Object.getOwnPropertyDescriptor(prototype, name);
const inheritance = baseClasses.reduce((all, klass) => {
let proto = klass && klass.prototype;
while (proto && proto !== ObjectProto) {
if (all.indexOf(proto) >= 0) {
break;
}
all.push(proto);
proto = Object.getPrototypeOf(proto);
}

return all;
}, []);

inheritance.forEach(proto => {
for (const name in proto) {
const property = win.Object.getOwnPropertyDescriptor(proto, name);
if (!property ||
// Exclude constants.
name.toUpperCase() == name ||
// Exclude on-events.
startsWith(name, 'on') ||
// Exclude properties that already been created.
win.Object.prototype.hasOwnProperty.call(FormProxyProto, name) ||
ObjectProto.hasOwnProperty.call(FormProxyProto, name) ||
// Exclude some properties. Currently only used for testing.
(blacklistedProperties && blacklistedProperties.includes(name))) {
continue;
Expand All @@ -118,19 +129,19 @@ function createFormProxyConstr(win) {
// A method call. Call the original prototype method via `call`.
const method = property.value;
FormProxyProto[name] = function() {
return method.apply(this.form_, arguments);
return method.apply(/** @type {!FormProxy} */(this).form_, arguments);
};
} else {
// A read/write property. Call the original prototype getter/setter.
const spec = {};
if (property.get) {
spec.get = function() {
return property.get.call(this.form_);
return property.get.call(/** @type {!FormProxy} */(this).form_);
};
}
if (property.set) {
spec.set = function(value) {
return property.set.call(this.form_, value);
spec.set = function(v) {
return property.set.call(/** @type {!FormProxy} */(this).form_, v);
};
}
win.Object.defineProperty(FormProxyProto, name, spec);
Expand Down
8 changes: 4 additions & 4 deletions src/custom-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -1756,11 +1756,11 @@ function isInternalOrServiceNode(node) {
* @param {function(new:./base-element.BaseElement, !Element)=} opt_implementationClass For testing only.
* @return {!Object} Prototype of element.
*/
export function createAmpElementProtoForTesting(
export function createAmpElementForTesting(
win, name, opt_implementationClass) {
const ElementProto = createCustomElementClass(win, name).prototype;
const Element = createCustomElementClass(win, name);
if (getMode().test && opt_implementationClass) {
ElementProto.implementationClassForTesting = opt_implementationClass;
Element.prototype.implementationClassForTesting = opt_implementationClass;
}
return ElementProto;
return Element;
}
13 changes: 9 additions & 4 deletions src/polyfills.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,25 @@
* limitations under the License.
*/

import {getMode} from './mode';
import {install as installArrayIncludes} from './polyfills/array-includes';
import {install as installCustomElements} from './polyfills/custom-elements';
import {
install as installDOMTokenListToggle,
} from './polyfills/domtokenlist-toggle';
import {install as installDocContains} from './polyfills/document-contains';
import {install as installMathSign} from './polyfills/math-sign';
import {install as installObjectAssign} from './polyfills/object-assign';
import {install as installPromise} from './polyfills/promise';
// Importing the document-register-element module has the side effect
// of installing the custom elements polyfill if necessary.
import {installCustomElements} from
import {installCustomElements as installRegisterElement} from
'document-register-element/build/document-register-element.patched';
import {isExperimentOn} from './experiments';

installCustomElements(self, 'auto');
if (isExperimentOn(self, 'custom-elements-v1') || getMode().test) {
Copy link
Member

Choose a reason for hiding this comment

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

You want at least one test that ensures the old still works. That is unless you are super optimistic about moving over.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm more worried about bugs with using native custom elements than I am with this polyfill not matching the current polyfill. Worst case we move to this one, and disable the native CE/Reflect.construct support.

installCustomElements(self, class {});
} else {
installRegisterElement(self, 'auto');
}
installDOMTokenListToggle(self);
installMathSign(self);
installObjectAssign(self);
Expand Down
Loading