From 086484caef8681ad9b78e5bd941ac62c5e0b3b97 Mon Sep 17 00:00:00 2001 From: Arthur Stolyar Date: Sat, 8 Apr 2017 00:50:10 +0300 Subject: [PATCH 01/54] preact/debug --- debug/debug.js | 72 ++++++++++++++++++++++++++++++++++++++++++ debug/debug.js.map | 1 + debug/index.js | 9 ++++++ debug/index.js.map | 1 + debug_src/debug.js | 78 ++++++++++++++++++++++++++++++++++++++++++++++ debug_src/index.js | 6 ++++ package.json | 8 +++-- 7 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 debug/debug.js create mode 100644 debug/debug.js.map create mode 100644 debug/index.js create mode 100644 debug/index.js.map create mode 100644 debug_src/debug.js create mode 100644 debug_src/index.js diff --git a/debug/debug.js b/debug/debug.js new file mode 100644 index 0000000000..a793e73064 --- /dev/null +++ b/debug/debug.js @@ -0,0 +1,72 @@ +'use strict'; + +var preact = require('../'); + +var original = { + h: preact.h +}; + +var config = { + undefinedComponents: true, + stringRefs: true, + arrayChildren: true +}; + +preact.h = function (nodeName, attributes) { + if (config.undefinedComponents && nodeName === void 0) { + throw new Error('Undefined component passed to preact.h()'); + } + + if (config.stringRefs && attributes && attributes.ref !== void 0 && typeof attributes.ref !== 'function') { + throw new Error('Component\'s "ref" property should be a function,' + (' but [' + typeof attributes.ref + '] passed')); + } + + if (config.arrayChildren) { + [].slice.call(arguments, 2).forEach(function (child) { + if (Array.isArray(child)) { + var hasKeys = child.every(function (child) { + return !!child.key; + }); + + if (!hasKeys) { + /* eslint-disable no-console */ + console.warn('An array is passed to a component. ' + 'Consider specifying "key" property to prevent unnecessary ' + 'component recreations. Component: \n\n' + serializeVNode(nodeName, attributes) + '\n\n'); + } + } + }); + } + + return original.h.apply(this, arguments); +}; + +module.exports.setConfig = function setConfig(params) { + Object.keys(config).forEach(function (key) { + if (key in params) { + config[key] = params[key]; + } + }); +}; + +function serializeVNode(nodeName, attributes) { + var name = undefined; + var props = undefined; + + if (typeof nodeName === 'function') { + name = nodeName.name || nodeName.displayName; + } else { + name = nodeName; + } + + if (attributes) { + props = Object.keys(attributes).map(function (attr) { + return attr + '=' + JSON.stringify(attributes[attr] + ''); + }); + } + + if (!props) { + return '<' + name + ' />'; + } + + return '<' + name + ' ' + props.join(' ') + ' />'; +} +//# sourceMappingURL=debug.js.map \ No newline at end of file diff --git a/debug/debug.js.map b/debug/debug.js.map new file mode 100644 index 0000000000..1f15b62d6e --- /dev/null +++ b/debug/debug.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../debug_src/debug.js"],"names":[],"mappings":";;AAAA,IAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;;AAE9B,IAAM,QAAQ,GAAG;AAChB,EAAC,EAAE,MAAM,CAAC,CAAC;CACX,CAAC;;AAEF,IAAM,MAAM,GAAG;AACd,oBAAmB,EAAE,IAAI;AACzB,WAAU,EAAE,IAAI;AAChB,cAAa,EAAE,IAAI;CACnB,CAAC;;AAEF,MAAM,CAAC,CAAC,GAAG,UAAS,QAAQ,EAAE,UAAU,EAAE;AACzC,KAAI,MAAM,CAAC,mBAAmB,IAAI,QAAQ,KAAK,KAAK,CAAC,EAAE;AACtD,QAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;EAC5D;;AAED,KACC,MAAM,CAAC,UAAU,IAAI,UAAU,IAC/B,UAAU,CAAC,GAAG,KAAK,KAAK,CAAC,IAAI,OAAO,UAAU,CAAC,GAAG,KAAK,UAAU,EAChE;AACD,QAAM,IAAI,KAAK,CACd,kEACS,OAAO,UAAU,CAAC,GAAG,cAAU,CACxC,CAAC;EACF;;AAED,KAAI,MAAM,CAAC,aAAa,EAAE;AACzB,IAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,UAAA,KAAK,EAAI;AAC5C,OAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACzB,QAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,UAAA,KAAK;YAAI,CAAC,CAAC,KAAK,CAAC,GAAG;KAAA,CAAC,CAAC;;AAElD,QAAI,CAAC,OAAO,EAAE;;AAEb,YAAO,CAAC,IAAI,CACX,qCAAqC,GACrC,4DAA4D,GAC5D,wCAAwC,GACxC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC,GAAG,MAAM,CAC7C,CAAC;KACF;IACD;GACD,CAAC,CAAC;EACH;;AAED,QAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;CACzC,CAAC;;AAEF,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,SAAS,SAAS,CAAC,MAAM,EAAE;AACrD,OAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,UAAA,GAAG,EAAI;AAClC,MAAI,GAAG,IAAI,MAAM,EAAE;AAClB,SAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;GAC1B;EACD,CAAC,CAAC;CACH,CAAC;;AAEF,SAAS,cAAc,CAAC,QAAQ,EAAE,UAAU,EAAE;AAC7C,KAAI,IAAI,YAAA,CAAC;AACT,KAAI,KAAK,YAAA,CAAC;;AAEV,KAAI,OAAO,QAAQ,KAAK,UAAU,EAAE;AACnC,MAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,WAAW,CAAC;EAC7C,MAAM;AACN,MAAI,GAAG,QAAQ,CAAC;EAChB;;AAED,KAAI,UAAU,EAAE;AACf,OAAK,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,UAAA,IAAI,EAAI;AAC3C,UAAU,IAAI,SAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAG;GAC1D,CAAC,CAAC;EACH;;AAED,KAAI,CAAC,KAAK,EAAE;AACX,eAAW,IAAI,SAAM;EACrB;;AAED,cAAW,IAAI,SAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,SAAM;CACxC","file":"debug.js","sourcesContent":["const preact = require('../');\n\nconst original = {\n\th: preact.h\n};\n\nconst config = {\n\tundefinedComponents: true,\n\tstringRefs: true,\n\tarrayChildren: true\n};\n\npreact.h = function(nodeName, attributes) {\n\tif (config.undefinedComponents && nodeName === void 0) {\n\t\tthrow new Error('Undefined component passed to preact.h()');\n\t}\n\n\tif (\n\t\tconfig.stringRefs && attributes &&\n\t\tattributes.ref !== void 0 && typeof attributes.ref !== 'function'\n\t) {\n\t\tthrow new Error(\n\t\t\t`Component's \"ref\" property should be a function,` +\n\t\t\t` but [${typeof attributes.ref}] passed`\n\t\t);\n\t}\n\n\tif (config.arrayChildren) {\n\t\t[].slice.call(arguments, 2).forEach(child => {\n\t\t\tif (Array.isArray(child)) {\n\t\t\t\tconst hasKeys = child.every(child => !!child.key);\n\n\t\t\t\tif (!hasKeys) {\n\t\t\t\t\t/* eslint-disable no-console */\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t'An array is passed to a component. ' +\n\t\t\t\t\t\t'Consider specifying \"key\" property to prevent unnecessary ' +\n\t\t\t\t\t\t'component recreations. Component: \\n\\n' +\n\t\t\t\t\t\tserializeVNode(nodeName, attributes) + '\\n\\n'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\treturn original.h.apply(this, arguments);\n};\n\nmodule.exports.setConfig = function setConfig(params) {\n\tObject.keys(config).forEach(key => {\n\t\tif (key in params) {\n\t\t\tconfig[key] = params[key];\n\t\t}\n\t});\n};\n\nfunction serializeVNode(nodeName, attributes) {\n\tlet name;\n\tlet props;\n\n\tif (typeof nodeName === 'function') {\n\t\tname = nodeName.name || nodeName.displayName;\n\t} else {\n\t\tname = nodeName;\n\t}\n\n\tif (attributes) {\n\t\tprops = Object.keys(attributes).map(attr => {\n\t\t\treturn `${attr}=${JSON.stringify(attributes[attr] + '')}`;\n\t\t});\n\t}\n\n\tif (!props) {\n\t\treturn `<${name} />`;\n\t}\n\n\treturn `<${name} ${props.join(' ')} />`;\n}"]} \ No newline at end of file diff --git a/debug/index.js b/debug/index.js new file mode 100644 index 0000000000..072f37996d --- /dev/null +++ b/debug/index.js @@ -0,0 +1,9 @@ +'use strict'; + +module.exports = function () {}; + +if (process.env.NODE_ENV === 'development') { + module.exports = require('./debug.js').setConfig; + require('../devtools'); +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/debug/index.js.map b/debug/index.js.map new file mode 100644 index 0000000000..3be20079db --- /dev/null +++ b/debug/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../debug_src/index.js"],"names":[],"mappings":";;AAAA,MAAM,CAAC,OAAO,GAAG,YAAM,EAAE,CAAC;;AAE1B,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;AAC1C,QAAM,CAAC,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC;AACjD,SAAO,CAAC,aAAa,CAAC,CAAC;CACxB","file":"index.js","sourcesContent":["module.exports = () => {};\n\nif (process.env.NODE_ENV === 'development') {\n module.exports = require('./debug.js').setConfig;\n require('../devtools');\n}"]} \ No newline at end of file diff --git a/debug_src/debug.js b/debug_src/debug.js new file mode 100644 index 0000000000..9f3b6b6f18 --- /dev/null +++ b/debug_src/debug.js @@ -0,0 +1,78 @@ +const preact = require('../'); + +const original = { + h: preact.h +}; + +const config = { + undefinedComponents: true, + stringRefs: true, + arrayChildren: true +}; + +preact.h = function(nodeName, attributes) { + if (config.undefinedComponents && nodeName === void 0) { + throw new Error('Undefined component passed to preact.h()'); + } + + if ( + config.stringRefs && attributes && + attributes.ref !== void 0 && typeof attributes.ref !== 'function' + ) { + throw new Error( + `Component's "ref" property should be a function,` + + ` but [${typeof attributes.ref}] passed` + ); + } + + if (config.arrayChildren) { + [].slice.call(arguments, 2).forEach(child => { + if (Array.isArray(child)) { + const hasKeys = child.every(child => !!child.key); + + if (!hasKeys) { + /* eslint-disable no-console */ + console.warn( + 'An array is passed to a component. ' + + 'Consider specifying "key" property to prevent unnecessary ' + + 'component recreations. Component: \n\n' + + serializeVNode(nodeName, attributes) + '\n\n' + ); + } + } + }); + } + + return original.h.apply(this, arguments); +}; + +module.exports.setConfig = function setConfig(params) { + Object.keys(config).forEach(key => { + if (key in params) { + config[key] = params[key]; + } + }); +}; + +function serializeVNode(nodeName, attributes) { + let name; + let props; + + if (typeof nodeName === 'function') { + name = nodeName.name || nodeName.displayName; + } else { + name = nodeName; + } + + if (attributes) { + props = Object.keys(attributes).map(attr => { + return `${attr}=${JSON.stringify(attributes[attr] + '')}`; + }); + } + + if (!props) { + return `<${name} />`; + } + + return `<${name} ${props.join(' ')} />`; +} \ No newline at end of file diff --git a/debug_src/index.js b/debug_src/index.js new file mode 100644 index 0000000000..fc68efa1a1 --- /dev/null +++ b/debug_src/index.js @@ -0,0 +1,6 @@ +module.exports = () => {}; + +if (process.env.NODE_ENV === 'development') { + module.exports = require('./debug.js').setConfig; + require('../devtools'); +} \ No newline at end of file diff --git a/package.json b/package.json index 57fb6bb129..dba13e58e6 100644 --- a/package.json +++ b/package.json @@ -7,13 +7,14 @@ "dev:main": "dist/preact.dev.js", "minified:main": "dist/preact.min.js", "scripts": { - "clean": "rimraf dist/ devtools.js devtools.js.map", + "clean": "rimraf dist/ devtools.js devtools.js.map debug/", "copy-flow-definition": "copyfiles -f src/preact.js.flow dist", "copy-typescript-definition": "copyfiles -f src/preact.d.ts dist", "build": "npm-run-all --silent clean transpile copy-flow-definition copy-typescript-definition strip optimize minify size", "transpile:main": "rollup -c config/rollup.config.js -m dist/preact.dev.js.map -n preact -o dist/preact.dev.js", "transpile:devtools": "rollup -c config/rollup.config.devtools.js -o devtools.js -m devtools.js.map", - "transpile": "npm-run-all transpile:main transpile:devtools", + "transpile:debug": "babel debug_src/ -d debug/ -s", + "transpile": "npm-run-all transpile:main transpile:devtools transpile:debug", "optimize": "uglifyjs dist/preact.dev.js -c conditionals=false,sequences=false,loops=false,join_vars=false,collapse_vars=false --pure-funcs=Object.defineProperty --mangle-props --mangle-regex=\"/^(_|normalizedNodeName|nextBase|prev[CPS]|_parentC)/\" --name-cache config/properties.json -b width=120,quote_style=3 -o dist/preact.js -p relative --in-source-map dist/preact.dev.js.map --source-map dist/preact.js.map", "minify": "uglifyjs dist/preact.js -c collapse_vars,evaluate,screw_ie8,unsafe,loops=false,keep_fargs=false,pure_getters,unused,dead_code -m -o dist/preact.min.js -p relative --in-source-map dist/preact.js.map --source-map dist/preact.min.js.map", "strip": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.dev.js", @@ -24,7 +25,7 @@ "test:karma": "karma start test/karma.conf.js --single-run", "test:mocha:watch": "npm run test:mocha -- --watch", "test:karma:watch": "npm run test:karma -- no-single-run", - "lint": "eslint devtools src test", + "lint": "eslint debug devtools src test", "prepublish": "npm run build", "smart-release": "npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish", "release": "cross-env npm run smart-release" @@ -39,6 +40,7 @@ }, "files": [ "devtools", + "debug", "src", "dist", "devtools.js", From 50b0696f9d9a240d28c9c18f88455b7a655c99f9 Mon Sep 17 00:00:00 2001 From: Arthur Stolyar Date: Sat, 8 Apr 2017 14:49:40 +0300 Subject: [PATCH 02/54] preact/debug linting --- debug_src/index.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/debug_src/index.js b/debug_src/index.js index fc68efa1a1..eb45d254f9 100644 --- a/debug_src/index.js +++ b/debug_src/index.js @@ -1,6 +1,6 @@ module.exports = () => {}; if (process.env.NODE_ENV === 'development') { - module.exports = require('./debug.js').setConfig; - require('../devtools'); + module.exports = require('./debug.js').setConfig; + require('../devtools'); } \ No newline at end of file diff --git a/package.json b/package.json index dba13e58e6..7c214a55f7 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "test:karma": "karma start test/karma.conf.js --single-run", "test:mocha:watch": "npm run test:mocha -- --watch", "test:karma:watch": "npm run test:karma -- no-single-run", - "lint": "eslint debug devtools src test", + "lint": "eslint debug_src devtools src test", "prepublish": "npm run build", "smart-release": "npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish", "release": "cross-env npm run smart-release" From 397c5cccf96707d858837f2177081ae7ddd46505 Mon Sep 17 00:00:00 2001 From: Arthur Stolyar Date: Tue, 11 Apr 2017 18:48:09 +0300 Subject: [PATCH 03/54] preact/debug rewrite --- debug.js | 30 ++++++++++++++++++ debug.js.map | 1 + debug/debug.js | 72 ------------------------------------------ debug/debug.js.map | 1 - debug/index.js | 29 ++++++++++++----- debug/index.js.map | 1 - debug_src/debug.js | 78 ---------------------------------------------- debug_src/index.js | 6 ---- package.json | 8 +++-- 9 files changed, 58 insertions(+), 168 deletions(-) create mode 100644 debug.js create mode 100644 debug.js.map delete mode 100644 debug/debug.js delete mode 100644 debug/debug.js.map delete mode 100644 debug/index.js.map delete mode 100644 debug_src/debug.js delete mode 100644 debug_src/index.js diff --git a/debug.js b/debug.js new file mode 100644 index 0000000000..77419c3318 --- /dev/null +++ b/debug.js @@ -0,0 +1,30 @@ +'use strict'; + +if (process.env.NODE_ENV === 'development') { + (function () { + var _require = require('preact'); + + var options = _require.options; + + var oldVnodeOption = options.vnode; + + options.vnode = function (vnode) { + var nodeName = vnode.nodeName; + var attributes = vnode.attributes; + + if (nodeName === void 0) { + throw new Error('Undefined component passed to preact.h()'); + } + + if (attributes && attributes.ref !== void 0 && typeof attributes.ref !== 'function') { + throw new Error('Component\'s "ref" property should be a function,' + (' but [' + typeof attributes.ref + '] passed')); + } + + return oldVnodeOption.call(this, vnode); + }; + + require('preact/devtools'); + })(); +} + +//# sourceMappingURL=debug.js.map \ No newline at end of file diff --git a/debug.js.map b/debug.js.map new file mode 100644 index 0000000000..b206f2a010 --- /dev/null +++ b/debug.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["debug/index.js"],"names":[],"mappings":";;AAAA,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;;iBACvB,OAAO,CAAC,QAAQ,CAAC;;MAA7B,OAAO,YAAP,OAAO;;AACf,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC;;AAErC,SAAO,CAAC,KAAK,GAAG,UAAS,KAAK,EAAE;OACvB,QAAQ,GAAiB,KAAK,CAA9B,QAAQ;OAAE,UAAU,GAAK,KAAK,CAApB,UAAU;;AAE5B,OAAI,QAAQ,KAAK,KAAK,CAAC,EAAE;AACxB,UAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC5D;;AAED,OAAI,UAAU,IAAI,UAAU,CAAC,GAAG,KAAK,KAAK,CAAC,IAAI,OAAO,UAAU,CAAC,GAAG,KAAK,UAAU,EACjF;AACD,UAAM,IAAI,KAAK,CACd,kEACS,OAAO,UAAU,CAAC,GAAG,cAAU,CACxC,CAAC;IACF;;AAED,UAAO,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;GACxC,CAAC;;AAEF,SAAO,CAAC,iBAAiB,CAAC,CAAC;;CAC3B","file":"debug.js","sourcesContent":["if (process.env.NODE_ENV === 'development') {\n\tconst { options } = require('preact');\n\tconst oldVnodeOption = options.vnode;\n\n\toptions.vnode = function(vnode) {\n\t\tconst { nodeName, attributes } = vnode;\n\n\t\tif (nodeName === void 0) {\n\t\t\tthrow new Error('Undefined component passed to preact.h()');\n\t\t}\n\n\t\tif (attributes && attributes.ref !== void 0 && typeof attributes.ref !== 'function'\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Component's \"ref\" property should be a function,` +\n\t\t\t\t` but [${typeof attributes.ref}] passed`\n\t\t\t);\n\t\t}\n\n\t\treturn oldVnodeOption.call(this, vnode);\n\t};\n\n\trequire('preact/devtools');\n}"]} \ No newline at end of file diff --git a/debug/debug.js b/debug/debug.js deleted file mode 100644 index a793e73064..0000000000 --- a/debug/debug.js +++ /dev/null @@ -1,72 +0,0 @@ -'use strict'; - -var preact = require('../'); - -var original = { - h: preact.h -}; - -var config = { - undefinedComponents: true, - stringRefs: true, - arrayChildren: true -}; - -preact.h = function (nodeName, attributes) { - if (config.undefinedComponents && nodeName === void 0) { - throw new Error('Undefined component passed to preact.h()'); - } - - if (config.stringRefs && attributes && attributes.ref !== void 0 && typeof attributes.ref !== 'function') { - throw new Error('Component\'s "ref" property should be a function,' + (' but [' + typeof attributes.ref + '] passed')); - } - - if (config.arrayChildren) { - [].slice.call(arguments, 2).forEach(function (child) { - if (Array.isArray(child)) { - var hasKeys = child.every(function (child) { - return !!child.key; - }); - - if (!hasKeys) { - /* eslint-disable no-console */ - console.warn('An array is passed to a component. ' + 'Consider specifying "key" property to prevent unnecessary ' + 'component recreations. Component: \n\n' + serializeVNode(nodeName, attributes) + '\n\n'); - } - } - }); - } - - return original.h.apply(this, arguments); -}; - -module.exports.setConfig = function setConfig(params) { - Object.keys(config).forEach(function (key) { - if (key in params) { - config[key] = params[key]; - } - }); -}; - -function serializeVNode(nodeName, attributes) { - var name = undefined; - var props = undefined; - - if (typeof nodeName === 'function') { - name = nodeName.name || nodeName.displayName; - } else { - name = nodeName; - } - - if (attributes) { - props = Object.keys(attributes).map(function (attr) { - return attr + '=' + JSON.stringify(attributes[attr] + ''); - }); - } - - if (!props) { - return '<' + name + ' />'; - } - - return '<' + name + ' ' + props.join(' ') + ' />'; -} -//# sourceMappingURL=debug.js.map \ No newline at end of file diff --git a/debug/debug.js.map b/debug/debug.js.map deleted file mode 100644 index 1f15b62d6e..0000000000 --- a/debug/debug.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["../debug_src/debug.js"],"names":[],"mappings":";;AAAA,IAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;;AAE9B,IAAM,QAAQ,GAAG;AAChB,EAAC,EAAE,MAAM,CAAC,CAAC;CACX,CAAC;;AAEF,IAAM,MAAM,GAAG;AACd,oBAAmB,EAAE,IAAI;AACzB,WAAU,EAAE,IAAI;AAChB,cAAa,EAAE,IAAI;CACnB,CAAC;;AAEF,MAAM,CAAC,CAAC,GAAG,UAAS,QAAQ,EAAE,UAAU,EAAE;AACzC,KAAI,MAAM,CAAC,mBAAmB,IAAI,QAAQ,KAAK,KAAK,CAAC,EAAE;AACtD,QAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;EAC5D;;AAED,KACC,MAAM,CAAC,UAAU,IAAI,UAAU,IAC/B,UAAU,CAAC,GAAG,KAAK,KAAK,CAAC,IAAI,OAAO,UAAU,CAAC,GAAG,KAAK,UAAU,EAChE;AACD,QAAM,IAAI,KAAK,CACd,kEACS,OAAO,UAAU,CAAC,GAAG,cAAU,CACxC,CAAC;EACF;;AAED,KAAI,MAAM,CAAC,aAAa,EAAE;AACzB,IAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,UAAA,KAAK,EAAI;AAC5C,OAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACzB,QAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,UAAA,KAAK;YAAI,CAAC,CAAC,KAAK,CAAC,GAAG;KAAA,CAAC,CAAC;;AAElD,QAAI,CAAC,OAAO,EAAE;;AAEb,YAAO,CAAC,IAAI,CACX,qCAAqC,GACrC,4DAA4D,GAC5D,wCAAwC,GACxC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC,GAAG,MAAM,CAC7C,CAAC;KACF;IACD;GACD,CAAC,CAAC;EACH;;AAED,QAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;CACzC,CAAC;;AAEF,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,SAAS,SAAS,CAAC,MAAM,EAAE;AACrD,OAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,UAAA,GAAG,EAAI;AAClC,MAAI,GAAG,IAAI,MAAM,EAAE;AAClB,SAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;GAC1B;EACD,CAAC,CAAC;CACH,CAAC;;AAEF,SAAS,cAAc,CAAC,QAAQ,EAAE,UAAU,EAAE;AAC7C,KAAI,IAAI,YAAA,CAAC;AACT,KAAI,KAAK,YAAA,CAAC;;AAEV,KAAI,OAAO,QAAQ,KAAK,UAAU,EAAE;AACnC,MAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,WAAW,CAAC;EAC7C,MAAM;AACN,MAAI,GAAG,QAAQ,CAAC;EAChB;;AAED,KAAI,UAAU,EAAE;AACf,OAAK,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,UAAA,IAAI,EAAI;AAC3C,UAAU,IAAI,SAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAG;GAC1D,CAAC,CAAC;EACH;;AAED,KAAI,CAAC,KAAK,EAAE;AACX,eAAW,IAAI,SAAM;EACrB;;AAED,cAAW,IAAI,SAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,SAAM;CACxC","file":"debug.js","sourcesContent":["const preact = require('../');\n\nconst original = {\n\th: preact.h\n};\n\nconst config = {\n\tundefinedComponents: true,\n\tstringRefs: true,\n\tarrayChildren: true\n};\n\npreact.h = function(nodeName, attributes) {\n\tif (config.undefinedComponents && nodeName === void 0) {\n\t\tthrow new Error('Undefined component passed to preact.h()');\n\t}\n\n\tif (\n\t\tconfig.stringRefs && attributes &&\n\t\tattributes.ref !== void 0 && typeof attributes.ref !== 'function'\n\t) {\n\t\tthrow new Error(\n\t\t\t`Component's \"ref\" property should be a function,` +\n\t\t\t` but [${typeof attributes.ref}] passed`\n\t\t);\n\t}\n\n\tif (config.arrayChildren) {\n\t\t[].slice.call(arguments, 2).forEach(child => {\n\t\t\tif (Array.isArray(child)) {\n\t\t\t\tconst hasKeys = child.every(child => !!child.key);\n\n\t\t\t\tif (!hasKeys) {\n\t\t\t\t\t/* eslint-disable no-console */\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t'An array is passed to a component. ' +\n\t\t\t\t\t\t'Consider specifying \"key\" property to prevent unnecessary ' +\n\t\t\t\t\t\t'component recreations. Component: \\n\\n' +\n\t\t\t\t\t\tserializeVNode(nodeName, attributes) + '\\n\\n'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\treturn original.h.apply(this, arguments);\n};\n\nmodule.exports.setConfig = function setConfig(params) {\n\tObject.keys(config).forEach(key => {\n\t\tif (key in params) {\n\t\t\tconfig[key] = params[key];\n\t\t}\n\t});\n};\n\nfunction serializeVNode(nodeName, attributes) {\n\tlet name;\n\tlet props;\n\n\tif (typeof nodeName === 'function') {\n\t\tname = nodeName.name || nodeName.displayName;\n\t} else {\n\t\tname = nodeName;\n\t}\n\n\tif (attributes) {\n\t\tprops = Object.keys(attributes).map(attr => {\n\t\t\treturn `${attr}=${JSON.stringify(attributes[attr] + '')}`;\n\t\t});\n\t}\n\n\tif (!props) {\n\t\treturn `<${name} />`;\n\t}\n\n\treturn `<${name} ${props.join(' ')} />`;\n}"]} \ No newline at end of file diff --git a/debug/index.js b/debug/index.js index 072f37996d..ca24b48aa6 100644 --- a/debug/index.js +++ b/debug/index.js @@ -1,9 +1,24 @@ -'use strict'; +if (process.env.NODE_ENV === 'development') { + const { options } = require('preact'); + const oldVnodeOption = options.vnode; -module.exports = function () {}; + options.vnode = function(vnode) { + const { nodeName, attributes } = vnode; -if (process.env.NODE_ENV === 'development') { - module.exports = require('./debug.js').setConfig; - require('../devtools'); -} -//# sourceMappingURL=index.js.map \ No newline at end of file + if (nodeName === void 0) { + throw new Error('Undefined component passed to preact.h()'); + } + + if (attributes && attributes.ref !== void 0 && typeof attributes.ref !== 'function' + ) { + throw new Error( + `Component's "ref" property should be a function,` + + ` but [${typeof attributes.ref}] passed` + ); + } + + return oldVnodeOption.call(this, vnode); + }; + + require('preact/devtools'); +} \ No newline at end of file diff --git a/debug/index.js.map b/debug/index.js.map deleted file mode 100644 index 3be20079db..0000000000 --- a/debug/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["../debug_src/index.js"],"names":[],"mappings":";;AAAA,MAAM,CAAC,OAAO,GAAG,YAAM,EAAE,CAAC;;AAE1B,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;AAC1C,QAAM,CAAC,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC;AACjD,SAAO,CAAC,aAAa,CAAC,CAAC;CACxB","file":"index.js","sourcesContent":["module.exports = () => {};\n\nif (process.env.NODE_ENV === 'development') {\n module.exports = require('./debug.js').setConfig;\n require('../devtools');\n}"]} \ No newline at end of file diff --git a/debug_src/debug.js b/debug_src/debug.js deleted file mode 100644 index 9f3b6b6f18..0000000000 --- a/debug_src/debug.js +++ /dev/null @@ -1,78 +0,0 @@ -const preact = require('../'); - -const original = { - h: preact.h -}; - -const config = { - undefinedComponents: true, - stringRefs: true, - arrayChildren: true -}; - -preact.h = function(nodeName, attributes) { - if (config.undefinedComponents && nodeName === void 0) { - throw new Error('Undefined component passed to preact.h()'); - } - - if ( - config.stringRefs && attributes && - attributes.ref !== void 0 && typeof attributes.ref !== 'function' - ) { - throw new Error( - `Component's "ref" property should be a function,` + - ` but [${typeof attributes.ref}] passed` - ); - } - - if (config.arrayChildren) { - [].slice.call(arguments, 2).forEach(child => { - if (Array.isArray(child)) { - const hasKeys = child.every(child => !!child.key); - - if (!hasKeys) { - /* eslint-disable no-console */ - console.warn( - 'An array is passed to a component. ' + - 'Consider specifying "key" property to prevent unnecessary ' + - 'component recreations. Component: \n\n' + - serializeVNode(nodeName, attributes) + '\n\n' - ); - } - } - }); - } - - return original.h.apply(this, arguments); -}; - -module.exports.setConfig = function setConfig(params) { - Object.keys(config).forEach(key => { - if (key in params) { - config[key] = params[key]; - } - }); -}; - -function serializeVNode(nodeName, attributes) { - let name; - let props; - - if (typeof nodeName === 'function') { - name = nodeName.name || nodeName.displayName; - } else { - name = nodeName; - } - - if (attributes) { - props = Object.keys(attributes).map(attr => { - return `${attr}=${JSON.stringify(attributes[attr] + '')}`; - }); - } - - if (!props) { - return `<${name} />`; - } - - return `<${name} ${props.join(' ')} />`; -} \ No newline at end of file diff --git a/debug_src/index.js b/debug_src/index.js deleted file mode 100644 index eb45d254f9..0000000000 --- a/debug_src/index.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = () => {}; - -if (process.env.NODE_ENV === 'development') { - module.exports = require('./debug.js').setConfig; - require('../devtools'); -} \ No newline at end of file diff --git a/package.json b/package.json index afbbcde807..fa42bed1c0 100644 --- a/package.json +++ b/package.json @@ -7,13 +7,13 @@ "dev:main": "dist/preact.dev.js", "minified:main": "dist/preact.min.js", "scripts": { - "clean": "rimraf dist/ devtools.js devtools.js.map debug/", + "clean": "rimraf dist/ devtools.js devtools.js.map debug.js debug.js.map", "copy-flow-definition": "copyfiles -f src/preact.js.flow dist", "copy-typescript-definition": "copyfiles -f src/preact.d.ts dist", "build": "npm-run-all --silent clean transpile copy-flow-definition copy-typescript-definition strip optimize minify size", "transpile:main": "rollup -c config/rollup.config.js -m dist/preact.dev.js.map -n preact -o dist/preact.dev.js", "transpile:devtools": "rollup -c config/rollup.config.devtools.js -o devtools.js -m devtools.js.map", - "transpile:debug": "babel debug_src/ -d debug/ -s", + "transpile:debug": "babel debug/ -o debug.js -s", "transpile": "npm-run-all transpile:main transpile:devtools transpile:debug", "optimize": "uglifyjs dist/preact.dev.js -c conditionals=false,sequences=false,loops=false,join_vars=false,collapse_vars=false --pure-funcs=Object.defineProperty --mangle-props --mangle-regex=\"/^(_|normalizedNodeName|nextBase|prev[CPS]|_parentC)/\" --name-cache config/properties.json -b width=120,quote_style=3 -o dist/preact.js -p relative --in-source-map dist/preact.dev.js.map --source-map dist/preact.js.map", "minify": "uglifyjs dist/preact.js -c collapse_vars,evaluate,screw_ie8,unsafe,loops=false,keep_fargs=false,pure_getters,unused,dead_code -m -o dist/preact.min.js -p relative --in-source-map dist/preact.js.map --source-map dist/preact.min.js.map", @@ -25,7 +25,7 @@ "test:karma": "karma start test/karma.conf.js --single-run", "test:mocha:watch": "npm run test:mocha -- --watch", "test:karma:watch": "npm run test:karma -- no-single-run", - "lint": "eslint debug_src devtools src test", + "lint": "eslint debug devtools src test", "prepublish": "npm run build", "smart-release": "npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish", "release": "cross-env npm run smart-release" @@ -45,6 +45,8 @@ "dist", "devtools.js", "devtools.js.map", + "debug.js", + "debug.js.map", "typings.json" ], "keywords": [ From 3e6532c2caa4efcfe52d8a6aedea1a8a2cd00b48 Mon Sep 17 00:00:00 2001 From: Arthur Stolyar Date: Tue, 11 Apr 2017 22:16:44 +0300 Subject: [PATCH 04/54] preact/debug fix code formatting --- debug/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/debug/index.js b/debug/index.js index ca24b48aa6..521baa1c28 100644 --- a/debug/index.js +++ b/debug/index.js @@ -9,7 +9,9 @@ if (process.env.NODE_ENV === 'development') { throw new Error('Undefined component passed to preact.h()'); } - if (attributes && attributes.ref !== void 0 && typeof attributes.ref !== 'function' + if ( + attributes && attributes.ref !== void 0 && + typeof attributes.ref !== 'function' ) { throw new Error( `Component's "ref" property should be a function,` + From 7956ee3c9520203e7601e516afd40506beb094f8 Mon Sep 17 00:00:00 2001 From: Arthur Stolyar Date: Sat, 15 Apr 2017 02:54:18 +0300 Subject: [PATCH 05/54] preact/debug report error on duplicate keys --- debug.js | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ debug.js.map | 2 +- debug/index.js | 61 +++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 121 insertions(+), 2 deletions(-) diff --git a/debug.js b/debug.js index 77419c3318..10cdb52354 100644 --- a/debug.js +++ b/debug.js @@ -11,6 +11,7 @@ if (process.env.NODE_ENV === 'development') { options.vnode = function (vnode) { var nodeName = vnode.nodeName; var attributes = vnode.attributes; + var children = vnode.children; if (nodeName === void 0) { throw new Error('Undefined component passed to preact.h()'); @@ -20,9 +21,68 @@ if (process.env.NODE_ENV === 'development') { throw new Error('Component\'s "ref" property should be a function,' + (' but [' + typeof attributes.ref + '] passed')); } + { + (function () { + var keys = {}; + + inspectChildren(children, function (deepChild) { + if (!deepChild) return; + + // In Preact, all keys are stored as object values, i.e. being strings + var key = deepChild.key + ''; + + if (key in keys) { + /* eslint-disable no-console */ + console.error('Following component has two or more children with the ' + 'same "key" attribute. This may cause glitches and misbehavior ' + 'in rendering process. Component: \n\n' + serializeVNode(vnode) + '\n\n'); + + // Return early to not spam the console + return true; + } + + keys[key] = true; + }); + })(); + } + return oldVnodeOption.call(this, vnode); }; + var inspectChildren = function inspectChildren(children, inspect) { + return children.some(function (child, i) { + if (Array.isArray(child)) { + return inspectChildren(child, inspect); + } + + return inspect(child, i); + }); + }; + + var serializeVNode = function serializeVNode(_ref) { + var nodeName = _ref.nodeName; + var attributes = _ref.attributes; + + var name = undefined; + var props = undefined; + + if (typeof nodeName === 'function') { + name = nodeName.name || nodeName.displayName; + } else { + name = nodeName; + } + + if (attributes) { + props = Object.keys(attributes).map(function (attr) { + return attr + '=' + JSON.stringify(attributes[attr] + ''); + }); + } + + if (!props) { + return '<' + name + ' />'; + } + + return '<' + name + ' ' + props.join(' ') + ' />'; + }; + require('preact/devtools'); })(); } diff --git a/debug.js.map b/debug.js.map index b206f2a010..4fba194809 100644 --- a/debug.js.map +++ b/debug.js.map @@ -1 +1 @@ -{"version":3,"sources":["debug/index.js"],"names":[],"mappings":";;AAAA,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;;iBACvB,OAAO,CAAC,QAAQ,CAAC;;MAA7B,OAAO,YAAP,OAAO;;AACf,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC;;AAErC,SAAO,CAAC,KAAK,GAAG,UAAS,KAAK,EAAE;OACvB,QAAQ,GAAiB,KAAK,CAA9B,QAAQ;OAAE,UAAU,GAAK,KAAK,CAApB,UAAU;;AAE5B,OAAI,QAAQ,KAAK,KAAK,CAAC,EAAE;AACxB,UAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC5D;;AAED,OAAI,UAAU,IAAI,UAAU,CAAC,GAAG,KAAK,KAAK,CAAC,IAAI,OAAO,UAAU,CAAC,GAAG,KAAK,UAAU,EACjF;AACD,UAAM,IAAI,KAAK,CACd,kEACS,OAAO,UAAU,CAAC,GAAG,cAAU,CACxC,CAAC;IACF;;AAED,UAAO,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;GACxC,CAAC;;AAEF,SAAO,CAAC,iBAAiB,CAAC,CAAC;;CAC3B","file":"debug.js","sourcesContent":["if (process.env.NODE_ENV === 'development') {\n\tconst { options } = require('preact');\n\tconst oldVnodeOption = options.vnode;\n\n\toptions.vnode = function(vnode) {\n\t\tconst { nodeName, attributes } = vnode;\n\n\t\tif (nodeName === void 0) {\n\t\t\tthrow new Error('Undefined component passed to preact.h()');\n\t\t}\n\n\t\tif (attributes && attributes.ref !== void 0 && typeof attributes.ref !== 'function'\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Component's \"ref\" property should be a function,` +\n\t\t\t\t` but [${typeof attributes.ref}] passed`\n\t\t\t);\n\t\t}\n\n\t\treturn oldVnodeOption.call(this, vnode);\n\t};\n\n\trequire('preact/devtools');\n}"]} \ No newline at end of file +{"version":3,"sources":["debug/index.js"],"names":[],"mappings":";;AAAA,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;;iBACvB,OAAO,CAAC,QAAQ,CAAC;;MAA7B,OAAO,YAAP,OAAO;;AACf,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC;;AAErC,SAAO,CAAC,KAAK,GAAG,UAAS,KAAK,EAAE;OACvB,QAAQ,GAA2B,KAAK,CAAxC,QAAQ;OAAE,UAAU,GAAe,KAAK,CAA9B,UAAU;OAAE,QAAQ,GAAK,KAAK,CAAlB,QAAQ;;AAEtC,OAAI,QAAQ,KAAK,KAAK,CAAC,EAAE;AACxB,UAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC5D;;AAED,OACC,UAAU,IAAI,UAAU,CAAC,GAAG,KAAK,KAAK,CAAC,IACvC,OAAO,UAAU,CAAC,GAAG,KAAK,UAAU,EACnC;AACD,UAAM,IAAI,KAAK,CACd,kEACS,OAAO,UAAU,CAAC,GAAG,cAAU,CACxC,CAAC;IACF;;AAED;;AACC,SAAM,IAAI,GAAG,EAAE,CAAC;;AAEhB,oBAAe,CAAC,QAAQ,EAAE,UAAC,SAAS,EAAK;AACxC,UAAI,CAAC,SAAS,EAAE,OAAO;;;AAGvB,UAAM,GAAG,GAAG,SAAS,CAAC,GAAG,GAAG,EAAE,CAAC;;AAE/B,UAAI,GAAG,IAAI,IAAI,EAAE;;AAEhB,cAAO,CAAC,KAAK,CACZ,wDAAwD,GACxD,gEAAgE,GAChE,uCAAuC,GACvC,cAAc,CAAC,KAAK,CAAC,GAAG,MAAM,CAC9B,CAAC;;;AAGF,cAAO,IAAI,CAAC;OACZ;;AAED,UAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;MACjB,CAAC,CAAC;;IACH;;AAED,UAAO,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;GACxC,CAAC;;AAEF,MAAM,eAAe,GAAG,SAAlB,eAAe,CAAI,QAAQ,EAAE,OAAO,EAAK;AAC9C,UAAO,QAAQ,CAAC,IAAI,CAAC,UAAC,KAAK,EAAE,CAAC,EAAK;AAClC,QAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACzB,YAAO,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;KACvC;;AAED,WAAO,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACzB,CAAC,CAAC;GACH,CAAC;;AAEF,MAAM,cAAc,GAAG,SAAjB,cAAc,CAAI,IAAwB,EAAK;OAA3B,QAAQ,GAAV,IAAwB,CAAtB,QAAQ;OAAE,UAAU,GAAtB,IAAwB,CAAZ,UAAU;;AAC7C,OAAI,IAAI,YAAA,CAAC;AACT,OAAI,KAAK,YAAA,CAAC;;AAEV,OAAI,OAAO,QAAQ,KAAK,UAAU,EAAE;AACnC,QAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,WAAW,CAAC;IAC7C,MAAM;AACN,QAAI,GAAG,QAAQ,CAAC;IAChB;;AAED,OAAI,UAAU,EAAE;AACf,SAAK,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,UAAA,IAAI,EAAI;AAC3C,YAAU,IAAI,SAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAG;KAC1D,CAAC,CAAC;IACH;;AAED,OAAI,CAAC,KAAK,EAAE;AACX,iBAAW,IAAI,SAAM;IACrB;;AAED,gBAAW,IAAI,SAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,SAAM;GACxC,CAAC;;AAEF,SAAO,CAAC,iBAAiB,CAAC,CAAC;;CAC3B","file":"debug.js","sourcesContent":["if (process.env.NODE_ENV === 'development') {\n\tconst { options } = require('preact');\n\tconst oldVnodeOption = options.vnode;\n\n\toptions.vnode = function(vnode) {\n\t\tconst { nodeName, attributes, children } = vnode;\n\n\t\tif (nodeName === void 0) {\n\t\t\tthrow new Error('Undefined component passed to preact.h()');\n\t\t}\n\n\t\tif (\n\t\t\tattributes && attributes.ref !== void 0 &&\n\t\t\ttypeof attributes.ref !== 'function'\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Component's \"ref\" property should be a function,` +\n\t\t\t\t` but [${typeof attributes.ref}] passed`\n\t\t\t);\n\t\t}\n\n\t\t{\n\t\t\tconst keys = {};\n\n\t\t\tinspectChildren(children, (deepChild) => {\n\t\t\t\tif (!deepChild) return;\n\n\t\t\t\t// In Preact, all keys are stored as object values, i.e. being strings\n\t\t\t\tconst key = deepChild.key + '';\n\n\t\t\t\tif (key in keys) {\n\t\t\t\t\t/* eslint-disable no-console */\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t'Following component has two or more children with the ' +\n\t\t\t\t\t\t'same \"key\" attribute. This may cause glitches and misbehavior ' +\n\t\t\t\t\t\t'in rendering process. Component: \\n\\n' +\n\t\t\t\t\t\tserializeVNode(vnode) + '\\n\\n'\n\t\t\t\t\t);\n\n\t\t\t\t\t// Return early to not spam the console\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tkeys[key] = true;\n\t\t\t});\n\t\t}\n\n\t\treturn oldVnodeOption.call(this, vnode);\n\t};\n\n\tconst inspectChildren = (children, inspect) => {\n\t\treturn children.some((child, i) => {\n\t\t\tif (Array.isArray(child)) {\n\t\t\t\treturn inspectChildren(child, inspect);\n\t\t\t}\n\n\t\t\treturn inspect(child, i);\n\t\t});\n\t};\n\n\tconst serializeVNode = ({ nodeName, attributes }) => {\n\t\tlet name;\n\t\tlet props;\n\n\t\tif (typeof nodeName === 'function') {\n\t\t\tname = nodeName.name || nodeName.displayName;\n\t\t} else {\n\t\t\tname = nodeName;\n\t\t}\n\n\t\tif (attributes) {\n\t\t\tprops = Object.keys(attributes).map(attr => {\n\t\t\t\treturn `${attr}=${JSON.stringify(attributes[attr] + '')}`;\n\t\t\t});\n\t\t}\n\n\t\tif (!props) {\n\t\t\treturn `<${name} />`;\n\t\t}\n\n\t\treturn `<${name} ${props.join(' ')} />`;\n\t};\n\n\trequire('preact/devtools');\n}"]} \ No newline at end of file diff --git a/debug/index.js b/debug/index.js index 521baa1c28..d6a3f40739 100644 --- a/debug/index.js +++ b/debug/index.js @@ -3,7 +3,7 @@ if (process.env.NODE_ENV === 'development') { const oldVnodeOption = options.vnode; options.vnode = function(vnode) { - const { nodeName, attributes } = vnode; + const { nodeName, attributes, children } = vnode; if (nodeName === void 0) { throw new Error('Undefined component passed to preact.h()'); @@ -19,8 +19,67 @@ if (process.env.NODE_ENV === 'development') { ); } + { + const keys = {}; + + inspectChildren(children, (deepChild) => { + if (!deepChild) return; + + // In Preact, all keys are stored as object values, i.e. being strings + const key = deepChild.key + ''; + + if (key in keys) { + /* eslint-disable no-console */ + console.error( + 'Following component has two or more children with the ' + + 'same "key" attribute. This may cause glitches and misbehavior ' + + 'in rendering process. Component: \n\n' + + serializeVNode(vnode) + '\n\n' + ); + + // Return early to not spam the console + return true; + } + + keys[key] = true; + }); + } + return oldVnodeOption.call(this, vnode); }; + const inspectChildren = (children, inspect) => { + return children.some((child, i) => { + if (Array.isArray(child)) { + return inspectChildren(child, inspect); + } + + return inspect(child, i); + }); + }; + + const serializeVNode = ({ nodeName, attributes }) => { + let name; + let props; + + if (typeof nodeName === 'function') { + name = nodeName.name || nodeName.displayName; + } else { + name = nodeName; + } + + if (attributes) { + props = Object.keys(attributes).map(attr => { + return `${attr}=${JSON.stringify(attributes[attr] + '')}`; + }); + } + + if (!props) { + return `<${name} />`; + } + + return `<${name} ${props.join(' ')} />`; + }; + require('preact/devtools'); } \ No newline at end of file From cb9e267b0ed39f9f8ae79805a715b2323b3c285a Mon Sep 17 00:00:00 2001 From: Arthur Stolyar Date: Sat, 15 Apr 2017 03:07:08 +0300 Subject: [PATCH 06/54] preact/debug report error on duplicate keys --- debug.js | 2 +- debug.js.map | 2 +- debug/index.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/debug.js b/debug.js index 10cdb52354..04379bdb5b 100644 --- a/debug.js +++ b/debug.js @@ -31,7 +31,7 @@ if (process.env.NODE_ENV === 'development') { // In Preact, all keys are stored as object values, i.e. being strings var key = deepChild.key + ''; - if (key in keys) { + if (keys.hasOwnProperty(key)) { /* eslint-disable no-console */ console.error('Following component has two or more children with the ' + 'same "key" attribute. This may cause glitches and misbehavior ' + 'in rendering process. Component: \n\n' + serializeVNode(vnode) + '\n\n'); diff --git a/debug.js.map b/debug.js.map index 4fba194809..1816453aad 100644 --- a/debug.js.map +++ b/debug.js.map @@ -1 +1 @@ -{"version":3,"sources":["debug/index.js"],"names":[],"mappings":";;AAAA,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;;iBACvB,OAAO,CAAC,QAAQ,CAAC;;MAA7B,OAAO,YAAP,OAAO;;AACf,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC;;AAErC,SAAO,CAAC,KAAK,GAAG,UAAS,KAAK,EAAE;OACvB,QAAQ,GAA2B,KAAK,CAAxC,QAAQ;OAAE,UAAU,GAAe,KAAK,CAA9B,UAAU;OAAE,QAAQ,GAAK,KAAK,CAAlB,QAAQ;;AAEtC,OAAI,QAAQ,KAAK,KAAK,CAAC,EAAE;AACxB,UAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC5D;;AAED,OACC,UAAU,IAAI,UAAU,CAAC,GAAG,KAAK,KAAK,CAAC,IACvC,OAAO,UAAU,CAAC,GAAG,KAAK,UAAU,EACnC;AACD,UAAM,IAAI,KAAK,CACd,kEACS,OAAO,UAAU,CAAC,GAAG,cAAU,CACxC,CAAC;IACF;;AAED;;AACC,SAAM,IAAI,GAAG,EAAE,CAAC;;AAEhB,oBAAe,CAAC,QAAQ,EAAE,UAAC,SAAS,EAAK;AACxC,UAAI,CAAC,SAAS,EAAE,OAAO;;;AAGvB,UAAM,GAAG,GAAG,SAAS,CAAC,GAAG,GAAG,EAAE,CAAC;;AAE/B,UAAI,GAAG,IAAI,IAAI,EAAE;;AAEhB,cAAO,CAAC,KAAK,CACZ,wDAAwD,GACxD,gEAAgE,GAChE,uCAAuC,GACvC,cAAc,CAAC,KAAK,CAAC,GAAG,MAAM,CAC9B,CAAC;;;AAGF,cAAO,IAAI,CAAC;OACZ;;AAED,UAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;MACjB,CAAC,CAAC;;IACH;;AAED,UAAO,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;GACxC,CAAC;;AAEF,MAAM,eAAe,GAAG,SAAlB,eAAe,CAAI,QAAQ,EAAE,OAAO,EAAK;AAC9C,UAAO,QAAQ,CAAC,IAAI,CAAC,UAAC,KAAK,EAAE,CAAC,EAAK;AAClC,QAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACzB,YAAO,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;KACvC;;AAED,WAAO,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACzB,CAAC,CAAC;GACH,CAAC;;AAEF,MAAM,cAAc,GAAG,SAAjB,cAAc,CAAI,IAAwB,EAAK;OAA3B,QAAQ,GAAV,IAAwB,CAAtB,QAAQ;OAAE,UAAU,GAAtB,IAAwB,CAAZ,UAAU;;AAC7C,OAAI,IAAI,YAAA,CAAC;AACT,OAAI,KAAK,YAAA,CAAC;;AAEV,OAAI,OAAO,QAAQ,KAAK,UAAU,EAAE;AACnC,QAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,WAAW,CAAC;IAC7C,MAAM;AACN,QAAI,GAAG,QAAQ,CAAC;IAChB;;AAED,OAAI,UAAU,EAAE;AACf,SAAK,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,UAAA,IAAI,EAAI;AAC3C,YAAU,IAAI,SAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAG;KAC1D,CAAC,CAAC;IACH;;AAED,OAAI,CAAC,KAAK,EAAE;AACX,iBAAW,IAAI,SAAM;IACrB;;AAED,gBAAW,IAAI,SAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,SAAM;GACxC,CAAC;;AAEF,SAAO,CAAC,iBAAiB,CAAC,CAAC;;CAC3B","file":"debug.js","sourcesContent":["if (process.env.NODE_ENV === 'development') {\n\tconst { options } = require('preact');\n\tconst oldVnodeOption = options.vnode;\n\n\toptions.vnode = function(vnode) {\n\t\tconst { nodeName, attributes, children } = vnode;\n\n\t\tif (nodeName === void 0) {\n\t\t\tthrow new Error('Undefined component passed to preact.h()');\n\t\t}\n\n\t\tif (\n\t\t\tattributes && attributes.ref !== void 0 &&\n\t\t\ttypeof attributes.ref !== 'function'\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Component's \"ref\" property should be a function,` +\n\t\t\t\t` but [${typeof attributes.ref}] passed`\n\t\t\t);\n\t\t}\n\n\t\t{\n\t\t\tconst keys = {};\n\n\t\t\tinspectChildren(children, (deepChild) => {\n\t\t\t\tif (!deepChild) return;\n\n\t\t\t\t// In Preact, all keys are stored as object values, i.e. being strings\n\t\t\t\tconst key = deepChild.key + '';\n\n\t\t\t\tif (key in keys) {\n\t\t\t\t\t/* eslint-disable no-console */\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t'Following component has two or more children with the ' +\n\t\t\t\t\t\t'same \"key\" attribute. This may cause glitches and misbehavior ' +\n\t\t\t\t\t\t'in rendering process. Component: \\n\\n' +\n\t\t\t\t\t\tserializeVNode(vnode) + '\\n\\n'\n\t\t\t\t\t);\n\n\t\t\t\t\t// Return early to not spam the console\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tkeys[key] = true;\n\t\t\t});\n\t\t}\n\n\t\treturn oldVnodeOption.call(this, vnode);\n\t};\n\n\tconst inspectChildren = (children, inspect) => {\n\t\treturn children.some((child, i) => {\n\t\t\tif (Array.isArray(child)) {\n\t\t\t\treturn inspectChildren(child, inspect);\n\t\t\t}\n\n\t\t\treturn inspect(child, i);\n\t\t});\n\t};\n\n\tconst serializeVNode = ({ nodeName, attributes }) => {\n\t\tlet name;\n\t\tlet props;\n\n\t\tif (typeof nodeName === 'function') {\n\t\t\tname = nodeName.name || nodeName.displayName;\n\t\t} else {\n\t\t\tname = nodeName;\n\t\t}\n\n\t\tif (attributes) {\n\t\t\tprops = Object.keys(attributes).map(attr => {\n\t\t\t\treturn `${attr}=${JSON.stringify(attributes[attr] + '')}`;\n\t\t\t});\n\t\t}\n\n\t\tif (!props) {\n\t\t\treturn `<${name} />`;\n\t\t}\n\n\t\treturn `<${name} ${props.join(' ')} />`;\n\t};\n\n\trequire('preact/devtools');\n}"]} \ No newline at end of file +{"version":3,"sources":["debug/index.js"],"names":[],"mappings":";;AAAA,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;;iBACvB,OAAO,CAAC,QAAQ,CAAC;;MAA7B,OAAO,YAAP,OAAO;;AACf,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC;;AAErC,SAAO,CAAC,KAAK,GAAG,UAAS,KAAK,EAAE;OACvB,QAAQ,GAA2B,KAAK,CAAxC,QAAQ;OAAE,UAAU,GAAe,KAAK,CAA9B,UAAU;OAAE,QAAQ,GAAK,KAAK,CAAlB,QAAQ;;AAEtC,OAAI,QAAQ,KAAK,KAAK,CAAC,EAAE;AACxB,UAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC5D;;AAED,OACC,UAAU,IAAI,UAAU,CAAC,GAAG,KAAK,KAAK,CAAC,IACvC,OAAO,UAAU,CAAC,GAAG,KAAK,UAAU,EACnC;AACD,UAAM,IAAI,KAAK,CACd,kEACS,OAAO,UAAU,CAAC,GAAG,cAAU,CACxC,CAAC;IACF;;AAED;;AACC,SAAM,IAAI,GAAG,EAAE,CAAC;;AAEhB,oBAAe,CAAC,QAAQ,EAAE,UAAC,SAAS,EAAK;AACxC,UAAI,CAAC,SAAS,EAAE,OAAO;;;AAGvB,UAAM,GAAG,GAAG,SAAS,CAAC,GAAG,GAAG,EAAE,CAAC;;AAE/B,UAAI,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;;AAE7B,cAAO,CAAC,KAAK,CACZ,wDAAwD,GACxD,gEAAgE,GAChE,uCAAuC,GACvC,cAAc,CAAC,KAAK,CAAC,GAAG,MAAM,CAC9B,CAAC;;;AAGF,cAAO,IAAI,CAAC;OACZ;;AAED,UAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;MACjB,CAAC,CAAC;;IACH;;AAED,UAAO,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;GACxC,CAAC;;AAEF,MAAM,eAAe,GAAG,SAAlB,eAAe,CAAI,QAAQ,EAAE,OAAO,EAAK;AAC9C,UAAO,QAAQ,CAAC,IAAI,CAAC,UAAC,KAAK,EAAE,CAAC,EAAK;AAClC,QAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACzB,YAAO,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;KACvC;;AAED,WAAO,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACzB,CAAC,CAAC;GACH,CAAC;;AAEF,MAAM,cAAc,GAAG,SAAjB,cAAc,CAAI,IAAwB,EAAK;OAA3B,QAAQ,GAAV,IAAwB,CAAtB,QAAQ;OAAE,UAAU,GAAtB,IAAwB,CAAZ,UAAU;;AAC7C,OAAI,IAAI,YAAA,CAAC;AACT,OAAI,KAAK,YAAA,CAAC;;AAEV,OAAI,OAAO,QAAQ,KAAK,UAAU,EAAE;AACnC,QAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,WAAW,CAAC;IAC7C,MAAM;AACN,QAAI,GAAG,QAAQ,CAAC;IAChB;;AAED,OAAI,UAAU,EAAE;AACf,SAAK,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,UAAA,IAAI,EAAI;AAC3C,YAAU,IAAI,SAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAG;KAC1D,CAAC,CAAC;IACH;;AAED,OAAI,CAAC,KAAK,EAAE;AACX,iBAAW,IAAI,SAAM;IACrB;;AAED,gBAAW,IAAI,SAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,SAAM;GACxC,CAAC;;AAEF,SAAO,CAAC,iBAAiB,CAAC,CAAC;;CAC3B","file":"debug.js","sourcesContent":["if (process.env.NODE_ENV === 'development') {\n\tconst { options } = require('preact');\n\tconst oldVnodeOption = options.vnode;\n\n\toptions.vnode = function(vnode) {\n\t\tconst { nodeName, attributes, children } = vnode;\n\n\t\tif (nodeName === void 0) {\n\t\t\tthrow new Error('Undefined component passed to preact.h()');\n\t\t}\n\n\t\tif (\n\t\t\tattributes && attributes.ref !== void 0 &&\n\t\t\ttypeof attributes.ref !== 'function'\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Component's \"ref\" property should be a function,` +\n\t\t\t\t` but [${typeof attributes.ref}] passed`\n\t\t\t);\n\t\t}\n\n\t\t{\n\t\t\tconst keys = {};\n\n\t\t\tinspectChildren(children, (deepChild) => {\n\t\t\t\tif (!deepChild) return;\n\n\t\t\t\t// In Preact, all keys are stored as object values, i.e. being strings\n\t\t\t\tconst key = deepChild.key + '';\n\n\t\t\t\tif (keys.hasOwnProperty(key)) {\n\t\t\t\t\t/* eslint-disable no-console */\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t'Following component has two or more children with the ' +\n\t\t\t\t\t\t'same \"key\" attribute. This may cause glitches and misbehavior ' +\n\t\t\t\t\t\t'in rendering process. Component: \\n\\n' +\n\t\t\t\t\t\tserializeVNode(vnode) + '\\n\\n'\n\t\t\t\t\t);\n\n\t\t\t\t\t// Return early to not spam the console\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tkeys[key] = true;\n\t\t\t});\n\t\t}\n\n\t\treturn oldVnodeOption.call(this, vnode);\n\t};\n\n\tconst inspectChildren = (children, inspect) => {\n\t\treturn children.some((child, i) => {\n\t\t\tif (Array.isArray(child)) {\n\t\t\t\treturn inspectChildren(child, inspect);\n\t\t\t}\n\n\t\t\treturn inspect(child, i);\n\t\t});\n\t};\n\n\tconst serializeVNode = ({ nodeName, attributes }) => {\n\t\tlet name;\n\t\tlet props;\n\n\t\tif (typeof nodeName === 'function') {\n\t\t\tname = nodeName.name || nodeName.displayName;\n\t\t} else {\n\t\t\tname = nodeName;\n\t\t}\n\n\t\tif (attributes) {\n\t\t\tprops = Object.keys(attributes).map(attr => {\n\t\t\t\treturn `${attr}=${JSON.stringify(attributes[attr] + '')}`;\n\t\t\t});\n\t\t}\n\n\t\tif (!props) {\n\t\t\treturn `<${name} />`;\n\t\t}\n\n\t\treturn `<${name} ${props.join(' ')} />`;\n\t};\n\n\trequire('preact/devtools');\n}"]} \ No newline at end of file diff --git a/debug/index.js b/debug/index.js index d6a3f40739..4bb2e7ee78 100644 --- a/debug/index.js +++ b/debug/index.js @@ -28,7 +28,7 @@ if (process.env.NODE_ENV === 'development') { // In Preact, all keys are stored as object values, i.e. being strings const key = deepChild.key + ''; - if (key in keys) { + if (keys.hasOwnProperty(key)) { /* eslint-disable no-console */ console.error( 'Following component has two or more children with the ' + From e53e306125e18da15b46c6c756abba6b1382e501 Mon Sep 17 00:00:00 2001 From: Brad Dunbar Date: Tue, 18 Apr 2017 20:10:22 -0400 Subject: [PATCH 07/54] Add test for rendering a component with text nodes The implementation of `h` suggests that textual children of components should not be merged. However, there is no test coverage of this behavior. --- test/shared/h.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/shared/h.js b/test/shared/h.js index 50000deecd..9a58637a07 100644 --- a/test/shared/h.js +++ b/test/shared/h.js @@ -208,4 +208,13 @@ describe('h(jsx)', () => { .with.property('children') .that.deep.equals(['onetwothree']); }); + + it('should not merge children of components', () => { + let Component = ({children}) => children; + let r = h(Component, null, 'x', 'y'); + + expect(r).to.be.an('object') + .with.property('children') + .that.deep.equals(['x', 'y']); + }); }); From 73a652692e409603ab8fe3dbcab7001843ee8a92 Mon Sep 17 00:00:00 2001 From: Arthur Stolyar Date: Sat, 22 Apr 2017 08:54:30 +0300 Subject: [PATCH 08/54] preact/debug remove build artefacts --- debug.js | 90 ---------------------------------------------------- debug.js.map | 1 - 2 files changed, 91 deletions(-) delete mode 100644 debug.js delete mode 100644 debug.js.map diff --git a/debug.js b/debug.js deleted file mode 100644 index 04379bdb5b..0000000000 --- a/debug.js +++ /dev/null @@ -1,90 +0,0 @@ -'use strict'; - -if (process.env.NODE_ENV === 'development') { - (function () { - var _require = require('preact'); - - var options = _require.options; - - var oldVnodeOption = options.vnode; - - options.vnode = function (vnode) { - var nodeName = vnode.nodeName; - var attributes = vnode.attributes; - var children = vnode.children; - - if (nodeName === void 0) { - throw new Error('Undefined component passed to preact.h()'); - } - - if (attributes && attributes.ref !== void 0 && typeof attributes.ref !== 'function') { - throw new Error('Component\'s "ref" property should be a function,' + (' but [' + typeof attributes.ref + '] passed')); - } - - { - (function () { - var keys = {}; - - inspectChildren(children, function (deepChild) { - if (!deepChild) return; - - // In Preact, all keys are stored as object values, i.e. being strings - var key = deepChild.key + ''; - - if (keys.hasOwnProperty(key)) { - /* eslint-disable no-console */ - console.error('Following component has two or more children with the ' + 'same "key" attribute. This may cause glitches and misbehavior ' + 'in rendering process. Component: \n\n' + serializeVNode(vnode) + '\n\n'); - - // Return early to not spam the console - return true; - } - - keys[key] = true; - }); - })(); - } - - return oldVnodeOption.call(this, vnode); - }; - - var inspectChildren = function inspectChildren(children, inspect) { - return children.some(function (child, i) { - if (Array.isArray(child)) { - return inspectChildren(child, inspect); - } - - return inspect(child, i); - }); - }; - - var serializeVNode = function serializeVNode(_ref) { - var nodeName = _ref.nodeName; - var attributes = _ref.attributes; - - var name = undefined; - var props = undefined; - - if (typeof nodeName === 'function') { - name = nodeName.name || nodeName.displayName; - } else { - name = nodeName; - } - - if (attributes) { - props = Object.keys(attributes).map(function (attr) { - return attr + '=' + JSON.stringify(attributes[attr] + ''); - }); - } - - if (!props) { - return '<' + name + ' />'; - } - - return '<' + name + ' ' + props.join(' ') + ' />'; - }; - - require('preact/devtools'); - })(); -} - -//# sourceMappingURL=debug.js.map \ No newline at end of file diff --git a/debug.js.map b/debug.js.map deleted file mode 100644 index 1816453aad..0000000000 --- a/debug.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["debug/index.js"],"names":[],"mappings":";;AAAA,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;;iBACvB,OAAO,CAAC,QAAQ,CAAC;;MAA7B,OAAO,YAAP,OAAO;;AACf,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC;;AAErC,SAAO,CAAC,KAAK,GAAG,UAAS,KAAK,EAAE;OACvB,QAAQ,GAA2B,KAAK,CAAxC,QAAQ;OAAE,UAAU,GAAe,KAAK,CAA9B,UAAU;OAAE,QAAQ,GAAK,KAAK,CAAlB,QAAQ;;AAEtC,OAAI,QAAQ,KAAK,KAAK,CAAC,EAAE;AACxB,UAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC5D;;AAED,OACC,UAAU,IAAI,UAAU,CAAC,GAAG,KAAK,KAAK,CAAC,IACvC,OAAO,UAAU,CAAC,GAAG,KAAK,UAAU,EACnC;AACD,UAAM,IAAI,KAAK,CACd,kEACS,OAAO,UAAU,CAAC,GAAG,cAAU,CACxC,CAAC;IACF;;AAED;;AACC,SAAM,IAAI,GAAG,EAAE,CAAC;;AAEhB,oBAAe,CAAC,QAAQ,EAAE,UAAC,SAAS,EAAK;AACxC,UAAI,CAAC,SAAS,EAAE,OAAO;;;AAGvB,UAAM,GAAG,GAAG,SAAS,CAAC,GAAG,GAAG,EAAE,CAAC;;AAE/B,UAAI,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;;AAE7B,cAAO,CAAC,KAAK,CACZ,wDAAwD,GACxD,gEAAgE,GAChE,uCAAuC,GACvC,cAAc,CAAC,KAAK,CAAC,GAAG,MAAM,CAC9B,CAAC;;;AAGF,cAAO,IAAI,CAAC;OACZ;;AAED,UAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;MACjB,CAAC,CAAC;;IACH;;AAED,UAAO,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;GACxC,CAAC;;AAEF,MAAM,eAAe,GAAG,SAAlB,eAAe,CAAI,QAAQ,EAAE,OAAO,EAAK;AAC9C,UAAO,QAAQ,CAAC,IAAI,CAAC,UAAC,KAAK,EAAE,CAAC,EAAK;AAClC,QAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACzB,YAAO,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;KACvC;;AAED,WAAO,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACzB,CAAC,CAAC;GACH,CAAC;;AAEF,MAAM,cAAc,GAAG,SAAjB,cAAc,CAAI,IAAwB,EAAK;OAA3B,QAAQ,GAAV,IAAwB,CAAtB,QAAQ;OAAE,UAAU,GAAtB,IAAwB,CAAZ,UAAU;;AAC7C,OAAI,IAAI,YAAA,CAAC;AACT,OAAI,KAAK,YAAA,CAAC;;AAEV,OAAI,OAAO,QAAQ,KAAK,UAAU,EAAE;AACnC,QAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,WAAW,CAAC;IAC7C,MAAM;AACN,QAAI,GAAG,QAAQ,CAAC;IAChB;;AAED,OAAI,UAAU,EAAE;AACf,SAAK,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,UAAA,IAAI,EAAI;AAC3C,YAAU,IAAI,SAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAG;KAC1D,CAAC,CAAC;IACH;;AAED,OAAI,CAAC,KAAK,EAAE;AACX,iBAAW,IAAI,SAAM;IACrB;;AAED,gBAAW,IAAI,SAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,SAAM;GACxC,CAAC;;AAEF,SAAO,CAAC,iBAAiB,CAAC,CAAC;;CAC3B","file":"debug.js","sourcesContent":["if (process.env.NODE_ENV === 'development') {\n\tconst { options } = require('preact');\n\tconst oldVnodeOption = options.vnode;\n\n\toptions.vnode = function(vnode) {\n\t\tconst { nodeName, attributes, children } = vnode;\n\n\t\tif (nodeName === void 0) {\n\t\t\tthrow new Error('Undefined component passed to preact.h()');\n\t\t}\n\n\t\tif (\n\t\t\tattributes && attributes.ref !== void 0 &&\n\t\t\ttypeof attributes.ref !== 'function'\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Component's \"ref\" property should be a function,` +\n\t\t\t\t` but [${typeof attributes.ref}] passed`\n\t\t\t);\n\t\t}\n\n\t\t{\n\t\t\tconst keys = {};\n\n\t\t\tinspectChildren(children, (deepChild) => {\n\t\t\t\tif (!deepChild) return;\n\n\t\t\t\t// In Preact, all keys are stored as object values, i.e. being strings\n\t\t\t\tconst key = deepChild.key + '';\n\n\t\t\t\tif (keys.hasOwnProperty(key)) {\n\t\t\t\t\t/* eslint-disable no-console */\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t'Following component has two or more children with the ' +\n\t\t\t\t\t\t'same \"key\" attribute. This may cause glitches and misbehavior ' +\n\t\t\t\t\t\t'in rendering process. Component: \\n\\n' +\n\t\t\t\t\t\tserializeVNode(vnode) + '\\n\\n'\n\t\t\t\t\t);\n\n\t\t\t\t\t// Return early to not spam the console\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tkeys[key] = true;\n\t\t\t});\n\t\t}\n\n\t\treturn oldVnodeOption.call(this, vnode);\n\t};\n\n\tconst inspectChildren = (children, inspect) => {\n\t\treturn children.some((child, i) => {\n\t\t\tif (Array.isArray(child)) {\n\t\t\t\treturn inspectChildren(child, inspect);\n\t\t\t}\n\n\t\t\treturn inspect(child, i);\n\t\t});\n\t};\n\n\tconst serializeVNode = ({ nodeName, attributes }) => {\n\t\tlet name;\n\t\tlet props;\n\n\t\tif (typeof nodeName === 'function') {\n\t\t\tname = nodeName.name || nodeName.displayName;\n\t\t} else {\n\t\t\tname = nodeName;\n\t\t}\n\n\t\tif (attributes) {\n\t\t\tprops = Object.keys(attributes).map(attr => {\n\t\t\t\treturn `${attr}=${JSON.stringify(attributes[attr] + '')}`;\n\t\t\t});\n\t\t}\n\n\t\tif (!props) {\n\t\t\treturn `<${name} />`;\n\t\t}\n\n\t\treturn `<${name} ${props.join(' ')} />`;\n\t};\n\n\trequire('preact/devtools');\n}"]} \ No newline at end of file From eef7d7010604ef900f9fe302fcacb610d12f5db4 Mon Sep 17 00:00:00 2001 From: Arthur Stolyar Date: Sat, 22 Apr 2017 08:55:07 +0300 Subject: [PATCH 09/54] preact/debug ignore debug build artefacts --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 6b81e1b5c2..40acf3f76e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ # Additional bundles /devtools.js /devtools.js.map +/debug.js +/debug.js.map From d4f55b129f01aaf0dbcc7ac1a93df3eea1ec2250 Mon Sep 17 00:00:00 2001 From: Denis Bardadym Date: Wed, 26 Apr 2017 11:31:09 +0300 Subject: [PATCH 10/54] Use build code from preact-compat --- config/rollup.config.js | 63 +++++++++++++++++++++++++---------------- package.json | 17 +++++++---- 2 files changed, 49 insertions(+), 31 deletions(-) diff --git a/config/rollup.config.js b/config/rollup.config.js index cd2810fc19..440fdc8371 100644 --- a/config/rollup.config.js +++ b/config/rollup.config.js @@ -1,28 +1,41 @@ -import nodeResolve from 'rollup-plugin-node-resolve'; -import babel from 'rollup-plugin-babel'; -import memory from 'rollup-plugin-memory'; +import fs from "fs"; +import memory from "rollup-plugin-memory"; +import buble from "rollup-plugin-buble"; +import nodeResolve from "rollup-plugin-node-resolve"; +import commonjs from "rollup-plugin-commonjs"; + +let pkg = JSON.parse(fs.readFileSync("./package.json")); + +let external = Object.keys(pkg.peerDependencies || {}).concat(Object.keys(pkg.dependencies || {})); + +let format = process.env.FORMAT === "es" ? "es" : "umd"; export default { - useStrict: true, - format: 'iife', - entry: 'src/preact.js', - plugins: [ - memory({ - path: 'src/preact.js', - contents: ` - import preact from './preact'; - if (typeof module!='undefined') module.exports = preact; - else self.preact = preact; - ` - }), - nodeResolve({ - main: true - }), - babel({ - sourceMap: true, - loose: 'all', - blacklist: ['es6.tailCall'], - exclude: 'node_modules/**' - }) - ] + entry: "src/preact.js", + sourceMap: true, + exports: format === "es" ? null : "default", + dest: format === "es" ? pkg.module : pkg.main, + format, + external, + useStrict: false, + plugins: [ + format === "umd" && + memory({ + path: "src/preact.js", + contents: "export { default } from './preact';" + }), + buble({ + objectAssign: "extend", + namedFunctionExpressions: false + }), + nodeResolve({ + jsnext: true, + main: true, + skip: external + }), + commonjs({ + include: "node_modules/**", + exclude: "**/*.css" + }) + ].filter(Boolean) }; diff --git a/package.json b/package.json index ed80ae0611..b9b36765f8 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,8 @@ "version": "8.1.0", "description": "Fast 3kb React alternative with the same ES6 API. Components & Virtual DOM.", "main": "dist/preact.js", - "jsnext:main": "src/preact.js", + "jsnext:main": "dist/preact.esm.js", + "module": "dist/preact.esm.js", "dev:main": "dist/preact.dev.js", "minified:main": "dist/preact.min.js", "scripts": { @@ -11,12 +12,15 @@ "copy-flow-definition": "copyfiles -f src/preact.js.flow dist", "copy-typescript-definition": "copyfiles -f src/preact.d.ts dist", "build": "npm-run-all --silent clean transpile copy-flow-definition copy-typescript-definition strip optimize minify size", - "transpile:main": "rollup -c config/rollup.config.js -m dist/preact.dev.js.map -n preact -o dist/preact.dev.js", + "transpile:main": "rollup --environment FORMAT:umd -c config/rollup.config.js -m dist/preact.dev.js.map -n preact -o dist/preact.dev.js", + "transpile:esm": "rollup --environment FORMAT:es -c config/rollup.config.js -m dist/preact.esm.js.map -o dist/preact.esm.js", "transpile:devtools": "rollup -c config/rollup.config.devtools.js -o devtools.js -m devtools.js.map", - "transpile": "npm-run-all transpile:main transpile:devtools", + "transpile": "npm-run-all transpile:main transpile:devtools transpile:esm", "optimize": "uglifyjs dist/preact.dev.js -c conditionals=false,sequences=false,loops=false,join_vars=false,collapse_vars=false --pure-funcs=Object.defineProperty --mangle-props --mangle-regex=\"/^(_|normalizedNodeName|nextBase|prev[CPS]|_parentC)/\" --name-cache config/properties.json -b width=120,quote_style=3 -o dist/preact.js -p relative --in-source-map dist/preact.dev.js.map --source-map dist/preact.js.map", "minify": "uglifyjs dist/preact.js -c collapse_vars,evaluate,screw_ie8,unsafe,loops=false,keep_fargs=false,pure_getters,unused,dead_code -m -o dist/preact.min.js -p relative --in-source-map dist/preact.js.map --source-map dist/preact.min.js.map", - "strip": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.dev.js", + "strip:main": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.dev.js", + "strip:esm": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.esm.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.esm.js", + "strip": "npm-run-all strip:main strip:esm", "size": "node -e \"process.stdout.write('gzip size: ')\" && gzip-size dist/preact.min.js", "test": "npm-run-all lint --parallel test:mocha test:karma test:ts", "test:ts": "tsc -p test/ts/", @@ -96,8 +100,9 @@ "npm-run-all": "^4.0.0", "phantomjs-prebuilt": "^2.1.7", "rimraf": "^2.5.3", - "rollup": "^0.40.0", - "rollup-plugin-babel": "^1.0.0", + "rollup": "^0.41.0", + "rollup-plugin-buble": "^0.15.0", + "rollup-plugin-commonjs": "^8.0.2", "rollup-plugin-memory": "^2.0.0", "rollup-plugin-node-resolve": "^2.0.0", "sinon": "^1.17.4", From 9d14988bc18a5da8605108bdba10140cfdae19a0 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Wed, 26 Apr 2017 07:56:12 -0400 Subject: [PATCH 11/54] ES Module build This adds an ES module build into `dist/preact.esm.js` as [described here](https://github.com/developit/preact/issues/670#issuecomment-297201594). Closes #670 --- config/rollup.config.esm.js | 19 +++++++++++++++++++ package.json | 3 ++- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 config/rollup.config.esm.js diff --git a/config/rollup.config.esm.js b/config/rollup.config.esm.js new file mode 100644 index 0000000000..a64fd9c4b6 --- /dev/null +++ b/config/rollup.config.esm.js @@ -0,0 +1,19 @@ +import nodeResolve from 'rollup-plugin-node-resolve'; +import babel from 'rollup-plugin-babel'; + +export default { + useStrict: true, + format: 'es', + entry: 'src/preact.js', + plugins: [ + nodeResolve({ + main: true + }), + babel({ + sourceMap: true, + loose: 'all', + blacklist: ['es6.tailCall'], + exclude: 'node_modules/**' + }) + ] +}; diff --git a/package.json b/package.json index ed80ae0611..c474a80c61 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "build": "npm-run-all --silent clean transpile copy-flow-definition copy-typescript-definition strip optimize minify size", "transpile:main": "rollup -c config/rollup.config.js -m dist/preact.dev.js.map -n preact -o dist/preact.dev.js", "transpile:devtools": "rollup -c config/rollup.config.devtools.js -o devtools.js -m devtools.js.map", - "transpile": "npm-run-all transpile:main transpile:devtools", + "transpile:esm": "rollup -c config/rollup.config.esm.js -m dist/preact.esm.js.map -o dist/preact.esm.js", + "transpile": "npm-run-all transpile:main transpile:devtools transpile:esm", "optimize": "uglifyjs dist/preact.dev.js -c conditionals=false,sequences=false,loops=false,join_vars=false,collapse_vars=false --pure-funcs=Object.defineProperty --mangle-props --mangle-regex=\"/^(_|normalizedNodeName|nextBase|prev[CPS]|_parentC)/\" --name-cache config/properties.json -b width=120,quote_style=3 -o dist/preact.js -p relative --in-source-map dist/preact.dev.js.map --source-map dist/preact.js.map", "minify": "uglifyjs dist/preact.js -c collapse_vars,evaluate,screw_ie8,unsafe,loops=false,keep_fargs=false,pure_getters,unused,dead_code -m -o dist/preact.min.js -p relative --in-source-map dist/preact.js.map --source-map dist/preact.min.js.map", "strip": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.dev.js", From cae8167ca8bf89a244a3f2513c0ac3aef88482f0 Mon Sep 17 00:00:00 2001 From: Garth Poitras Date: Tue, 2 May 2017 09:10:40 -0400 Subject: [PATCH 12/54] Babel 6 upgrade --- .babelrc | 9 +++++++++ config/rollup.config.devtools.js | 9 ++++----- config/rollup.config.js | 6 +++--- package.json | 15 ++++++++------- test/karma.conf.js | 8 +------- 5 files changed, 25 insertions(+), 22 deletions(-) create mode 100644 .babelrc diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000000..3a0cd0a8ea --- /dev/null +++ b/.babelrc @@ -0,0 +1,9 @@ +{ + "presets": [ + ["es2015", { "loose": true }] + ], + "plugins": [ + "transform-object-rest-spread", + ["transform-react-jsx", { "pragma": "preact.h" }] + ] +} diff --git a/config/rollup.config.devtools.js b/config/rollup.config.devtools.js index 1fb90b2384..0069d9cbef 100644 --- a/config/rollup.config.devtools.js +++ b/config/rollup.config.devtools.js @@ -1,4 +1,3 @@ -import nodeResolve from 'rollup-plugin-node-resolve'; import babel from 'rollup-plugin-babel'; export default { @@ -12,9 +11,9 @@ export default { plugins: [ babel({ sourceMap: true, - loose: 'all', - blacklist: ['es6.tailCall'], - exclude: 'node_modules/**' + exclude: 'node_modules/**', + babelrc: false, + presets: [ ['es2015', { loose: true, modules: false }] ] }) ] -} +}; diff --git a/config/rollup.config.js b/config/rollup.config.js index cd2810fc19..c51bc34c2e 100644 --- a/config/rollup.config.js +++ b/config/rollup.config.js @@ -20,9 +20,9 @@ export default { }), babel({ sourceMap: true, - loose: 'all', - blacklist: ['es6.tailCall'], - exclude: 'node_modules/**' + exclude: 'node_modules/**', + babelrc: false, + presets: [ ['es2015', { loose: true, modules: false }] ] }) ] }; diff --git a/package.json b/package.json index 22cbd20e4a..73e31df9d1 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "size": "node -e \"process.stdout.write('gzip size: ')\" && gzip-size dist/preact.min.js", "test": "npm-run-all lint --parallel test:mocha test:karma test:ts", "test:ts": "tsc -p test/ts/", - "test:mocha": "mocha --recursive --compilers js:babel/register test/shared test/node", + "test:mocha": "mocha --recursive --require babel-register test/shared test/node", "test:karma": "karma start test/karma.conf.js --single-run", "test:mocha:watch": "npm run test:mocha -- --watch", "test:karma:watch": "npm run test:karma -- no-single-run", @@ -63,11 +63,12 @@ }, "homepage": "https://github.com/developit/preact", "devDependencies": { - "babel": "^5.8.23", - "babel-core": "^5.8.24", - "babel-eslint": "^6.1.0", - "babel-loader": "^5.3.2", - "babel-runtime": "^5.8.24", + "babel-core": "^6.24.1", + "babel-eslint": "^7.2.3", + "babel-loader": "^7.0.0", + "babel-plugin-transform-object-rest-spread": "^6.23.0", + "babel-plugin-transform-react-jsx": "^6.24.1", + "babel-preset-es2015": "^6.24.1", "chai": "^3.4.1", "copyfiles": "^1.0.0", "core-js": "^2.4.1", @@ -97,7 +98,7 @@ "phantomjs-prebuilt": "^2.1.7", "rimraf": "^2.5.3", "rollup": "^0.40.0", - "rollup-plugin-babel": "^1.0.0", + "rollup-plugin-babel": "^2.7.1", "rollup-plugin-memory": "^2.0.0", "rollup-plugin-node-resolve": "^2.0.0", "sinon": "^1.17.4", diff --git a/test/karma.conf.js b/test/karma.conf.js index f11ad1f24c..f967ffffdd 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -116,13 +116,7 @@ module.exports = function(config) { enforce: 'pre', test: /\.jsx?$/, exclude: /node_modules/, - loader: 'babel-loader', - options: { - loose: 'all', - blacklist: ['es6.tailCall'], - comments: false, - compact: true - } + loader: 'babel-loader' }, /* Only Instrument our source files for coverage */ coverage ? { From d678932f7069f03c6b0c9af82b78000dcb469893 Mon Sep 17 00:00:00 2001 From: Garth Poitras Date: Tue, 2 May 2017 09:57:06 -0400 Subject: [PATCH 13/54] Same output as babel 5 via babel-preset-env --- .babelrc | 8 +++++++- config/rollup.config.devtools.js | 11 ++++++++++- config/rollup.config.js | 11 ++++++++++- package.json | 2 +- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/.babelrc b/.babelrc index 3a0cd0a8ea..ec27390457 100644 --- a/.babelrc +++ b/.babelrc @@ -1,6 +1,12 @@ { "presets": [ - ["es2015", { "loose": true }] + ["env", { + "loose": true, + "exclude": ["transform-es2015-typeof-symbol"], + "targets": { + "browsers": ["last 2 versions", "IE >= 9"] + } + }] ], "plugins": [ "transform-object-rest-spread", diff --git a/config/rollup.config.devtools.js b/config/rollup.config.devtools.js index 0069d9cbef..60e93356be 100644 --- a/config/rollup.config.devtools.js +++ b/config/rollup.config.devtools.js @@ -13,7 +13,16 @@ export default { sourceMap: true, exclude: 'node_modules/**', babelrc: false, - presets: [ ['es2015', { loose: true, modules: false }] ] + presets: [ + ['env', { + modules: false, + loose: true, + exclude: ['transform-es2015-typeof-symbol'], + targets: { + browsers: ['last 2 versions', 'IE >= 9'] + } + }] + ] }) ] }; diff --git a/config/rollup.config.js b/config/rollup.config.js index c51bc34c2e..fe0581139c 100644 --- a/config/rollup.config.js +++ b/config/rollup.config.js @@ -22,7 +22,16 @@ export default { sourceMap: true, exclude: 'node_modules/**', babelrc: false, - presets: [ ['es2015', { loose: true, modules: false }] ] + presets: [ + ['env', { + modules: false, + loose: true, + exclude: ['transform-es2015-typeof-symbol'], + targets: { + browsers: ['last 2 versions', 'IE >= 9'] + } + }] + ] }) ] }; diff --git a/package.json b/package.json index 73e31df9d1..2097becae3 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "babel-loader": "^7.0.0", "babel-plugin-transform-object-rest-spread": "^6.23.0", "babel-plugin-transform-react-jsx": "^6.24.1", - "babel-preset-es2015": "^6.24.1", + "babel-preset-env": "^1.4.0", "chai": "^3.4.1", "copyfiles": "^1.0.0", "core-js": "^2.4.1", From 6405efec31b8f27b547ad62bbdeaf5b82ae21bec Mon Sep 17 00:00:00 2001 From: Garth Poitras Date: Tue, 2 May 2017 10:10:30 -0400 Subject: [PATCH 14/54] don't need jsx pragma --- .babelrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.babelrc b/.babelrc index ec27390457..d42301f46b 100644 --- a/.babelrc +++ b/.babelrc @@ -10,6 +10,6 @@ ], "plugins": [ "transform-object-rest-spread", - ["transform-react-jsx", { "pragma": "preact.h" }] + "transform-react-jsx" ] } From 2354686a94a6c34cb051573e3870fe596b840ca1 Mon Sep 17 00:00:00 2001 From: Garth Poitras Date: Wed, 3 May 2017 00:04:53 -0400 Subject: [PATCH 15/54] restore karma babel options to fix code coverage --- test/karma.conf.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/karma.conf.js b/test/karma.conf.js index f967ffffdd..b5d1a34fe5 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -116,7 +116,11 @@ module.exports = function(config) { enforce: 'pre', test: /\.jsx?$/, exclude: /node_modules/, - loader: 'babel-loader' + loader: 'babel-loader', + options: { + comments: false, + compact: true + } }, /* Only Instrument our source files for coverage */ coverage ? { From 6b09fa9e79bf10f30a39bb0e5b65eb610c882309 Mon Sep 17 00:00:00 2001 From: Garth Poitras Date: Wed, 3 May 2017 12:28:46 -0400 Subject: [PATCH 16/54] Add codemod for restoring var names transformed by let block scoping --- config/codemod-let-name.js | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 config/codemod-let-name.js diff --git a/config/codemod-let-name.js b/config/codemod-let-name.js new file mode 100644 index 0000000000..e04d3f41e0 --- /dev/null +++ b/config/codemod-let-name.js @@ -0,0 +1,12 @@ +/** + * Restores var names transformed by babel's let block scoping + */ +export default (file, api) => { + let j = api.jscodeshift; + let code = j(file.source); + + code.findVariableDeclarators().filter(d => /^_i/.test(d.value.id.name)).renameTo('i'); + code.findVariableDeclarators('_key').renameTo('key'); + + return code.toSource({ quote: 'single' }); +}; diff --git a/package.json b/package.json index 2097becae3..d0966c4f12 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "transpile": "npm-run-all transpile:main transpile:devtools", "optimize": "uglifyjs dist/preact.dev.js -c conditionals=false,sequences=false,loops=false,join_vars=false,collapse_vars=false --pure-funcs=Object.defineProperty --mangle-props --mangle-regex=\"/^(_|normalizedNodeName|nextBase|prev[CPS]|_parentC)/\" --name-cache config/properties.json -b width=120,quote_style=3 -o dist/preact.js -p relative --in-source-map dist/preact.dev.js.map --source-map dist/preact.js.map", "minify": "uglifyjs dist/preact.js -c collapse_vars,evaluate,screw_ie8,unsafe,loops=false,keep_fargs=false,pure_getters,unused,dead_code -m -o dist/preact.min.js -p relative --in-source-map dist/preact.js.map --source-map dist/preact.min.js.map", - "strip": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.dev.js", + "strip": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-let-name.js dist/preact.dev.js", "size": "node -e \"process.stdout.write('gzip size: ')\" && gzip-size dist/preact.min.js", "test": "npm-run-all lint --parallel test:mocha test:karma test:ts", "test:ts": "tsc -p test/ts/", From 3f38738eb300a550a51088e3f6992c92685e89a5 Mon Sep 17 00:00:00 2001 From: Benedikt Meurer Date: Tue, 16 May 2017 20:45:28 +0200 Subject: [PATCH 17/54] Use typeof to test booleaness. Using the typeof check is shorter, and in case of Chrome also faster at this point as shown in https://esbench.com/bench/591b46f299634800a03481f8 (upstream bug to address this at http://crbug.com/v8/6403). I personally also find the typeof version more readable, as it makes it clear what the intent was. --- src/h.js | 2 +- src/vdom/diff.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/h.js b/src/h.js index b8dbd9480b..457481f1a8 100644 --- a/src/h.js +++ b/src/h.js @@ -25,7 +25,7 @@ export function h(nodeName, attributes) { for (i=child.length; i--; ) stack.push(child[i]); } else { - if (child===true || child===false) child = null; + if (typeof child==='boolean') child = null; if ((simple = typeof nodeName!=='function')) { if (child==null) child = ''; diff --git a/src/vdom/diff.js b/src/vdom/diff.js index bc421ebdcf..986a685e83 100644 --- a/src/vdom/diff.js +++ b/src/vdom/diff.js @@ -66,7 +66,7 @@ function idiff(dom, vnode, context, mountAll, componentRoot) { prevSvgMode = isSvgMode; // empty values (null, undefined, booleans) render as empty Text nodes - if (vnode==null || vnode===false || vnode===true) vnode = ''; + if (vnode==null || typeof vnode==='boolean') vnode = ''; // Fast case: Strings & Numbers create/update Text nodes. From 467f41f0672c11c80001a8aa7b5417173c9ba15b Mon Sep 17 00:00:00 2001 From: Benedikt Meurer Date: Tue, 16 May 2017 20:50:19 +0200 Subject: [PATCH 18/54] Load vnode.nodeName only once. Since idiff is invoked on all kinds of virtual nodes, the property access vnode.nodeName is usually megamorphic in any realistic workload, so it's better for the JS engine to load the property only once. Also apply the String constructor only once to the vnode.nodeName, because the String constructor can have arbitrary side-effects (since it can call out to Symbol.toPrimitive, valueOf or toString), and thus requires magic on the engines' side to optimize this away, which doesn't always kick in (and is costly). --- src/vdom/diff.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/vdom/diff.js b/src/vdom/diff.js index bc421ebdcf..42d81de90a 100644 --- a/src/vdom/diff.js +++ b/src/vdom/diff.js @@ -94,18 +94,20 @@ function idiff(dom, vnode, context, mountAll, componentRoot) { // If the VNode represents a Component, perform a component diff: - if (typeof vnode.nodeName==='function') { + let vnodeName = vnode.nodeName; + if (typeof vnodeName==='function') { return buildComponentFromVNode(dom, vnode, context, mountAll); } // Tracks entering and exiting SVG namespace when descending through the tree. - isSvgMode = vnode.nodeName==='svg' ? true : vnode.nodeName==='foreignObject' ? false : isSvgMode; + isSvgMode = vnodeName==='svg' ? true : vnodeName==='foreignObject' ? false : isSvgMode; // If there's no existing element or it's the wrong type, create a new one: - if (!dom || !isNamedNode(dom, String(vnode.nodeName))) { - out = createNode(String(vnode.nodeName), isSvgMode); + vnodeName = String(vnodeName); + if (!dom || !isNamedNode(dom, vnodeName)) { + out = createNode(vnodeName, isSvgMode); if (dom) { // move children into the replacement node From b06ff846d7a15b21296fe9f0e409f5e148bf4b3b Mon Sep 17 00:00:00 2001 From: cotttpan Date: Thu, 18 May 2017 10:55:10 +0900 Subject: [PATCH 19/54] TS: Correct 'onDoubleClick' to 'onDblClick' --- src/preact.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/preact.d.ts b/src/preact.d.ts index cf9b626ccb..84f37fcad3 100644 --- a/src/preact.d.ts +++ b/src/preact.d.ts @@ -419,7 +419,7 @@ declare namespace JSX { // MouseEvents onClick?:MouseEventHandler; onContextMenu?:MouseEventHandler; - onDoubleClick?:MouseEventHandler; + onDblClick?: MouseEventHandler; onDrag?:DragEventHandler; onDragEnd?:DragEventHandler; onDragEnter?:DragEventHandler; From a260174358be3be4c90278cd4a46c4717fcd6eaf Mon Sep 17 00:00:00 2001 From: Damien Maillard Date: Thu, 25 May 2017 03:15:08 +0200 Subject: [PATCH 20/54] Fix attributes diff on DOM node (#677) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix render attributes diff with a DOM node * Add another demo the list (#681) Added the Periodic Weather PWA with the lastest of Preact to the list! ☀️ --- src/vdom/diff.js | 10 +++++++++- test/browser/render.js | 16 +++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/vdom/diff.js b/src/vdom/diff.js index 2382707c48..561c016993 100644 --- a/src/vdom/diff.js +++ b/src/vdom/diff.js @@ -123,9 +123,17 @@ function idiff(dom, vnode, context, mountAll, componentRoot) { let fc = out.firstChild, - props = out[ATTR_KEY] || (out[ATTR_KEY] = {}), + props, vchildren = vnode.children; + if (out[ATTR_KEY]) { + props = out[ATTR_KEY]; + } + else { + props = out[ATTR_KEY] = {}; + for (let a=out.attributes, i=a.length; i--; ) props[a[i].name] = a[i].value; + } + // Optimization: fast-path for elements containing a single TextNode: if (!hydrating && vchildren && vchildren.length===1 && typeof vchildren[0]==='string' && fc!=null && fc.splitText!==undefined && fc.nextSibling==null) { if (fc.nodeValue!=vchildren[0]) { diff --git a/test/browser/render.js b/test/browser/render.js index 69ca264a4b..bd76b880b3 100644 --- a/test/browser/render.js +++ b/test/browser/render.js @@ -406,7 +406,7 @@ describe('render()', () => { expect(scratch.innerHTML, 're-set').to.equal('
'+html+'
'); }); - it( 'should apply proper mutation for VNodes with dangerouslySetInnerHTML attr', () => { + it('should apply proper mutation for VNodes with dangerouslySetInnerHTML attr', () => { class Thing extends Component { constructor(props, context) { super(props, context); @@ -496,6 +496,20 @@ describe('render()', () => { expect(scratch.firstChild.lastChild).to.equal(a); }); + it('should not merge attributes with node created by the DOM', () => { + const html = (htmlString) => { + const div = document.createElement('div'); + div.innerHTML = htmlString; + return div.firstChild; + }; + + const DOMElement = html`
`; + const preactElement =
; + + render(preactElement, scratch, DOMElement); + expect(scratch).to.have.property('innerHTML', '
'); + }); + it('should skip non-preact elements', () => { class Foo extends Component { render() { From 5a5cc80b125262d233235c4376fc3e512aa9a19e Mon Sep 17 00:00:00 2001 From: Garth Poitras Date: Tue, 30 May 2017 17:33:35 -0400 Subject: [PATCH 21/54] Add babel-cli for transpile:debug script. Freshen babel deps --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d50c718bfa..bf39424cca 100644 --- a/package.json +++ b/package.json @@ -67,12 +67,13 @@ }, "homepage": "https://github.com/developit/preact", "devDependencies": { + "babel-cli": "^6.24.1", "babel-core": "^6.24.1", "babel-eslint": "^7.2.3", "babel-loader": "^7.0.0", "babel-plugin-transform-object-rest-spread": "^6.23.0", "babel-plugin-transform-react-jsx": "^6.24.1", - "babel-preset-env": "^1.4.0", + "babel-preset-env": "^1.5.1", "chai": "^3.4.1", "copyfiles": "^1.0.0", "core-js": "^2.4.1", @@ -113,13 +114,12 @@ }, "greenkeeper": { "ignore": [ - "rollup-plugin-babel", - "babel", + "babel-cli", "babel-core", "babel-eslint", "babel-loader", - "babel-runtime", - "jscodeshift" + "jscodeshift", + "rollup-plugin-babel" ] } } From 47a85cf8bd4c50b45fa114171a5980fd88cade23 Mon Sep 17 00:00:00 2001 From: windyge Date: Thu, 1 Jun 2017 19:25:30 +0800 Subject: [PATCH 22/54] Only execute appendChild when vnode length greater than origin node. (#717) --- src/vdom/diff.js | 2 +- test/browser/render.js | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/vdom/diff.js b/src/vdom/diff.js index 561c016993..81d3aab33c 100644 --- a/src/vdom/diff.js +++ b/src/vdom/diff.js @@ -222,7 +222,7 @@ function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) { child = idiff(child, vchild, context, mountAll); if (child && child!==dom) { - if (i>=len) { + if (i>len) { dom.appendChild(child); } else if (child!==originalChildren[i]) { diff --git a/test/browser/render.js b/test/browser/render.js index bd76b880b3..3aeae531c0 100644 --- a/test/browser/render.js +++ b/test/browser/render.js @@ -582,4 +582,45 @@ describe('render()', () => { let html = scratch.firstElementChild.firstElementChild.outerHTML; expect(sortAttributes(html)).to.equal(sortAttributes('')); }); + + it('should not execute append operation when child is at last', (done) => { + let input; + class TodoList extends Component { + constructor(props) { + super(props); + this.state = { todos: [], text: '' }; + this.setText = this.setText.bind(this); + this.addTodo = this.addTodo.bind(this); + } + setText(e) { + this.setState({ text: e.target.value }); + } + addTodo() { + let { todos, text } = this.state; + todos = todos.concat({ text }); + this.setState({ todos, text: '' }); + } + render() { + const {todos, text} = this.state; + return ( +
+ { todos.map( todo => (
{todo.text}
)) } + input = i} /> +
+ ); + } + } + const root = render(, scratch); + input.focus(); + input.value = 1; + root._component.setText({ + target: input + }); + root._component.addTodo(); + expect(document.activeElement).to.equal(input); + setTimeout(() =>{ + expect(/1/.test(scratch.innerHTML)).to.equal(true); + done(); + }, 10); + }); }); From 22179794b928317ddd16408d10923e45927a6205 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Sat, 3 Jun 2017 13:45:24 -0400 Subject: [PATCH 23/54] fix sourcemaps breakage in dev --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7276cbc03a..d11fe4f292 100644 --- a/package.json +++ b/package.json @@ -93,9 +93,9 @@ "karma-mocha-reporter": "^2.0.4", "karma-phantomjs-launcher": "^1.0.1", "karma-sauce-launcher": "^1.1.0", - "karma-source-map-support": "^1.1.0", + "karma-source-map-support": "^1.2.0", "karma-sourcemap-loader": "^0.3.6", - "karma-webpack": "^2.0.1", + "karma-webpack": "^2.0.3", "mocha": "^3.0.1", "npm-run-all": "^4.0.0", "phantomjs-prebuilt": "^2.1.7", From 2ef872d7785d8dd4c5d6556d007faa4248109bc9 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Sat, 3 Jun 2017 13:46:04 -0400 Subject: [PATCH 24/54] Addendum to #677, avoid repeated access to dynamic key --- src/vdom/diff.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/vdom/diff.js b/src/vdom/diff.js index 81d3aab33c..eb2010cf28 100644 --- a/src/vdom/diff.js +++ b/src/vdom/diff.js @@ -123,13 +123,10 @@ function idiff(dom, vnode, context, mountAll, componentRoot) { let fc = out.firstChild, - props, + props = out[ATTR_KEY], vchildren = vnode.children; - if (out[ATTR_KEY]) { - props = out[ATTR_KEY]; - } - else { + if (props==null) { props = out[ATTR_KEY] = {}; for (let a=out.attributes, i=a.length; i--; ) props[a[i].name] = a[i].value; } From 92f65dfddfe038c4584f5f35e8de93a66c98dda4 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Sat, 3 Jun 2017 13:48:00 -0400 Subject: [PATCH 25/54] =?UTF-8?q?Improvement=20to=20@windyGex's=20awesome?= =?UTF-8?q?=20work=20from=20#717.=20This=20entirely=20removes=20the=20case?= =?UTF-8?q?s=20where=20preact=20would=20erroneously=20invoke=20appendChild?= =?UTF-8?q?()=20when=20it=20didn't=20need=20to.=20=20The=20diff=20no=20lon?= =?UTF-8?q?ger=20depends=20on=20DOM=20length=20values=20=F0=9F=8E=89=20=20?= =?UTF-8?q?Big=20thanks=20to=20@e1ectronic=20for=20pointing=20this=20out?= =?UTF-8?q?=20and=20providing=20a=20great=20repro=20(http://jsfiddle.net/o?= =?UTF-8?q?402afwp/).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/vdom/diff.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/vdom/diff.js b/src/vdom/diff.js index eb2010cf28..44aebc12c6 100644 --- a/src/vdom/diff.js +++ b/src/vdom/diff.js @@ -170,7 +170,7 @@ function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) { len = originalChildren.length, childrenLen = 0, vlen = vchildren ? vchildren.length : 0, - j, c, vchild, child; + j, c, f, vchild, child; // Build up a map of keyed children and an Array of unkeyed children: if (len!==0) { @@ -218,17 +218,16 @@ function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) { // morph the matched/found/created DOM child to match vchild (deep) child = idiff(child, vchild, context, mountAll); - if (child && child!==dom) { - if (i>len) { + f = originalChildren[i]; + if (child && child!==dom && child!==f) { + if (f==null) { dom.appendChild(child); } - else if (child!==originalChildren[i]) { - if (child===originalChildren[i+1]) { - removeNode(originalChildren[i]); - } - else { - dom.insertBefore(child, originalChildren[i] || null); - } + else if (child===f.nextSibling) { + removeNode(f); + } + else { + dom.insertBefore(child, f); } } } From 576dda310a8e31e524fa2ecc803d6d406597c41e Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Sat, 3 Jun 2017 15:15:11 -0400 Subject: [PATCH 26/54] We're going back to microtasks (via Promise#then) for async! Fixes #708. Fixes developit/preact-compat#376. --- src/render-queue.js | 4 ++-- src/util.js | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/render-queue.js b/src/render-queue.js index a8e7dcf5f5..42021f69c7 100644 --- a/src/render-queue.js +++ b/src/render-queue.js @@ -1,4 +1,5 @@ import options from './options'; +import { defer } from './util'; import { renderComponent } from './vdom/component'; /** Managed queue of dirty components to be re-rendered */ @@ -7,11 +8,10 @@ let items = []; export function enqueueRender(component) { if (!component._dirty && (component._dirty = true) && items.push(component)==1) { - (options.debounceRendering || setTimeout)(rerender); + (options.debounceRendering || defer)(rerender); } } - export function rerender() { let p, list = items; items = []; diff --git a/src/util.js b/src/util.js index 7adca8c0ea..720db3b108 100644 --- a/src/util.js +++ b/src/util.js @@ -7,4 +7,7 @@ export function extend(obj, props) { return obj; } - +/** Call a function asynchronously, as soon as possible. + * @param {Function} callback + */ +export const defer = typeof Promise=='function' ? Promise.resolve().then.bind(Promise.resolve()) : setTimeout; From 8611fbcedd74dcbc50bdd860c04637f84481cd37 Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Sat, 3 Jun 2017 12:22:39 -0700 Subject: [PATCH 27/54] Add Play.cash to demos list (#719) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 31e7438b88..e7343af21f 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ Preact supports modern browsers and IE9+: - [**Rainbow Explorer**](https://use-the-platform.com/rainbow-explorer/) _([Github Project](https://github.com/vaneenige/rainbow-explorer/))_ :rainbow: - [**Offline Gallery**](https://use-the-platform.com/offline-gallery/) _([Github Project](https://github.com/vaneenige/offline-gallery/))_ :balloon: - [**Periodic Weather**](https://use-the-platform.com/periodic-weather/) _([Github Project](https://github.com/vaneenige/periodic-weather/))_ :sunny: +- [**Play.cash**](https://play.cash) :notes: ## Libraries & Add-ons From d3407b89144a54848a60a2d086c9def1225992c1 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Tue, 6 Jun 2017 17:09:12 -0400 Subject: [PATCH 28/54] Adds the "module" field --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 405ddabc34..9d3996cf2c 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "8.1.0", "description": "Fast 3kb React alternative with the same ES6 API. Components & Virtual DOM.", "main": "dist/preact.js", + "module": "dist/preact.esm.js", "jsnext:main": "src/preact.js", "dev:main": "dist/preact.dev.js", "minified:main": "dist/preact.min.js", From bf62d5ff5014561f6484475fc574ba81137726d2 Mon Sep 17 00:00:00 2001 From: Nathan Cahill Date: Thu, 8 Jun 2017 11:48:01 -0700 Subject: [PATCH 29/54] add preact-render-to-json (#726) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e7343af21f..a9f307b4ef 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ Preact supports modern browsers and IE9+: - :raised_hands: [**preact-compat**](https://git.io/preact-compat): use any React library with Preact *([full example](http://git.io/preact-compat-example))* - :page_facing_up: [**preact-render-to-string**](https://git.io/preact-render-to-string): Universal rendering. +- :loop: [**preact-render-to-json**](https://git.io/preact-render-to-json): Render for Jest Snapshot testing. - :earth_americas: [**preact-router**](https://git.io/preact-router): URL routing for your components - :bookmark_tabs: [**preact-markup**](https://git.io/preact-markup): Render HTML & Custom Elements as JSX & Components - :satellite: [**preact-portal**](https://git.io/preact-portal): Render Preact components into (a) SPACE :milky_way: From d213b086e36e0ec3c4700d36a5e6a3368af74894 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Fri, 9 Jun 2017 20:36:43 -0400 Subject: [PATCH 30/54] =?UTF-8?q?Add=20notes=20about=20preact-cli=20?= =?UTF-8?q?=E2=9A=9B=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a9f307b4ef..50298c1e5c 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ - Everything you need: JSX, VDOM, React DevTools, HMR, SSR.. - A highly optimized diff algorithm and seamless Server Side Rendering - Transparent asynchronous rendering with a pluggable scheduler +- 🆕💥 **Instant no-config app bundling with [Preact CLI](https://github.com/developit/preact-cli)** ### 💁 More information at the [Preact Website ➞](https://preactjs.com) @@ -125,9 +126,13 @@ Preact supports modern browsers and IE9+: ## Getting Started -> 💁 You [don't _have_ to use ES2015 to use Preact](https://github.com/developit/preact-without-babel)... but you should. +> 💁 _**Note:** You [don't need ES2015 to use Preact](https://github.com/developit/preact-in-es3)... but give it a try!_ -The following guide assumes you have some sort of ES2015 build set up using babel and/or webpack/browserify/gulp/grunt/etc. If you don't, start with [preact-boilerplate] or a [CodePen Template](http://codepen.io/developit/pen/pgaROe?editors=0010). +The easiest way to get started with Preact is to install [Preact CLI](https://github.com/developit/preact-cli). This simple command-line tool wraps up the best possible Webpack and Babel setup for you, and even keeps you up-to-date as the underlying tools change. Best of all, it's easy to understand! It builds your app in a single command (`preact build`), doesn't need any configuration, and bakes in best-practises 🙌. + +The following guide assumes you have some sort of ES2015 build set up using babel and/or webpack/browserify/gulp/grunt/etc. + +You can also start with [preact-boilerplate] or a [CodePen Template](http://codepen.io/developit/pen/pgaROe?editors=0010). ### Import what you need @@ -331,7 +336,7 @@ Here is a somewhat verbose Preact `` component: ```js class Link extends Component { render(props, state) { - return { props.children }; + return {props.children}; } } ``` @@ -340,21 +345,21 @@ Since this is ES6/ES2015, we can further simplify: ```js class Link extends Component { - render({ href, children }) { - return ; - } + render({ href, children }) { + return ; + } } // or, for wide-open props support: class Link extends Component { - render(props) { - return ; - } + render(props) { + return ; + } } // or, as a stateless functional component: const Link = ({ children, ...props }) => ( - { children } + { children } ); ``` From b03bb360b123f95ebe6b2d08944eb32a92863745 Mon Sep 17 00:00:00 2001 From: Dmitry Jakubovsky Date: Mon, 19 Jun 2017 23:18:04 +0300 Subject: [PATCH 31/54] Preparation for typescript 2.4 (#730) * ComponentLifecycle: interface -> abstract class * fix typo --- src/preact.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/preact.d.ts b/src/preact.d.ts index 84f37fcad3..ef3c122dc9 100644 --- a/src/preact.d.ts +++ b/src/preact.d.ts @@ -22,7 +22,7 @@ declare namespace preact { key:string; } - interface ComponentLifecycle { + abstract class ComponentLifecycle { componentWillMount?():void; componentDidMount?():void; componentWillUnmount?():void; @@ -45,7 +45,7 @@ declare namespace preact { // Type alias for a component considered generally, whether stateless or stateful. type AnyComponent = FunctionalComponent | typeof Component; - abstract class Component implements ComponentLifecycle { + abstract class Component extends ComponentLifecycle { constructor(props?:PropsType, context?:any); static displayName?:string; From d49ba50ecc838361e5440f06618d9bb0c3bad7d8 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Tue, 27 Jun 2017 14:03:27 -0400 Subject: [PATCH 32/54] Create CODE_OF_CONDUCT.md --- CODE_OF_CONDUCT.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..9e81e67c88 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@preactjs.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ From 7d5ca189fe5292954f531b8aec2035be289584d0 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 27 Jun 2017 13:11:22 -0700 Subject: [PATCH 33/54] Correct the definition of ComponentLifecycle --- src/preact.d.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/preact.d.ts b/src/preact.d.ts index ef3c122dc9..435c9f7a18 100644 --- a/src/preact.d.ts +++ b/src/preact.d.ts @@ -22,7 +22,7 @@ declare namespace preact { key:string; } - abstract class ComponentLifecycle { + interface ComponentLifecycle { componentWillMount?():void; componentDidMount?():void; componentWillUnmount?():void; @@ -45,7 +45,7 @@ declare namespace preact { // Type alias for a component considered generally, whether stateless or stateful. type AnyComponent = FunctionalComponent | typeof Component; - abstract class Component extends ComponentLifecycle { + abstract class Component { constructor(props?:PropsType, context?:any); static displayName?:string; @@ -65,6 +65,7 @@ declare namespace preact { abstract render(props?:PropsType & ComponentProps, state?:StateType, context?:any):JSX.Element; } + interface Component extends ComponentLifecycle { } function h(node:ComponentConstructor | FunctionalComponent, params:PropsType, ...children:(JSX.Element|JSX.Element[]|string)[]):JSX.Element; function h(node:string, params:JSX.HTMLAttributes&JSX.SVGAttributes&{[propName: string]: any}, ...children:(JSX.Element|JSX.Element[]|string)[]):JSX.Element; From 8a729f99e50ec872410cacf7678aa3572ae0c8bb Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Sun, 2 Jul 2017 01:11:41 +0530 Subject: [PATCH 34/54] Add library size check in CI (#741) * add bundlesize to tests * Upgrade bundlesize to 0.5.6 * Loose the brackets --- package.json | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d11fe4f292..b1d20ccbd2 100644 --- a/package.json +++ b/package.json @@ -19,12 +19,13 @@ "minify": "uglifyjs dist/preact.js -c collapse_vars,evaluate,screw_ie8,unsafe,loops=false,keep_fargs=false,pure_getters,unused,dead_code -m -o dist/preact.min.js -p relative --in-source-map dist/preact.js.map --source-map dist/preact.min.js.map", "strip": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.dev.js", "size": "node -e \"process.stdout.write('gzip size: ')\" && gzip-size dist/preact.min.js", - "test": "npm-run-all lint --parallel test:mocha test:karma test:ts", + "test": "npm-run-all lint --parallel test:mocha test:karma test:ts test:size", "test:ts": "tsc -p test/ts/", "test:mocha": "mocha --recursive --compilers js:babel/register test/shared test/node", "test:karma": "karma start test/karma.conf.js --single-run", "test:mocha:watch": "npm run test:mocha -- --watch", "test:karma:watch": "npm run test:karma -- no-single-run", + "test:size": "bundlesize", "lint": "eslint debug devtools src test", "prepublish": "npm run build", "smart-release": "npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish", @@ -72,6 +73,7 @@ "babel-eslint": "^6.1.0", "babel-loader": "^5.3.2", "babel-runtime": "^5.8.24", + "bundlesize": "^0.5.7", "chai": "^3.4.1", "copyfiles": "^1.0.0", "core-js": "^2.4.1", @@ -120,5 +122,11 @@ "babel-runtime", "jscodeshift" ] - } + }, + "bundlesize": [ + { + "path": "./dist/preact.min.js", + "threshold": "4Kb" + } + ] } From 6517af9ac32292559757b7a9f585cf509fe86a68 Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Sun, 2 Jul 2017 21:14:03 +0530 Subject: [PATCH 35/54] Upgrade bundlesize to 0.6.1 (#744) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b1d20ccbd2..a4a97ce446 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "babel-eslint": "^6.1.0", "babel-loader": "^5.3.2", "babel-runtime": "^5.8.24", - "bundlesize": "^0.5.7", + "bundlesize": "^0.6.1", "chai": "^3.4.1", "copyfiles": "^1.0.0", "core-js": "^2.4.1", From e134f3f8c93facf535408683f378da80862d6577 Mon Sep 17 00:00:00 2001 From: Garth Poitras Date: Sun, 2 Jul 2017 12:02:14 -0400 Subject: [PATCH 36/54] Accurate code coverage + more tests (#706) * Accurate code coverage * Add cloneElement test to reach 100% function coverage * rerender a keyed node in test so code path is covered * skip coverage of line that can't be hit - It's only there to patch a Firefox quirk * Add shouldComponentUpdate tests --- src/vdom/diff.js | 1 + test/browser/components.js | 10 ++++++++- test/browser/keys.js | 4 +++- test/browser/lifecycle.js | 45 ++++++++++++++++++++++++++++++++++++++ test/karma.conf.js | 4 +--- 5 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/vdom/diff.js b/src/vdom/diff.js index 44aebc12c6..b025bde0aa 100644 --- a/src/vdom/diff.js +++ b/src/vdom/diff.js @@ -74,6 +74,7 @@ function idiff(dom, vnode, context, mountAll, componentRoot) { // update if it's already a Text node: if (dom && dom.splitText!==undefined && dom.parentNode && (!dom._component || componentRoot)) { + /* istanbul ignore if */ /* Browser quirk that can't be covered: https://github.com/developit/preact/commit/fd4f21f5c45dfd75151bd27b4c217d8003aa5eb9 */ if (dom.nodeValue!=vnode) { dom.nodeValue = vnode; } diff --git a/test/browser/components.js b/test/browser/components.js index 73ea6af165..904559df11 100644 --- a/test/browser/components.js +++ b/test/browser/components.js @@ -1,4 +1,4 @@ -import { h, render, rerender, Component } from '../../src/preact'; +import { h, cloneElement, render, rerender, Component } from '../../src/preact'; /** @jsx h */ let spyAll = obj => Object.keys(obj).forEach( key => sinon.spy(obj,key) ); @@ -111,6 +111,14 @@ describe('Components', () => { }); + it('should clone components', () => { + function Comp () {} + let instance = ; + let clone = cloneElement(instance); + expect(clone.prototype).to.equal(instance.prototype); + }); + + // Test for Issue #73 it('should remove orphaned elements replaced by Components', () => { class Comp extends Component { diff --git a/test/browser/keys.js b/test/browser/keys.js index 9141b46f61..2a9b0199a2 100644 --- a/test/browser/keys.js +++ b/test/browser/keys.js @@ -24,6 +24,7 @@ describe('keys', () => {
1
  • a
  • +
  • b
  • ), scratch); @@ -31,10 +32,11 @@ describe('keys', () => {
    2
  • b
  • +
  • c
  • ), scratch, root); - expect(scratch.innerHTML).to.equal('
    2
  • b
  • '); + expect(scratch.innerHTML).to.equal('
    2
  • b
  • c
  • '); }); it('should set VNode#key property', () => { diff --git a/test/browser/lifecycle.js b/test/browser/lifecycle.js index 6493473c3e..750bb8abc8 100644 --- a/test/browser/lifecycle.js +++ b/test/browser/lifecycle.js @@ -411,6 +411,51 @@ describe('Lifecycle methods', () => { }); }); + + describe('shouldComponentUpdate', () => { + let setState; + + class Should extends Component { + constructor() { + super(); + this.state = { show:true }; + setState = s => this.setState(s); + } + render(props, { show }) { + return show ?
    : null; + } + } + + class ShouldNot extends Should { + shouldComponentUpdate() { + return false; + } + } + + sinon.spy(Should.prototype, 'render'); + sinon.spy(ShouldNot.prototype, 'shouldComponentUpdate'); + + beforeEach(() => Should.prototype.render.reset()); + + it('should rerender component on change by default', () => { + render(, scratch); + setState({ show:false }); + rerender(); + + expect(Should.prototype.render).to.have.been.calledTwice; + }); + + it('should not rerender component if shouldComponentUpdate returns false', () => { + render(, scratch); + setState({ show:false }); + rerender(); + + expect(ShouldNot.prototype.shouldComponentUpdate).to.have.been.calledOnce; + expect(ShouldNot.prototype.render).to.have.been.calledOnce; + }); + }); + + describe('Lifecycle DOM Timing', () => { it('should be invoked when dom does (DidMount, WillUnmount) or does not (WillMount, DidUnmount) exist', () => { let setState; diff --git a/test/karma.conf.js b/test/karma.conf.js index f11ad1f24c..f859b376c0 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -119,9 +119,7 @@ module.exports = function(config) { loader: 'babel-loader', options: { loose: 'all', - blacklist: ['es6.tailCall'], - comments: false, - compact: true + blacklist: ['es6.tailCall'] } }, /* Only Instrument our source files for coverage */ From 855c34a236e7b5b6bfb4e73658c3a10fd78843b8 Mon Sep 17 00:00:00 2001 From: Greenkeeper Date: Sun, 2 Jul 2017 18:02:53 +0200 Subject: [PATCH 37/54] chore(package): update sinon to version 2.2.0 (#682) https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a4a97ce446..a899e66b54 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "rollup-plugin-babel": "^1.0.0", "rollup-plugin-memory": "^2.0.0", "rollup-plugin-node-resolve": "^2.0.0", - "sinon": "^1.17.4", + "sinon": "^2.2.0", "sinon-chai": "^2.8.0", "typescript": "^2.2.2", "uglify-js": "^2.7.5", From 57341a5fc53a33debd268e3d61850641194daf03 Mon Sep 17 00:00:00 2001 From: Markus Wolf Date: Sun, 2 Jul 2017 18:03:57 +0200 Subject: [PATCH 38/54] fix: allow render function to return null (#669) * fix: allow render function to return null In react components are allowed to return null from the render function * refactor: remove unneccessary prop-types --- src/preact.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/preact.d.ts b/src/preact.d.ts index 435c9f7a18..aec381e3d0 100644 --- a/src/preact.d.ts +++ b/src/preact.d.ts @@ -33,7 +33,7 @@ declare namespace preact { } interface FunctionalComponent { - (props?:PropsType & ComponentProps, context?:any):JSX.Element; + (props?:PropsType & ComponentProps, context?:any):JSX.Element; displayName?:string; defaultProps?:any; } @@ -52,7 +52,7 @@ declare namespace preact { static defaultProps?:any; state:StateType; - props:PropsType & ComponentProps; + props:PropsType & ComponentProps; context:any; base:HTMLElement; @@ -63,7 +63,7 @@ declare namespace preact { forceUpdate(callback?:() => void): void; - abstract render(props?:PropsType & ComponentProps, state?:StateType, context?:any):JSX.Element; + abstract render(props?:PropsType & ComponentProps, state?:StateType, context?:any):JSX.Element|null; } interface Component extends ComponentLifecycle { } From 6756a9c6f74f24dd19002bfa0dff43a78bb78b5c Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 10 Jul 2017 21:05:42 -0400 Subject: [PATCH 39/54] Fix TS defintion breakage --- src/preact.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/preact.d.ts b/src/preact.d.ts index aec381e3d0..6fcdb02f3f 100644 --- a/src/preact.d.ts +++ b/src/preact.d.ts @@ -33,7 +33,7 @@ declare namespace preact { } interface FunctionalComponent { - (props?:PropsType & ComponentProps, context?:any):JSX.Element; + (props?:PropsType & ComponentProps, context?:any):JSX.Element; displayName?:string; defaultProps?:any; } @@ -52,7 +52,7 @@ declare namespace preact { static defaultProps?:any; state:StateType; - props:PropsType & ComponentProps; + props:PropsType & ComponentProps; context:any; base:HTMLElement; @@ -63,7 +63,7 @@ declare namespace preact { forceUpdate(callback?:() => void): void; - abstract render(props?:PropsType & ComponentProps, state?:StateType, context?:any):JSX.Element|null; + abstract render(props?:PropsType & ComponentProps, state?:StateType, context?:any):JSX.Element|null; } interface Component extends ComponentLifecycle { } From 8621b1880e5c5eab25f1e8a6f18a240cf10665c6 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 10 Jul 2017 21:18:41 -0400 Subject: [PATCH 40/54] Derive rollup config from base one --- config/rollup.config.esm.js | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/config/rollup.config.esm.js b/config/rollup.config.esm.js index a64fd9c4b6..5078a1171b 100644 --- a/config/rollup.config.esm.js +++ b/config/rollup.config.esm.js @@ -1,19 +1,9 @@ -import nodeResolve from 'rollup-plugin-node-resolve'; -import babel from 'rollup-plugin-babel'; +import config from './rollup.config'; -export default { - useStrict: true, - format: 'es', - entry: 'src/preact.js', - plugins: [ - nodeResolve({ - main: true - }), - babel({ - sourceMap: true, - loose: 'all', - blacklist: ['es6.tailCall'], - exclude: 'node_modules/**' - }) - ] -}; +// ES output +config.format = 'es'; + +// remove memory() plugin +config.plugins.splice(0, 1); + +export default config; From 7f03a81b1e63264f10f8be782437ca8c160fc7ea Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 10 Jul 2017 21:41:27 -0400 Subject: [PATCH 41/54] Move babel config into package.json and add a note about the iffy transform for babel6+ --- .babelrc | 15 --------------- config/codemod-let-name.js | 1 + package.json | 15 +++++++++++++++ 3 files changed, 16 insertions(+), 15 deletions(-) delete mode 100644 .babelrc diff --git a/.babelrc b/.babelrc deleted file mode 100644 index d42301f46b..0000000000 --- a/.babelrc +++ /dev/null @@ -1,15 +0,0 @@ -{ - "presets": [ - ["env", { - "loose": true, - "exclude": ["transform-es2015-typeof-symbol"], - "targets": { - "browsers": ["last 2 versions", "IE >= 9"] - } - }] - ], - "plugins": [ - "transform-object-rest-spread", - "transform-react-jsx" - ] -} diff --git a/config/codemod-let-name.js b/config/codemod-let-name.js index e04d3f41e0..782cc99d76 100644 --- a/config/codemod-let-name.js +++ b/config/codemod-let-name.js @@ -5,6 +5,7 @@ export default (file, api) => { let j = api.jscodeshift; let code = j(file.source); + // @TODO unsafe, but without it we gain 20b gzipped: https://www.diffchecker.com/bVrOJWTO code.findVariableDeclarators().filter(d => /^_i/.test(d.value.id.name)).renameTo('i'); code.findVariableDeclarators('_key').renameTo('key'); diff --git a/package.json b/package.json index 01b40316ef..cf726303bd 100644 --- a/package.json +++ b/package.json @@ -116,6 +116,21 @@ "uglify-js": "^2.7.5", "webpack": "^2.4.1" }, + "babel": { + "presets": [ + ["env", { + "loose": true, + "exclude": ["transform-es2015-typeof-symbol"], + "targets": { + "browsers": ["last 2 versions", "IE >= 9"] + } + }] + ], + "plugins": [ + "transform-object-rest-spread", + "transform-react-jsx" + ] + }, "greenkeeper": { "ignore": [ "babel-cli", From 5b04dbf0f04042638b1f3310274442707b9dd6ad Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 10 Jul 2017 22:01:48 -0400 Subject: [PATCH 42/54] Backport Babel 6 configuration from master, but keep the awesome preact.esm.js optimizations (https://www.diffchecker.com/xJBzW3dR) --- config/rollup.config.js | 51 ++++++++++++++++++----------------------- package.json | 9 ++++---- 2 files changed, 26 insertions(+), 34 deletions(-) diff --git a/config/rollup.config.js b/config/rollup.config.js index 5214765069..fe0581139c 100644 --- a/config/rollup.config.js +++ b/config/rollup.config.js @@ -1,44 +1,37 @@ -import fs from 'fs'; -import memory from 'rollup-plugin-memory'; -import buble from 'rollup-plugin-buble'; import nodeResolve from 'rollup-plugin-node-resolve'; -import commonjs from 'rollup-plugin-commonjs'; - -let pkg = JSON.parse(fs.readFileSync('./package.json')); - -let external = Object.keys(pkg.peerDependencies || {}).concat(Object.keys(pkg.dependencies || {})); - -let format = process.env.FORMAT === 'es' ? 'es' : 'iife'; +import babel from 'rollup-plugin-babel'; +import memory from 'rollup-plugin-memory'; export default { - entry: 'src/preact.js', - sourceMap: true, - exports: format==='es' ? null : 'default', - dest: format==='es' ? pkg.module : pkg.main, - format, - external, useStrict: true, + format: 'iife', + entry: 'src/preact.js', plugins: [ - format==='iife' && memory({ - path: 'src/preact.js', + memory({ + path: 'src/preact.js', contents: ` import preact from './preact'; if (typeof module!='undefined') module.exports = preact; else self.preact = preact; ` }), - buble({ - objectAssign: 'extend', - namedFunctionExpressions: false - }), nodeResolve({ - jsnext: true, - main: true, - skip: external + main: true }), - commonjs({ - include: 'node_modules/**', - exclude: '**/*.css' + babel({ + sourceMap: true, + exclude: 'node_modules/**', + babelrc: false, + presets: [ + ['env', { + modules: false, + loose: true, + exclude: ['transform-es2015-typeof-symbol'], + targets: { + browsers: ['last 2 versions', 'IE >= 9'] + } + }] + ] }) - ].filter(Boolean) + ] }; diff --git a/package.json b/package.json index 9bdcdd7220..eb4b4ca67c 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "copy-flow-definition": "copyfiles -f src/preact.js.flow dist", "copy-typescript-definition": "copyfiles -f src/preact.d.ts dist", "build": "npm-run-all --silent clean transpile copy-flow-definition copy-typescript-definition strip optimize minify size", - "transpile:main": "rollup --environment FORMAT:umd -c config/rollup.config.js -m dist/preact.dev.js.map -n preact -o dist/preact.dev.js", - "transpile:esm": "rollup --environment FORMAT:es -c config/rollup.config.js -m dist/preact.esm.js.map -o dist/preact.esm.js", + "transpile:main": "rollup -c config/rollup.config.js -m dist/preact.dev.js.map -n preact -o dist/preact.dev.js", "transpile:devtools": "rollup -c config/rollup.config.devtools.js -o devtools.js -m devtools.js.map", + "transpile:esm": "rollup -c config/rollup.config.esm.js -m dist/preact.esm.js.map -o dist/preact.esm.js", "transpile:debug": "babel debug/ -o debug.js -s", "transpile": "npm-run-all transpile:main transpile:esm transpile:devtools transpile:debug", "optimize": "uglifyjs dist/preact.dev.js -c conditionals=false,sequences=false,loops=false,join_vars=false,collapse_vars=false --pure-funcs=Object.defineProperty --mangle-props --mangle-regex=\"/^(_|normalizedNodeName|nextBase|prev[CPS]|_parentC)/\" --name-cache config/properties.json -b width=120,quote_style=3 -o dist/preact.js -p relative --in-source-map dist/preact.dev.js.map --source-map dist/preact.js.map", @@ -108,9 +108,8 @@ "npm-run-all": "^4.0.0", "phantomjs-prebuilt": "^2.1.7", "rimraf": "^2.5.3", - "rollup": "^0.41.0", - "rollup-plugin-buble": "^0.15.0", - "rollup-plugin-commonjs": "^8.0.2", + "rollup": "^0.40.0", + "rollup-plugin-babel": "^2.7.1", "rollup-plugin-memory": "^2.0.0", "rollup-plugin-node-resolve": "^2.0.0", "sinon": "^2.2.0", From 429da73eef5b544f9a8580f8f1bd31194b229873 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 10 Jul 2017 22:07:49 -0400 Subject: [PATCH 43/54] Re-add missing codemod --- config/codemod-const.js | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/codemod-const.js b/config/codemod-const.js index 26ba3ae373..5d27f93eab 100644 --- a/config/codemod-const.js +++ b/config/codemod-const.js @@ -17,7 +17,7 @@ export default (file, api) => { init = node.init; if (name && init && name.match(/^[A-Z0-9_$]+$/g) && !init.regex) { if (init.type==='Literal') { - console.log(`Inlining constant: ${name}=${init.raw}`); + // console.log(`Inlining constant: ${name}=${init.raw}`); found++; constants[name] = init; // remove declaration diff --git a/package.json b/package.json index eb4b4ca67c..6069d165f7 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ "transpile": "npm-run-all transpile:main transpile:esm transpile:devtools transpile:debug", "optimize": "uglifyjs dist/preact.dev.js -c conditionals=false,sequences=false,loops=false,join_vars=false,collapse_vars=false --pure-funcs=Object.defineProperty --mangle-props --mangle-regex=\"/^(_|normalizedNodeName|nextBase|prev[CPS]|_parentC)/\" --name-cache config/properties.json -b width=120,quote_style=3 -o dist/preact.js -p relative --in-source-map dist/preact.dev.js.map --source-map dist/preact.js.map", "minify": "uglifyjs dist/preact.js -c collapse_vars,evaluate,screw_ie8,unsafe,loops=false,keep_fargs=false,pure_getters,unused,dead_code -m -o dist/preact.min.js -p relative --in-source-map dist/preact.js.map --source-map dist/preact.min.js.map", - "strip:main": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.dev.js", - "strip:esm": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.esm.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.esm.js", + "strip:main": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-let-name.js dist/preact.dev.js", + "strip:esm": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.esm.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.esm.js && jscodeshift --run-in-band -s -t config/codemod-let-name.js dist/preact.esm.js", "strip": "npm-run-all strip:main strip:esm", "size": "node -e \"process.stdout.write('gzip size: ')\" && gzip-size dist/preact.min.js", "test": "npm-run-all lint --parallel test:mocha test:karma test:ts test:size", From 0948d4dd3a3efb70025f3a7c439e9ae305ef9ef8 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 10 Jul 2017 22:17:43 -0400 Subject: [PATCH 44/54] slim down the OpenCollective post-install message and make it colorful --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 6069d165f7..3cab6e4cf5 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,7 @@ "prepublish": "npm run build", "smart-release": "npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish", "release": "cross-env npm run smart-release", - "postinstall": "npm run -s donate", - "donate": "echo \"\n *** Thanks for downloading Preact! ***\nPlease consider donating to our open collective\n\n => https://opencollective.com/preact/donate\n\"" + "postinstall": "echo \"\u001b[35m\u001b[1mLove Preact? You can now donate to our open collective:\u001b[22m\u001b[39m\n > \u001b[34mhttps://opencollective.com/preact/donate\u001b[39m\"" }, "eslintConfig": { "extends": "./config/eslint-config.js" From fd1df721a374e1ed97694cc5e837a08f4dcf5855 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 10 Jul 2017 22:22:13 -0400 Subject: [PATCH 45/54] [postinstall fix] --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 3cab6e4cf5..febb61a3db 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,8 @@ "prepublish": "npm run build", "smart-release": "npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish", "release": "cross-env npm run smart-release", - "postinstall": "echo \"\u001b[35m\u001b[1mLove Preact? You can now donate to our open collective:\u001b[22m\u001b[39m\n > \u001b[34mhttps://opencollective.com/preact/donate\u001b[39m\"" + "postinstall": "npm run -s donate", + "donate": "echo \"\u001b[35m\u001b[1mLove Preact? You can now donate to our open collective:\u001b[22m\u001b[39m\n > \u001b[34mhttps://opencollective.com/preact/donate\u001b[39m\"" }, "eslintConfig": { "extends": "./config/eslint-config.js" From 90a720cfc539106db0e4e390f1d59eaa518c2a93 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 10 Jul 2017 22:24:01 -0400 Subject: [PATCH 46/54] 8.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index febb61a3db..7d0edecd38 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "preact", - "version": "8.1.0", + "version": "8.2.0", "description": "Fast 3kb React alternative with the same ES6 API. Components & Virtual DOM.", "main": "dist/preact.js", "jsnext:main": "dist/preact.esm.js", From 824404bf0ebad47af12686f806f5876dbe499bbe Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Tue, 11 Jul 2017 08:06:52 -0400 Subject: [PATCH 47/54] Fix comment typo (closes #752) --- src/vdom/diff.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vdom/diff.js b/src/vdom/diff.js index b025bde0aa..f74e9961fa 100644 --- a/src/vdom/diff.js +++ b/src/vdom/diff.js @@ -248,7 +248,7 @@ function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) { -/** Recursively recycle (or just unmount) a node an its descendants. +/** Recursively recycle (or just unmount) a node and its descendants. * @param {Node} node DOM node to start unmount/removal from * @param {Boolean} [unmountOnly=false] If `true`, only triggers unmount lifecycle, skips removal */ From 7e70fb11e567cb95b017b532356125cbc6be1410 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Tue, 11 Jul 2017 11:32:18 -0400 Subject: [PATCH 48/54] [Temporarily] disable flushMounts() to fix #750 --- src/vdom/component.js | 3 ++- test/browser/lifecycle.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vdom/component.js b/src/vdom/component.js index b64ae40087..4d867e7101 100644 --- a/src/vdom/component.js +++ b/src/vdom/component.js @@ -175,7 +175,8 @@ export function renderComponent(component, opts, mountAll, isChild) { else if (!skip) { // Ensure that pending componentDidMount() hooks of child components // are called before the componentDidUpdate() hook in the parent. - flushMounts(); + // Note: disabled as it causes duplicate hooks, see https://github.com/developit/preact/issues/750 + // flushMounts(); if (component.componentDidUpdate) { component.componentDidUpdate(previousProps, previousState, previousContext); diff --git a/test/browser/lifecycle.js b/test/browser/lifecycle.js index 750bb8abc8..4a22c78e55 100644 --- a/test/browser/lifecycle.js +++ b/test/browser/lifecycle.js @@ -122,7 +122,7 @@ describe('Lifecycle methods', () => { const elem = render(, scratch); render(, scratch, elem); - expect(log).to.deep.equal(['Inner mounted', 'Outer updated']); + // expect(log).to.deep.equal(['Inner mounted', 'Outer updated']); }); }); From e026d9e1a871a3f84fb88a499168b4af083673f6 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Tue, 11 Jul 2017 18:35:57 -0400 Subject: [PATCH 49/54] 8.2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7d0edecd38..8f3ffadb4b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "preact", - "version": "8.2.0", + "version": "8.2.1", "description": "Fast 3kb React alternative with the same ES6 API. Components & Virtual DOM.", "main": "dist/preact.js", "jsnext:main": "dist/preact.esm.js", From 947d9d82885460dd5581965f7ff393d9fb3d5932 Mon Sep 17 00:00:00 2001 From: feizheng <1290657123@qq.com> Date: Mon, 21 Aug 2017 00:38:01 +0800 Subject: [PATCH 50/54] Weui for preact (#793) * Weui for preact Weui for preact * issue: preact-weui url Modify preact-weui url --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 50298c1e5c..6d2876e857 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ Preact supports modern browsers and IE9+: - [**preact-mui**](https://git.io/v1aVO): The MUI CSS Preact library. - [**preact-photon**](https://git.io/preact-photon): build beautiful desktop UI with [photon](http://photonkit.com) - [**preact-mdl**](https://git.io/preact-mdl): [Material Design Lite](https://getmdl.io) for Preact +- [**preact-weui**](https://github.com/afeiship/preact-weui): [Weui](https://github.com/afeiship/preact-weui) for Preact --- From 1b2b106248824a543d20ba8b43e37d5efb315151 Mon Sep 17 00:00:00 2001 From: ReadmeCritic Date: Sun, 20 Aug 2017 09:40:50 -0700 Subject: [PATCH 51/54] Minor capitalization correction for GitHub in README (#787) --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 6d2876e857..4a9630f843 100644 --- a/README.md +++ b/README.md @@ -61,14 +61,14 @@ Preact supports modern browsers and IE9+: ## Demos - [**ESBench**](http://esbench.com) is built using Preact. -- [**Nectarine.rocks**](http://nectarine.rocks) _([Github Project](https://github.com/developit/nectarine))_ :peach: -- [**Documentation Viewer**](https://documentation-viewer.firebaseapp.com) _([Github Project](https://github.com/developit/documentation-viewer))_ -- [**TodoMVC**](https://preact-todomvc.surge.sh) _([Github Project](https://github.com/developit/preact-todomvc))_ -- [**Hacker News Minimal**](https://developit.github.io/hn_minimal/) _([Github Project](https://github.com/developit/hn_minimal))_ -- [**Preact Boilerplate**](https://preact-boilerplate.surge.sh) _([Github Project](https://github.com/developit/preact-boilerplate))_ :zap: -- [**Preact Offline Starter**](https://preact-starter.now.sh) _([Github Project](https://github.com/lukeed/preact-starter))_ :100: -- [**Preact PWA**](https://preact-pwa.appspot.com/) _([Github Project](https://github.com/ezekielchentnik/preact-pwa))_ :hamburger: -- [**Preact Mobx Starter**](https://awaw00.github.io/preact-mobx-starter/) _([Github Project](https://github.com/awaw00/preact-mobx-starter))_ :sunny: +- [**Nectarine.rocks**](http://nectarine.rocks) _([GitHub Project](https://github.com/developit/nectarine))_ :peach: +- [**Documentation Viewer**](https://documentation-viewer.firebaseapp.com) _([GitHub Project](https://github.com/developit/documentation-viewer))_ +- [**TodoMVC**](https://preact-todomvc.surge.sh) _([GitHub Project](https://github.com/developit/preact-todomvc))_ +- [**Hacker News Minimal**](https://developit.github.io/hn_minimal/) _([GitHub Project](https://github.com/developit/hn_minimal))_ +- [**Preact Boilerplate**](https://preact-boilerplate.surge.sh) _([GitHub Project](https://github.com/developit/preact-boilerplate))_ :zap: +- [**Preact Offline Starter**](https://preact-starter.now.sh) _([GitHub Project](https://github.com/lukeed/preact-starter))_ :100: +- [**Preact PWA**](https://preact-pwa.appspot.com/) _([GitHub Project](https://github.com/ezekielchentnik/preact-pwa))_ :hamburger: +- [**Preact Mobx Starter**](https://awaw00.github.io/preact-mobx-starter/) _([GitHub Project](https://github.com/awaw00/preact-mobx-starter))_ :sunny: - [**Preact Redux Example**](https://github.com/developit/preact-redux-example) :star: - [**Flickr Browser**](http://codepen.io/developit/full/VvMZwK/) (@ CodePen) - [**Animating Text**](http://codepen.io/developit/full/LpNOdm/) (@ CodePen) @@ -78,13 +78,13 @@ Preact supports modern browsers and IE9+: - [**Stock Ticker**](http://codepen.io/developit/pen/wMYoBb?editors=0010) (@ CodePen) - [**Create your Own!**](https://jsfiddle.net/developit/rs6zrh5f/embedded/result/) (@ JSFiddle) - [**Preact Coffeescript**](https://github.com/crisward/preact-coffee) -- [**GuriVR**](https://gurivr.com) _([Github Project](https://github.com/opennewslabs/guri-vr))_ +- [**GuriVR**](https://gurivr.com) _([GitHub Project](https://github.com/opennewslabs/guri-vr))_ - [**V2EX Preact**](https://github.com/yanni4night/v2ex-preact) -- [**BigWebQuiz**](https://bigwebquiz.com/) _([Github Project](https://github.com/jakearchibald/big-web-quiz))_ -- [**Color Picker**](https://colors.now.sh) _([Github Project](https://github.com/lukeed/colors-app))_ :art: -- [**Rainbow Explorer**](https://use-the-platform.com/rainbow-explorer/) _([Github Project](https://github.com/vaneenige/rainbow-explorer/))_ :rainbow: -- [**Offline Gallery**](https://use-the-platform.com/offline-gallery/) _([Github Project](https://github.com/vaneenige/offline-gallery/))_ :balloon: -- [**Periodic Weather**](https://use-the-platform.com/periodic-weather/) _([Github Project](https://github.com/vaneenige/periodic-weather/))_ :sunny: +- [**BigWebQuiz**](https://bigwebquiz.com/) _([GitHub Project](https://github.com/jakearchibald/big-web-quiz))_ +- [**Color Picker**](https://colors.now.sh) _([GitHub Project](https://github.com/lukeed/colors-app))_ :art: +- [**Rainbow Explorer**](https://use-the-platform.com/rainbow-explorer/) _([GitHub Project](https://github.com/vaneenige/rainbow-explorer/))_ :rainbow: +- [**Offline Gallery**](https://use-the-platform.com/offline-gallery/) _([GitHub Project](https://github.com/vaneenige/offline-gallery/))_ :balloon: +- [**Periodic Weather**](https://use-the-platform.com/periodic-weather/) _([GitHub Project](https://github.com/vaneenige/periodic-weather/))_ :sunny: - [**Play.cash**](https://play.cash) :notes: ## Libraries & Add-ons @@ -466,7 +466,7 @@ Support us with a monthly donation and help us continue our activities. [[Become ## Sponsors -Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/preact#sponsor)] +Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor](https://opencollective.com/preact#sponsor)] From 0a88752e4890d391b5e23809d9432f625a833ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sk=C3=B6ld?= Date: Sun, 20 Aug 2017 18:41:50 +0200 Subject: [PATCH 52/54] Update import paths for #792 (#796) * Changed ../dom -> ../dom/index Should take care of #792 * Changed ../dom -> ../dom/index --- src/vdom/component.js | 2 +- src/vdom/diff.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vdom/component.js b/src/vdom/component.js index 4d867e7101..5286735174 100644 --- a/src/vdom/component.js +++ b/src/vdom/component.js @@ -5,7 +5,7 @@ import { enqueueRender } from '../render-queue'; import { getNodeProps } from './index'; import { diff, mounts, diffLevel, flushMounts, recollectNodeTree, removeChildren } from './diff'; import { createComponent, collectComponent } from './component-recycler'; -import { removeNode } from '../dom'; +import { removeNode } from '../dom/index'; /** Set a component's `props` (generally derived from JSX attributes). * @param {Object} props diff --git a/src/vdom/diff.js b/src/vdom/diff.js index f74e9961fa..6cc9bb7106 100644 --- a/src/vdom/diff.js +++ b/src/vdom/diff.js @@ -4,7 +4,7 @@ import { buildComponentFromVNode } from './component'; import { createNode, setAccessor } from '../dom/index'; import { unmountComponent } from './component'; import options from '../options'; -import { removeNode } from '../dom'; +import { removeNode } from '../dom/index'; /** Queue of components that have been mounted and are awaiting componentDidMount */ export const mounts = []; From 68fa5106d061c1f5bf283ea419220f416803697d Mon Sep 17 00:00:00 2001 From: Daniel Ciao Date: Sun, 20 Aug 2017 09:49:20 -0700 Subject: [PATCH 53/54] Fix preact/debug accessing attributes that don't have toString (#754) * Fix accessing attributes that don't inherit Object * Use object's toString if it exists * Fix spacing * Fix spacing * Fix spacing --- debug/index.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/debug/index.js b/debug/index.js index 4bb2e7ee78..fa02855308 100644 --- a/debug/index.js +++ b/debug/index.js @@ -70,7 +70,17 @@ if (process.env.NODE_ENV === 'development') { if (attributes) { props = Object.keys(attributes).map(attr => { - return `${attr}=${JSON.stringify(attributes[attr] + '')}`; + const attrValue = attributes[attr]; + let attrValueString; + + // If it is an object but doesn't have toString(), use Object.toString + if (Object(attrValue) === attrValue && !attrValue.toString) { + attrValueString = Object.prototype.toString.call(attrValue); + } else { + attrValueString = attrValue + ''; + } + + return `${attr}=${JSON.stringify(attrValueString)}`; }); } @@ -82,4 +92,4 @@ if (process.env.NODE_ENV === 'development') { }; require('preact/devtools'); -} \ No newline at end of file +} From 0dea3b77ee0677987815347c1e6bd23821728aa2 Mon Sep 17 00:00:00 2001 From: David Zhang Date: Tue, 22 Aug 2017 01:35:29 +0800 Subject: [PATCH 54/54] Add rugby board as an example (#821) * Add rugby board example * Add the missing parentheses --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4a9630f843..46b533a937 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ Preact supports modern browsers and IE9+: - [**Offline Gallery**](https://use-the-platform.com/offline-gallery/) _([GitHub Project](https://github.com/vaneenige/offline-gallery/))_ :balloon: - [**Periodic Weather**](https://use-the-platform.com/periodic-weather/) _([GitHub Project](https://github.com/vaneenige/periodic-weather/))_ :sunny: - [**Play.cash**](https://play.cash) :notes: +- [**Rugby News Board**](http://nbrugby.com) _[(GitHub Project)](https://github.com/rugby-board/rugby-board-node)_ ## Libraries & Add-ons