Address feedback from kschaaf

This commit is contained in:
Daniel Freedman
2017-01-18 14:24:27 -08:00
parent af1afd75f2
commit a2757991ea
16 changed files with 178 additions and 154 deletions
+60 -66
View File
@@ -2,10 +2,8 @@
* @fileoverview Externs for Polymer, polyfills, and missing stuff in Closure Compiler
* @externs
* */
/**
* @param {!{is: string}} init
*/
function Polymer(init){}
/* externs to upstream to closure compiler */
/**
* @record
@@ -20,12 +18,50 @@ CustomElement.prototype.disconnectedCallback;
/** @type {function(string, ?string, ?string, ?string)|undefined} */
CustomElement.prototype.attributeChangedCallback;
/** @type {boolean} */
Event.prototype.composed;
/**
* @return {!Array<!(Element|ShadowRoot|Document|Window)>}
*/
Event.prototype.composedPath = function(){};
/**
* @param {!{mode: string}} options
* @return {!ShadowRoot}
*/
HTMLElement.prototype.attachShadow = function(options){};
/**
* @constructor
* @extends {HTMLElement}
*/
function HTMLSlotElement(){}
/**
* @param {!{flatten: boolean}=} options
* @return {!Array<!Node>}
*/
HTMLSlotElement.prototype.assignedNodes = function(options){};
/** @type {HTMLSlotElement} */
Node.prototype.assignedSlot;
/** @constructor */
function InputDeviceCapabilities(){}
/** @type {boolean} */
InputDeviceCapabilities.prototype.firesTouchEvents;
/** @type {InputDeviceCapabilities} */
MouseEvent.prototype.sourceCapabilities;
const customElements = {
/**
* @param {string} tagName
* @param {!CustomElement} klass
* @param {Object=} options
* @return {CustomElement}
* @return {!CustomElement}
*/
define(tagName, klass, options){},
/**
@@ -41,6 +77,17 @@ const customElements = {
}
window.customElements = customElements;
/* externs to include in webcomponents polyfills */
/**
* @constructor
* @extends {HTMLElement}
*/
function CustomStyle(){}
/**
* @param {!HTMLStyleElement} style
*/
CustomStyle.prototype.processHook = function(style){};
let HTMLImports = {
/**
* @param {function()} callback
@@ -73,69 +120,16 @@ window.ShadyDOM = ShadyDOM;
let WebComponents = {};
window.WebComponents = WebComponents;
/**
* @type {boolean}
*/
Event.prototype.composed;
/**
* @return {!Array<!(Element|ShadowRoot|Document|Window)>}
*/
Event.prototype.composedPath = function(){};
/**
* @param {!{mode: string}} options
* @return {!ShadowRoot}
*/
HTMLElement.prototype.attachShadow = function(options){};
/**
* @constructor
* @extends {HTMLElement}
*/
function CustomStyle(){}
/**
* @param {!HTMLStyleElement} style
*/
CustomStyle.prototype.processHook = function(style){};
/**
* @constructor
* @extends {HTMLElement}
*/
function HTMLSlotElement(){}
/**
* @param {!{flatten: boolean} | undefined} options
* @return {!Array<!Node>}
*/
HTMLSlotElement.prototype.assignedNodes = function(options){};
/**
* @type {HTMLSlotElement}
*/
Node.prototype.assignedSlot;
/**
* @constructor
*/
function InputDeviceCapabilities(){}
/**
* @type {boolean}
*/
InputDeviceCapabilities.prototype.firesTouchEvents;
/**
* @type {InputDeviceCapabilities}
*/
MouseEvent.prototype.sourceCapabilities;
/**
* @type {Element}
*/
/** @type {Element} */
HTMLElement.prototype._activeElement;
/**
* @param {HTMLTemplateElement} template
*/
HTMLTemplateElement.prototype.decorate = function(template){};
HTMLTemplateElement.prototype.decorate = function(template){};
/**
* @param {!{is: string}} init
* @return {!CustomElement}
*/
function Polymer(init){}
+69 -45
View File
@@ -20,10 +20,18 @@ const del = require('del');
const eslint = require('gulp-eslint');
const fs = require('fs');
const path = require('path');
const mergeStream = require('merge-stream');
const babel = require('gulp-babel');
const htmlmin = require('gulp-htmlmin');
const size = require('gulp-size');
const lazypipe = require('lazypipe');
const closure = require('google-closure-compiler').gulp();
const minimalDocument = require('./util/minimalDocument.js')
const DIST_DIR = 'dist';
const BUNDLED_DIR = path.join(DIST_DIR, 'bundled');
const UNBUNDLED_DIR = path.join(DIST_DIR, 'unbundled');
const COMPILED_DIR = path.join(DIST_DIR, 'compiled');
const DEFAULT_BUILD_DIR = BUNDLED_DIR;
const POLYMER_LEGACY = 'polymer.html';
const POLYMER_ELEMENT = 'polymer-element.html';
@@ -32,24 +40,10 @@ const ENTRY_POINTS = [POLYMER_LEGACY, POLYMER_ELEMENT];
const polymer = require('polymer-build');
const PolymerProject = polymer.PolymerProject;
const project = new PolymerProject({
sources: ['./polymer.html'],
shell: './polymer.html'
});
const project = new PolymerProject({ shell: DEFAULT_BUILD_TARGET });
const fork = polymer.forkStream;
const mergeStream = require('merge-stream');
const babel = require('gulp-babel');
const uglify = require('gulp-uglify');
const htmlmin = require('gulp-htmlmin');
const gzipSize = require('gzip-size');
const prettyBytes = require('pretty-bytes');
const lazypipe = require('lazypipe');
const closure = require('google-closure-compiler').gulp();
gulp.task('clean', function () {
gulp.task('clean', function() {
return del(DIST_DIR);
});
@@ -81,21 +75,21 @@ class OldNameStream extends Transform {
}
}
gulp.task('build', ['clean'], () => {
gulp.task('closure', ['clean'], () => {
const project = new PolymerProject({
sources: ['./polymer.html'],
shell: './polymer.html'
});
const closureStream = closure({
// debug: true,
// new_type_inf: true,
compilation_level: 'ADVANCED',
// compilation_level: 'SIMPLE',
language_in: 'ES6_STRICT',
language_out: 'ES5_STRICT',
warning_level: 'VERBOSE',
output_wrapper: '(function(){\n%output%\n}).call(self)',
rewrite_polyfills: false,
formatting: 'PRETTY_PRINT',
externs: 'externs/externs.js'
// polymer_pass: true
});
const closurePipeline = lazypipe()
@@ -116,26 +110,65 @@ gulp.task('build', ['clean'], () => {
.pipe(project.splitHtml())
.pipe(gulpif(/polymer\.html_script_\d+\.js$/, closurePipeline()))
.pipe(project.rejoinHtml())
.pipe(gulp.dest(BUNDLED_DIR))
.pipe(htmlmin({removeComments: true}))
.pipe(gulpif(/polymer\.html/, minimalDocument()))
.pipe(gulpif(/polymer\.html/, size({title: 'closure size', gzip: true, showTotal: false, showFiles: true})))
.pipe(gulp.dest(COMPILED_DIR))
});
gulp.task('build', ['clean'], () => {
// process source files in the project
const sources = project.sources();
// process dependencies
const dependencies = project.dependencies();
// merge the source and dependencies streams to we can analyze the project
const mergedFiles = mergeStream(sources, dependencies);
const bundlePipe = lazypipe()
.pipe(() => project.splitHtml())
.pipe(() => gulpif(/\.js$/, babel({presets: ['babili']})))
.pipe(() => project.rejoinHtml())
.pipe(htmlmin, {removeComments: true})
.pipe(minimalDocument)
.pipe(size, {title: 'bundled size', gzip: true, showTotal: false, showFiles: true})
return mergeStream(
fork(mergedFiles)
.pipe(project.bundler)
.pipe(gulpif(/polymer\.html/, bundlePipe()))
// write to the bundled folder
.pipe(gulp.dest(BUNDLED_DIR)),
fork(mergedFiles)
.pipe(project.splitHtml())
// add compilers or optimizers here!
.pipe(gulpif(/\.js$/, babel({presets: ['babili']})))
.pipe(project.rejoinHtml())
.pipe(htmlmin({removeComments: true}))
// write to the unbundled folder
.pipe(gulp.dest(UNBUNDLED_DIR))
);
});
// copy bower.json into dist folder
gulp.task('copy-bower-json', function () {
gulp.task('copy-bower-json', function() {
return gulp.src('bower.json').pipe(gulp.dest(DEFAULT_BUILD_DIR));
});
// Build
gulp.task('build-steps', function (cb) {
gulp.task('build-steps', function(cb) {
runseq('restore-src', 'build', 'print-size', cb);
});
// Bundled build
gulp.task('build-bundled', function (cb) {
gulp.task('build-bundled', function(cb) {
runseq('build-steps', 'save-src', 'link-bundled', cb);
});
// Unbundled build
gulp.task('build-unbundled', function (cb) {
gulp.task('build-unbundled', function(cb) {
runseq('build-steps', 'save-src', 'link-unbundled', cb);
});
@@ -143,58 +176,49 @@ gulp.task('build-unbundled', function (cb) {
gulp.task('default', ['build-bundled']);
// switch src and build for testing
gulp.task('save-src', function () {
gulp.task('save-src', function() {
return gulp.src(ENTRY_POINTS)
.pipe(rename(function (p) {
.pipe(rename(function(p) {
p.extname += '.src';
}))
.pipe(gulp.dest('.'));
});
gulp.task('restore-src', function (cb) {
gulp.task('restore-src', function(cb) {
const files = ENTRY_POINTS.map(f => `${f}.src`);
gulp.src(files)
.pipe(rename(function (p) {
.pipe(rename(function(p) {
p.extname = '';
}))
.pipe(gulp.dest('.'))
.on('end', () => Promise.all(files.map(f => del(f))).then(() => cb()));
});
gulp.task('link-bundled', function (cb) {
gulp.task('link-bundled', function(cb) {
ENTRY_POINTS.forEach(f => {
fs.writeFileSync(f, `<link rel="import" href="${DEFAULT_BUILD_DIR}/${DEFAULT_BUILD_TARGET}">`);
});
cb();
});
gulp.task('link-unbundled', function (cb) {
gulp.task('link-unbundled', function(cb) {
ENTRY_POINTS.forEach(f => {
fs.writeFileSync(f, `<link rel="import" href="${DEFAULT_BUILD_DIR}/${f}">`);
});
cb();
});
gulp.task('print-size', function (cb) {
fs.readFile(path.join(DEFAULT_BUILD_DIR, DEFAULT_BUILD_TARGET), function (err, contents) {
gzipSize(contents, function (err, size) {
console.log(`${DEFAULT_BUILD_TARGET} size: ${prettyBytes(size)}`);
cb();
});
});
});
gulp.task('audit', function () {
gulp.task('audit', function() {
return gulp.src(ENTRY_POINTS.map(f => path.join(DEFAULT_BUILD_DIR, f)))
.pipe(audit('build.log', { repos: ['.'] }))
.pipe(gulp.dest(DEFAULT_BUILD_DIR));
});
gulp.task('release', function (cb) {
gulp.task('release', function(cb) {
runseq('default', ['copy-bower-json', 'audit'], cb);
});
gulp.task('lint', function () {
gulp.task('lint', function() {
return gulp.src(['src/**/*.html', 'test/unit/*.html', 'util/*.js'])
.pipe(eslint())
.pipe(eslint.format())
+3 -8
View File
@@ -8,8 +8,7 @@
"test": "test"
},
"devDependencies": {
"babel-plugin-external-helpers": "^6.8.0",
"babel-preset-es2015": "^6.13.2",
"babel-preset-babili": "0.0.10",
"del": "^2.2.1",
"dom5": "^1.3.1",
"eslint-plugin-html": "^1.3.0",
@@ -18,19 +17,15 @@
"gulp-audit": "^1.0.0",
"gulp-babel": "^6.1.2",
"gulp-eslint": "^3.0.1",
"gulp-htmlmin": "^2.0.0",
"gulp-htmlmin": "^3.0.0",
"gulp-if": "^2.0.1",
"gulp-rename": "^1.2.2",
"gulp-replace": "^0.5.3",
"gulp-size": "^2.1.0",
"gulp-uglify": "^2.0.0",
"gulp-vulcanize": "^6.0.1",
"lazypipe": "^1.0.1",
"merge-stream": "^1.0.0",
"polyclean": "^1.2.0",
"merge-stream": "^1.0.1",
"polymer-build": "^0.6.0",
"run-sequence": "^1.1.0",
"through2": "^2.0.0",
"web-component-tester": "^4"
},
"scripts": {
+1
View File
@@ -1 +1,2 @@
<!DOCTYPE html>
<link rel="import" href="src/elements/element.html">
+1
View File
@@ -1,3 +1,4 @@
<!DOCTYPE html>
<!-- bc compatible Polymer({...}); enabled via Polymer.LegacyElement -->
<link rel="import" href="src/legacy/polymer-fn.html">
<link rel="import" href="src/legacy/class.html">
+1
View File
@@ -1,3 +1,4 @@
<!DOCTYPE html>
<link rel="import" href="polymer-legacy.html">
<!-- template elements -->
<link rel="import" href="src/templatizer/dom-bind.html">
+1 -1
View File
@@ -85,7 +85,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
static _getTemplate() {
return behavior._template || super._getTemplate();
return behavior._template || super._getTemplate() || this.prototype._template;
}
/**
+1 -1
View File
@@ -1985,7 +1985,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
propPath = info.path;
} else if (Array.isArray(path)) {
// Normalize path if needed
propPath = /** @type {string} */(Polymer.Path.normalize(path));
propPath = Polymer.Path.normalize(path);
} else {
propPath = /** @type{string} */(path);
}
+1 -2
View File
@@ -326,8 +326,7 @@ is false, `selected` is a property representing the last selected item. When
Polymer.ArraySelectorMixin = ArraySelectorMixin;
// define element class & export
const ArraySelectorMixinImpl = ArraySelectorMixin(Polymer.Element);
class ArraySelector extends ArraySelectorMixinImpl { }
const ArraySelector = ArraySelectorMixin(Polymer.Element);
customElements.define('array-selector', ArraySelector);
Polymer.ArraySelector = ArraySelector;
+2 -2
View File
@@ -34,7 +34,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
static get template() { return null; }
static get config() {
static get config() {
return {
@@ -81,7 +81,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
_debounceRender() {
this._renderDebouncer =
Polymer.Debouncer.debounce(this._renderDebouncer, this._render, null, this);
Polymer.Debouncer.debounce(this._renderDebouncer, this._render, undefined, this);
Polymer.Templatizer.enqueueDebouncer(this._renderDebouncer);
}
+2 -1
View File
@@ -425,7 +425,7 @@ Then the `observe` property should be configured as follows:
/**
* @param {function()} fn
* @param {?number=} delay
* @param {number=} delay
*/
_debounceRender(fn, delay) {
this._renderDebouncer =
@@ -634,6 +634,7 @@ Then the `observe` property should be configured as follows:
*
* @method modelForElement
* @param {HTMLElement} el Element for which to return a template model.
* TODO(kschaaf): replace return type with interface for TemplateInstanceBaseInterface
* @return {Object} Model representing the binding scope for
* the element.
*/
+1
View File
@@ -270,6 +270,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
*
* @method modelForElement
* @param {HTMLElement} el Element for which to return a template model.
* TODO(kschaaf): replace return type with interface for TemplateInstanceBaseInterface
* @return {Object} Model representing the binding scope for
* the element.
*/
+4
View File
@@ -13,6 +13,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
window.Polymer.version = '2.0-preview';
/* eslint-disable no-unused-vars */
/*
When using Closure Compiler, goog.reflect.objectProperty(property, object) is replaced by the munged name for object[property]
We cannot alias this function, so we have to use a small shim that has the same behavior when not compiling.
*/
var goog = {
reflect: {
objectProperty(s, o) {
+1 -1
View File
@@ -63,7 +63,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
/**
* @param {Debouncer} debouncer
* @param {function()} callback
* @param {?number=} wait
* @param {number=} wait
* @param {Object=} context
* @return {Debouncer}
*/
+2 -2
View File
@@ -37,9 +37,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
constructor(target, callback) {
/** @type {MutationObserver} */
this.shadyChildrenObserver;
this.shadyChildrenObserver = null;
/** @type {MutationObserver} */
this.nativeChildrenObserver;
this.nativeChildrenObserver = null;
this.connected = false;
this.target = target;
this.callback = callback;
+28 -25
View File
@@ -11,10 +11,10 @@
// jshint node: true
'use strict';
var dom5 = require('dom5');
var through2 = require('through2');
const dom5 = require('dom5');
const {Transform} = require('stream');
var p = dom5.predicates;
const p = dom5.predicates;
function isBlankTextNode(node) {
return node && dom5.isTextNode(node) && !/\S/.test(dom5.getTextContent(node));
@@ -24,14 +24,14 @@ function replaceWithChildren(node) {
if (!node) {
return;
}
var parent = node.parentNode;
var idx = parent.childNodes.indexOf(node);
var children = node.childNodes;
let parent = node.parentNode;
let idx = parent.childNodes.indexOf(node);
let children = node.childNodes;
children.forEach(function(n) {
n.parentNode = parent;
});
var til = idx + 1;
var next = parent.childNodes[til];
let til = idx + 1;
let next = parent.childNodes[til];
// remove newline text node as well
while (isBlankTextNode(next)) {
til++;
@@ -40,13 +40,16 @@ function replaceWithChildren(node) {
parent.childNodes = parent.childNodes.slice(0, idx).concat(children, parent.childNodes.slice(til));
}
module.exports = function() {
return through2.obj(function(file, enc, cb) {
var doc = dom5.parse(String(file.contents));
var head = dom5.query(doc, p.hasTagName('head'));
var body = dom5.query(doc, p.hasTagName('body'));
var vulc = dom5.query(body, p.AND(p.hasTagName('div'), p.hasAttr('by-vulcanize'), p.hasAttr('hidden')));
var charset = dom5.query(doc, p.AND(p.hasTagName('meta'), p.hasAttrValue('charset', 'UTF-8')));
class MinimalDocTransform extends Transform {
constructor() {
super({objectMode: true});
}
_transform(file, enc, cb) {
let doc = dom5.parse(String(file.contents));
let head = dom5.query(doc, p.hasTagName('head'));
let body = dom5.query(doc, p.hasTagName('body'));
let vulc = dom5.query(body, p.AND(p.hasTagName('div'), p.hasAttr('by-vulcanize'), p.hasAttr('hidden')));
let charset = dom5.query(doc, p.AND(p.hasTagName('meta'), p.hasAttrValue('charset', 'UTF-8')));
if (charset) {
dom5.remove(charset);
@@ -56,23 +59,23 @@ module.exports = function() {
replaceWithChildren(vulc);
replaceWithChildren(body);
var scripts = dom5.queryAll(doc, p.hasTagName('script'));
var collector = scripts[0];
var contents = [];
for (var i = 0, s; i < scripts.length; i++) {
let scripts = dom5.queryAll(doc, p.hasTagName('script'));
let collector = scripts[0];
let contents = [dom5.getTextContent(collector)];
for (let i = 1, s; i < scripts.length; i++) {
s = scripts[i];
if (i > 0) {
dom5.remove(s);
}
dom5.remove(s);
contents.push(dom5.getTextContent(s));
}
dom5.setTextContent(collector, contents.join(''));
var html = dom5.query(doc, p.hasTagName('html'));
let html = dom5.query(doc, p.hasTagName('html'));
replaceWithChildren(html);
file.contents = new Buffer(dom5.serialize(doc));
cb(null, file);
});
};
}
}
module.exports = () => new MinimalDocTransform();