diff --git a/.flowconfig b/.flowconfig index 5f8e969f2bd..522d3c0d306 100644 --- a/.flowconfig +++ b/.flowconfig @@ -36,4 +36,4 @@ untyped-import untyped-type-import [version] -0.158.0 +0.160.1 diff --git a/Cargo.lock b/Cargo.lock index 72961081c26..5b8f28ade7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,9 +55,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf" +checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" [[package]] name = "arrayvec" @@ -155,9 +155,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cc" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" +checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" dependencies = [ "jobserver", ] @@ -228,9 +228,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "cpufeatures" -version = "0.1.5" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" dependencies = [ "libc", ] @@ -533,9 +533,9 @@ dependencies = [ [[package]] name = "if_chain" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7280c75fb2e2fc47080ec80ccc481376923acb04501957fc38f935c3de5088" +checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" [[package]] name = "image" @@ -596,9 +596,9 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "jemalloc-sys" @@ -670,9 +670,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.99" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765" +checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" [[package]] name = "libdeflate-sys" @@ -718,9 +718,9 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memoffset" @@ -773,9 +773,9 @@ dependencies = [ [[package]] name = "napi" -version = "1.7.6" +version = "1.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb22375ec7cbd8bee4535126bb323e4e62cbf8088d84f0225d4d3226d1619bd5" +checksum = "2813a6f24e181eb1faba8bc632e56049901fb71df4bf3e0cd6b4086db6606c78" dependencies = [ "napi-sys", "serde", @@ -907,9 +907,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "ordered-float" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039f02eb0f69271f26abe3202189275d7aa2258b903cb0281b5de710a2570ff3" +checksum = "97c9d06878b3a851e8026ef94bf7fef9ba93062cd412601da4d9cf369b1cc62d" dependencies = [ "num-traits", ] @@ -1128,9 +1128,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" dependencies = [ "unicode-xid", ] @@ -1330,18 +1330,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.127" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" dependencies = [ "serde_derive", ] [[package]] name = "serde-wasm-bindgen" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1102fa7714968fcf70fd8efa29fb3b189e20ef0e7701fbab9634384dda034bf3" +checksum = "618365e8e586c22123d692b72a7d791d5ee697817b65a218cdf12a98870af0f7" dependencies = [ "fnv", "js-sys", @@ -1360,9 +1360,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.127" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc" +checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" dependencies = [ "proc-macro2", "quote", @@ -1371,9 +1371,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127" +checksum = "a7f9e390c27c3c0ce8bc5d725f6e4d30a29d26659494aa4b17535f7522c5c950" dependencies = [ "itoa", "ryu", @@ -1382,9 +1382,9 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a0c8611594e2ab4ebbf06ec7cbbf0a99450b8570e96cbf5188b5d5f6ef18d81" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer", "cfg-if 1.0.0", @@ -1395,9 +1395,9 @@ dependencies = [ [[package]] name = "siphasher" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729a25c17d72b06c68cb47955d44fda88ad2d3e7d77e025663fdd69b93dd71a1" +checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" [[package]] name = "smallvec" @@ -1520,9 +1520,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" [[package]] name = "swc_atoms" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bcdb70cb6ecee568e5acfda1a8c6e851ecf49443e5fb51f1b13613b5d04d2b0" +checksum = "837a3ef86c2817228e733b6f173c821fd76f9eb21a0bc9001a826be48b00b4e7" dependencies = [ "string_cache", "string_cache_codegen", @@ -1530,9 +1530,9 @@ dependencies = [ [[package]] name = "swc_common" -version = "0.11.6" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc89b8c9f2fa3fc646e7d1a05ebc2063b1396b3ba5277afc741505bd7414fff" +checksum = "0100bddbd0b5587223a862dedc9556715d066205e7e1954ca080567693923ee5" dependencies = [ "ahash", "ast_node", @@ -1553,13 +1553,14 @@ dependencies = [ "swc_visit", "termcolor", "unicode-width", + "url", ] [[package]] name = "swc_ecma_ast" -version = "0.49.4" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3efef728f69665d765c52b233155dcb3290424f56a9f978ecfbd53f136804461" +checksum = "aa0efb0e13ba6545e2b86336937e1641594f78c48484b85c2dc9582eaccb41e1" dependencies = [ "is-macro", "num-bigint", @@ -1571,9 +1572,9 @@ dependencies = [ [[package]] name = "swc_ecma_codegen" -version = "0.67.0" +version = "0.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a380bd935ce811c0bc8b961abc97cbf3a8c759213634aa59f5b0601162ba4e" +checksum = "7940bff62e5caf62fe6732ce4f07e52c3c208cb58cd9299f7f7c92dddab2bf72" dependencies = [ "bitflags", "num-bigint", @@ -1600,9 +1601,9 @@ dependencies = [ [[package]] name = "swc_ecma_loader" -version = "0.15.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc6a797d2df5f60cc9ab6a85aa7a49ab1bcaac8150d184f79a27deba2d21983" +checksum = "c2f718f0335f9ab7437fecf9f3d73ae6a24c03a3d3f46910a68261703d407f03" dependencies = [ "anyhow", "dashmap", @@ -1620,9 +1621,9 @@ dependencies = [ [[package]] name = "swc_ecma_parser" -version = "0.67.0" +version = "0.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0418c8dcb041d74e90c2179290bf3be0e58f2425d1f86843a5e297a13755912" +checksum = "042a901352b84cefbb64916a010ee33f621a7e341ced2b2fa60035858f3146a5" dependencies = [ "either", "enum_kind", @@ -1641,9 +1642,9 @@ dependencies = [ [[package]] name = "swc_ecma_preset_env" -version = "0.38.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "283a609ec84132c2751bdee13a7a81228007206538ef09a1066163602f0d34d8" +checksum = "7fdb885d7b8ad47fb5f62cff0b36f61d6282b3548a566b8760a800c00de23679" dependencies = [ "dashmap", "fxhash", @@ -1665,9 +1666,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms" -version = "0.67.0" +version = "0.71.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c50b45538663ae18d56768c93567312dd5cbf29786678a94cfa610172ba93a4" +checksum = "b2124504a4203cab8f903b8e8be49dbd6c4bad2b0405ba0c8188f952c224c44b" dependencies = [ "swc_atoms", "swc_common", @@ -1687,9 +1688,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_base" -version = "0.27.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5de480c55ae93eb59715cfc8f66965d192bc62cd4c12e33cff9f940f9431e12" +checksum = "b26e191df68943565f22059d31b02967e60a62c4f76533b5b5106546785a8e2e" dependencies = [ "fxhash", "once_cell", @@ -1706,9 +1707,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_classes" -version = "0.13.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdcbad381d349cbff95f7602bf2d9ad6a40c7df92a391d4af62221bd0d7633a2" +checksum = "ad5a845d5ec140ba8580c6b8d0f51ce417b86395a7b74c4280bb6cdae3c042c6" dependencies = [ "swc_atoms", "swc_common", @@ -1720,9 +1721,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_compat" -version = "0.30.0" +version = "0.34.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cca0020d15ecb278fcdc4cd55f199f39e0c42ceb9e7f9740416f36120c17ad5" +checksum = "cda7278fdc9598ec43d40aa795ec7049532194bbcea861dd89bfe0ad3901446d" dependencies = [ "arrayvec", "fxhash", @@ -1757,9 +1758,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_module" -version = "0.34.0" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac0abb8acb4b72d1ef37971b0bfed8e267ecaab37b3d34bac96205d7b62689e2" +checksum = "c79229bac86ac213d69c6d5957f9ee281979a9a7c6e5b94ca360a8a4429c6021" dependencies = [ "Inflector", "anyhow", @@ -1779,9 +1780,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_optimization" -version = "0.37.0" +version = "0.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4c8d2613ce06be5cf8160159eb468117ef6257eba744e1bf18125cca31ad" +checksum = "ea2600bc3bd557353511cd90b336943ae30e8807bce989a420cb004953fb940a" dependencies = [ "dashmap", "fxhash", @@ -1801,9 +1802,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_proposal" -version = "0.34.0" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02a8edf26ee1695c0137a829dbb8bb3c6681c1ae55e23ff45e0e0f41308e795f" +checksum = "637093e49ee993b16fb7bf8918f3d409c986fc77850440a3c779de85d1442cfb" dependencies = [ "either", "fxhash", @@ -1821,9 +1822,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_react" -version = "0.35.0" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72eabb27291ac7bef4f1f85e3aa7d335138dde1a1606b7d584e7f414882e5f3c" +checksum = "18bf8799eb49b25f0632b9e60b7871b3f77e18fecb1972e4932ba08005b5c85f" dependencies = [ "base64 0.13.0", "dashmap", @@ -1844,9 +1845,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_typescript" -version = "0.36.0" +version = "0.40.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc043fd29ceac49f13c1c994ba784f404cca3e189dd6cb771bfe905a0f776592" +checksum = "98099e3db58fb758715736ea9c8fa68d238e6527f0bfb4a3af0bf7ea063b9162" dependencies = [ "fxhash", "serde", @@ -1861,9 +1862,9 @@ dependencies = [ [[package]] name = "swc_ecma_utils" -version = "0.41.3" +version = "0.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bacaf860e4224e1a12bea8730c94de28f990f92685dad57aa572e3473043f7" +checksum = "3c811bca37142f7fe21ce800784db1d537645762ffe8d8a52e2a7179d8cc1723" dependencies = [ "once_cell", "scoped-tls", @@ -1876,9 +1877,9 @@ dependencies = [ [[package]] name = "swc_ecma_visit" -version = "0.35.2" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51ce688b7c984d0325261edb3ced4195790c7ac76982e269d2114ec04e3ae7c" +checksum = "78c6721dfbcb8bea64383edb0d59ccb02bc1e140024f2e0f8766792a14f5f466" dependencies = [ "num-bigint", "swc_atoms", @@ -1889,9 +1890,9 @@ dependencies = [ [[package]] name = "swc_ecmascript" -version = "0.57.0" +version = "0.63.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e41615d9e65c7b148950211dacd0b2343a646d84493b9c8efa8795ee1a6e2f4f" +checksum = "ba53c5582d6e5881b093ece9aaa4b561465afab0560abb19948f2c4bbff1bdb9" dependencies = [ "swc_ecma_ast", "swc_ecma_codegen", @@ -1999,9 +2000,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338" +checksum = "5241dd6f21443a3606b432718b166d3cedc962fd4b8bea54a8bc7f514ebda986" dependencies = [ "tinyvec_macros", ] @@ -2020,9 +2021,9 @@ checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" [[package]] name = "typenum" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" [[package]] name = "unicode-bidi" diff --git a/flow-libs/posthtml-parser.js.flow b/flow-libs/posthtml-parser.js.flow index ae5f4c5d24c..32ae1c9c942 100644 --- a/flow-libs/posthtml-parser.js.flow +++ b/flow-libs/posthtml-parser.js.flow @@ -22,5 +22,8 @@ declare module 'posthtml-parser' { } ) => PostHTMLNode; - declare module.exports: typeof parser; + declare module.exports: { + parser: typeof parser; + ... + } } diff --git a/flow-libs/posthtml-render.js.flow b/flow-libs/posthtml-render.js.flow index be6ab7f4d6e..ad4289c6415 100644 --- a/flow-libs/posthtml-render.js.flow +++ b/flow-libs/posthtml-render.js.flow @@ -12,7 +12,7 @@ declare module 'posthtml-render' { ... }; - declare var parser: ( + declare var render: ( tree: PostHTMLNode, options?: { singleTags?: Array, @@ -21,5 +21,8 @@ declare module 'posthtml-render' { } ) => string; - declare module.exports: typeof parser; + declare module.exports: { + render: typeof render; + ... + } } diff --git a/package.json b/package.json index e2e43da8ed5..892dab33b71 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "cross-env": "^7.0.0", "doctoc": "^1.4.0", "eslint": "^7.20.0", - "flow-bin": "0.158.0", + "flow-bin": "0.160.1", "glob": "^7.1.6", "gulp": "^4.0.2", "gulp-babel": "^8.0.0", diff --git a/packages/core/core/src/BundleGraph.js b/packages/core/core/src/BundleGraph.js index b62690d2770..54ae3c0f72f 100644 --- a/packages/core/core/src/BundleGraph.js +++ b/packages/core/core/src/BundleGraph.js @@ -64,7 +64,7 @@ export const bundleGraphEdgeTypes = { internal_async: 5, }; -type BundleGraphEdgeType = $Values; +export type BundleGraphEdgeType = $Values; type InternalSymbolResolution = {| asset: Asset, diff --git a/packages/core/core/src/Parcel.js b/packages/core/core/src/Parcel.js index 9aa0d713faa..70b3b24d79f 100644 --- a/packages/core/core/src/Parcel.js +++ b/packages/core/core/src/Parcel.js @@ -31,7 +31,10 @@ import {AbortController} from 'abortcontroller-polyfill/dist/cjs-ponyfill'; import {PromiseQueue} from '@parcel/utils'; import ParcelConfig from './ParcelConfig'; import logger from '@parcel/logger'; -import RequestTracker, {getWatcherOptions} from './RequestTracker'; +import RequestTracker, { + getWatcherOptions, + requestGraphEdgeTypes, +} from './RequestTracker'; import createValidationRequest from './requests/ValidationRequest'; import createParcelBuildRequest from './requests/ParcelBuildRequest'; import {Disposable} from '@parcel/events'; @@ -274,8 +277,12 @@ export default class Parcel { this.#requestedAssetIds.clear(); - // $FlowFixMe - dumpGraphToGraphViz(this.#requestTracker.graph, 'RequestGraph'); + dumpGraphToGraphViz( + // $FlowFixMe + this.#requestTracker.graph, + 'RequestGraph', + requestGraphEdgeTypes, + ); let event = { type: 'buildSuccess', diff --git a/packages/core/core/src/RequestTracker.js b/packages/core/core/src/RequestTracker.js index c705b074609..41def55de58 100644 --- a/packages/core/core/src/RequestTracker.js +++ b/packages/core/core/src/RequestTracker.js @@ -59,7 +59,7 @@ export const requestGraphEdgeTypes = { dirname: 7, }; -type RequestGraphEdgeType = $Values; +export type RequestGraphEdgeType = $Values; type RequestGraphOpts = {| ...ContentGraphOpts, @@ -70,6 +70,7 @@ type RequestGraphOpts = {| optionNodeIds: Set, unpredicatableNodeIds: Set, |}; + type SerializedRequestGraph = {| ...SerializedContentGraph, invalidNodeIds: Set, diff --git a/packages/core/core/src/dumpGraphToGraphViz.js b/packages/core/core/src/dumpGraphToGraphViz.js index 1441e5ca3e3..65ec13025cd 100644 --- a/packages/core/core/src/dumpGraphToGraphViz.js +++ b/packages/core/core/src/dumpGraphToGraphViz.js @@ -2,6 +2,8 @@ import type {Graph} from '@parcel/graph'; import type {AssetGraphNode, BundleGraphNode, Environment} from './types'; +import {bundleGraphEdgeTypes} from './BundleGraph'; +import {requestGraphEdgeTypes} from './RequestTracker'; import path from 'path'; import {fromProjectPathRelative} from './projectPath'; @@ -32,7 +34,7 @@ export default async function dumpGraphToGraphViz( // $FlowFixMe graph: Graph | Graph, name: string, - edgeTypes?: any, + edgeTypes?: typeof bundleGraphEdgeTypes | typeof requestGraphEdgeTypes, ): Promise { if ( process.env.PARCEL_BUILD_ENV === 'production' || @@ -130,15 +132,20 @@ export default async function dumpGraphToGraphViz( } n.set('label', label); } + let edgeNames; if (edgeTypes) { edgeNames = Object.fromEntries( Object.entries(edgeTypes).map(([k, v]) => [v, k]), ); } + for (let edge of graph.getAllEdges()) { let gEdge = g.addEdge(nodeId(edge.from), nodeId(edge.to)); - let color = edge.type != null ? TYPE_COLORS[edge.type] : null; + let color = null; + if (edge.type != 1 && edgeNames) { + color = TYPE_COLORS[edgeNames[edge.type]]; + } if (color != null) { gEdge.set('color', color); } diff --git a/packages/core/core/src/requests/ParcelBuildRequest.js b/packages/core/core/src/requests/ParcelBuildRequest.js index 56b690afe78..ea5a2a00215 100644 --- a/packages/core/core/src/requests/ParcelBuildRequest.js +++ b/packages/core/core/src/requests/ParcelBuildRequest.js @@ -14,6 +14,7 @@ import createBundleGraphRequest from './BundleGraphRequest'; import createWriteBundlesRequest from './WriteBundlesRequest'; import {assertSignalNotAborted} from '../utils'; import dumpGraphToGraphViz from '../dumpGraphToGraphViz'; +import {bundleGraphEdgeTypes} from '../BundleGraph'; type ParcelBuildRequestInput = {| optionsRef: SharedReference, @@ -75,7 +76,7 @@ async function run({input, api, options}: RunInput) { let bundleGraph = await api.runRequest(bundleGraphRequest); // $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 (Windows only) - dumpGraphToGraphViz(bundleGraph._graph, 'BundleGraph'); + dumpGraphToGraphViz(bundleGraph._graph, 'BundleGraph', bundleGraphEdgeTypes); let writeBundlesRequest = createWriteBundlesRequest({ bundleGraph, diff --git a/packages/core/core/src/resolveOptions.js b/packages/core/core/src/resolveOptions.js index b0992beba1d..1ce2e208571 100644 --- a/packages/core/core/src/resolveOptions.js +++ b/packages/core/core/src/resolveOptions.js @@ -108,14 +108,14 @@ export default async function resolveOptions( ), shouldPatchConsole: initialOptions.shouldPatchConsole ?? false, env: { - ...process.env, - ...initialOptions.env, ...(await loadDotEnv( initialOptions.env ?? {}, inputFS, path.join(projectRoot, 'index'), projectRoot, )), + ...process.env, + ...initialOptions.env, }, mode, shouldAutoInstall: initialOptions.shouldAutoInstall ?? false, diff --git a/packages/core/graph/src/Graph.js b/packages/core/graph/src/Graph.js index 5fa0e3ea94b..325296c5378 100644 --- a/packages/core/graph/src/Graph.js +++ b/packages/core/graph/src/Graph.js @@ -11,13 +11,13 @@ import nullthrows from 'nullthrows'; export type NullEdgeType = 1; export type GraphOpts = {| nodes?: Map, - adjacencyList?: SerializedAdjacencyList, + adjacencyList?: SerializedAdjacencyList, rootNodeId?: ?NodeId, |}; export type SerializedGraph = {| nodes: Map, - adjacencyList: SerializedAdjacencyList, + adjacencyList: SerializedAdjacencyList, rootNodeId: ?NodeId, |}; @@ -26,7 +26,7 @@ export const ALL_EDGE_TYPES: AllEdgeTypes = '@@all_edge_types'; export default class Graph { nodes: Map; - adjacencyList: AdjacencyList; + adjacencyList: AdjacencyList; rootNodeId: ?NodeId; constructor(opts: ?GraphOpts) { diff --git a/packages/core/integration-tests/test/html.js b/packages/core/integration-tests/test/html.js index 990a8344088..e1fa04cd7f4 100644 --- a/packages/core/integration-tests/test/html.js +++ b/packages/core/integration-tests/test/html.js @@ -467,6 +467,38 @@ describe('html', function() { assert.equal(html.length, 0); }); + it('should work with an invalid html file', async function() { + let inputFile = path.join( + __dirname, + '/integration/html-invalid/index.html', + ); + await bundle(inputFile, { + defaultTargetOptions: { + shouldOptimize: false, + }, + }); + + let outputFile = path.join(distDir, 'index.html'); + let html = await outputFS.readFile(outputFile, 'utf8'); + assert(html.includes('This is a paragraph')); + }); + + it("should work with html that doesn't include optional closing tags", async function() { + let inputFile = path.join( + __dirname, + '/integration/html-optional-closing-tags/index.html', + ); + await bundle(inputFile, { + defaultTargetOptions: { + shouldOptimize: false, + }, + }); + + let outputFile = path.join(distDir, 'index.html'); + let html = await outputFS.readFile(outputFile, 'utf8'); + assert(html.includes('Paragraph 1')); + }); + it('should read .htmlnanorc.json and minify HTML in production mode', async function() { await bundle( path.join(__dirname, '/integration/htmlnano-config/index.html'), diff --git a/packages/core/integration-tests/test/integration/html-invalid/index.html b/packages/core/integration-tests/test/integration/html-invalid/index.html new file mode 100644 index 00000000000..60e7ff060bb --- /dev/null +++ b/packages/core/integration-tests/test/integration/html-invalid/index.html @@ -0,0 +1,14 @@ + + + + + Invalid HTML file + + + + +

This is a paragraph.

  • This is a list.

+ + + + diff --git a/packages/core/integration-tests/test/integration/html-optional-closing-tags/index.html b/packages/core/integration-tests/test/integration/html-optional-closing-tags/index.html new file mode 100644 index 00000000000..0c6cd109d23 --- /dev/null +++ b/packages/core/integration-tests/test/integration/html-optional-closing-tags/index.html @@ -0,0 +1,9 @@ + + +Title + +

Paragraph 1 + +


+ +

Paragraph 2 diff --git a/packages/core/integration-tests/test/integration/sourcemap/.babelrc b/packages/core/integration-tests/test/integration/sourcemap/.babelrc deleted file mode 100644 index 1320b9a3272..00000000000 --- a/packages/core/integration-tests/test/integration/sourcemap/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@babel/preset-env"] -} diff --git a/packages/core/integration-tests/test/javascript.js b/packages/core/integration-tests/test/javascript.js index b9189a79169..e5f3e25ede9 100644 --- a/packages/core/integration-tests/test/javascript.js +++ b/packages/core/integration-tests/test/javascript.js @@ -2940,6 +2940,16 @@ describe('javascript', function() { assert.equal(output, 'productiontest'); }); + it('should overwrite environment variables from a file if passed', async function() { + let b = await bundle( + path.join(__dirname, '/integration/env-file/index.js'), + {env: {BAR: 'baz'}}, + ); + + let output = await run(b); + assert.equal(output, 'barbaz'); + }); + it('should error on process.env mutations', async function() { let filePath = path.join(__dirname, '/integration/env-mutate/index.js'); await assert.rejects(bundle(filePath), { diff --git a/packages/core/test-utils/package.json b/packages/core/test-utils/package.json index 8121e6194b2..41746b34ffb 100644 --- a/packages/core/test-utils/package.json +++ b/packages/core/test-utils/package.json @@ -21,8 +21,8 @@ "chalk": "^4.1.0", "ncp": "^2.0.0", "nullthrows": "^1.1.1", - "posthtml": "^0.16.4", - "posthtml-parser": "^0.9.0", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", "resolve": "^1.12.0", "ws": "^7.0.0" } diff --git a/packages/core/test-utils/src/utils.js b/packages/core/test-utils/src/utils.js index 2177941ff20..e513992b8b0 100644 --- a/packages/core/test-utils/src/utils.js +++ b/packages/core/test-utils/src/utils.js @@ -24,7 +24,7 @@ import path from 'path'; import url from 'url'; import WebSocket from 'ws'; import nullthrows from 'nullthrows'; -import postHtmlParse from 'posthtml-parser'; +import {parser as postHtmlParse} from 'posthtml-parser'; import postHtml from 'posthtml'; import EventEmitter from 'events'; diff --git a/packages/optimizers/htmlnano/package.json b/packages/optimizers/htmlnano/package.json index 6fd2a73bd24..6c738f9ff61 100644 --- a/packages/optimizers/htmlnano/package.json +++ b/packages/optimizers/htmlnano/package.json @@ -23,7 +23,7 @@ "@parcel/plugin": "2.0.0-rc.0", "htmlnano": "^1.0.1", "nullthrows": "^1.1.1", - "posthtml": "^0.16.4", + "posthtml": "^0.16.5", "svgo": "^2.4.0" } } diff --git a/packages/packagers/html/package.json b/packages/packagers/html/package.json index 6123c6495fe..3ad37a5bf89 100644 --- a/packages/packagers/html/package.json +++ b/packages/packagers/html/package.json @@ -24,6 +24,6 @@ "@parcel/types": "2.0.0-rc.0", "@parcel/utils": "2.0.0-rc.0", "nullthrows": "^1.1.1", - "posthtml": "^0.16.4" + "posthtml": "^0.16.5" } } diff --git a/packages/reporters/cli/src/CLIReporter.js b/packages/reporters/cli/src/CLIReporter.js index 3f08065018d..246f8175e5b 100644 --- a/packages/reporters/cli/src/CLIReporter.js +++ b/packages/reporters/cli/src/CLIReporter.js @@ -200,7 +200,7 @@ async function writeDiagnostic( writeOut(indentString(codeframe, indent), isError); } - if ((stack || codeframe) && hints.length > 0) { + if ((stack || codeframe) && (hints.length > 0 || documentation)) { writeOut(''); } diff --git a/packages/runtimes/hmr/src/loaders/hmr-runtime.js b/packages/runtimes/hmr/src/loaders/hmr-runtime.js index 53e2793f9a3..4b8da0d14d1 100644 --- a/packages/runtimes/hmr/src/loaders/hmr-runtime.js +++ b/packages/runtimes/hmr/src/loaders/hmr-runtime.js @@ -95,7 +95,9 @@ if ((!parent || !parent.isParcelRequire) && typeof WebSocket !== 'undefined') { if (data.type === 'update') { // Remove error overlay if there is one - removeErrorOverlay(); + if (typeof document !== 'undefined') { + removeErrorOverlay(); + } let assets = data.assets.filter(asset => asset.envHash === HMR_ENV_HASH); @@ -143,11 +145,13 @@ if ((!parent || !parent.isParcelRequire) && typeof WebSocket !== 'undefined') { ); } - // Render the fancy html overlay - removeErrorOverlay(); - var overlay = createErrorOverlay(data.diagnostics.html); - // $FlowFixMe - document.body.appendChild(overlay); + if (typeof document !== 'undefined') { + // Render the fancy html overlay + removeErrorOverlay(); + var overlay = createErrorOverlay(data.diagnostics.html); + // $FlowFixMe + document.body.appendChild(overlay); + } } }; ws.onerror = function(e) { diff --git a/packages/transformers/html/package.json b/packages/transformers/html/package.json index a80b37e1773..b1eb1ad5fd5 100644 --- a/packages/transformers/html/package.json +++ b/packages/transformers/html/package.json @@ -23,9 +23,9 @@ "@parcel/hash": "2.0.0-rc.0", "@parcel/plugin": "2.0.0-rc.0", "nullthrows": "^1.1.1", - "posthtml": "^0.16.4", - "posthtml-parser": "^0.9.0", - "posthtml-render": "^2.0.6", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", "semver": "^5.4.1" } } diff --git a/packages/transformers/html/src/HTMLTransformer.js b/packages/transformers/html/src/HTMLTransformer.js index 13b85e80dce..db7bf863f25 100644 --- a/packages/transformers/html/src/HTMLTransformer.js +++ b/packages/transformers/html/src/HTMLTransformer.js @@ -1,9 +1,9 @@ // @flow import {Transformer} from '@parcel/plugin'; -import parse from 'posthtml-parser'; +import {parser as parse} from 'posthtml-parser'; import nullthrows from 'nullthrows'; -import render from 'posthtml-render'; +import {render} from 'posthtml-render'; import semver from 'semver'; import collectDependencies from './dependencies'; import extractInlineAssets from './inline'; diff --git a/packages/transformers/js/core/Cargo.toml b/packages/transformers/js/core/Cargo.toml index 279d45252d5..27af8cd6b8f 100644 --- a/packages/transformers/js/core/Cargo.toml +++ b/packages/transformers/js/core/Cargo.toml @@ -8,10 +8,10 @@ edition = "2018" crate-type = ["rlib"] [dependencies] -swc_ecmascript = { version = "0.57.0", features = ["parser", "transforms", "module", "optimization", "react", "typescript", "utils", "visit", "codegen", "utils"] } -swc_ecma_preset_env = "0.38.0" -swc_common = { version = "0.11.6", features = ["tty-emitter", "sourcemap"] } -swc_atoms = "0.2.6" +swc_ecmascript = { version = "0.63.1", features = ["parser", "transforms", "module", "optimization", "react", "typescript", "utils", "visit", "codegen", "utils"] } +swc_ecma_preset_env = "0.42.1" +swc_common = { version = "0.12.1", features = ["tty-emitter", "sourcemap"] } +swc_atoms = "0.2.7" indoc = "1.0.3" serde = "1.0.123" serde_bytes = "0.11.5" diff --git a/packages/transformers/js/core/src/fs.rs b/packages/transformers/js/core/src/fs.rs index 836c4366313..b0c33849edc 100644 --- a/packages/transformers/js/core/src/fs.rs +++ b/packages/transformers/js/core/src/fs.rs @@ -26,7 +26,13 @@ pub fn inline_fs<'a>( ) -> impl Fold + 'a { InlineFS { filename: Path::new(filename).to_path_buf(), - collect: Collect::new(source_map, decls, Mark::fresh(Mark::root()), global_mark), + collect: Collect::new( + source_map, + decls, + Mark::fresh(Mark::root()), + global_mark, + false, + ), global_mark, project_root, deps, diff --git a/packages/transformers/js/core/src/hoist.rs b/packages/transformers/js/core/src/hoist.rs index 02b5d1d5972..e114daaead7 100644 --- a/packages/transformers/js/core/src/hoist.rs +++ b/packages/transformers/js/core/src/hoist.rs @@ -8,8 +8,8 @@ use swc_ecmascript::ast::*; use swc_ecmascript::visit::{Fold, FoldWith, Node, Visit, VisitWith}; use crate::utils::{ - match_import, match_member_expr, match_require, CodeHighlight, Diagnostic, DiagnosticSeverity, - SourceLocation, + match_import, match_member_expr, match_require, Bailout, BailoutReason, CodeHighlight, + Diagnostic, DiagnosticSeverity, SourceLocation, }; type IdentId = (JsWord, SyntaxContext); @@ -34,8 +34,9 @@ pub fn hoist( decls: HashSet, ignore_mark: Mark, global_mark: Mark, -) -> Result<(Module, HoistResult), Vec> { - let mut collect = Collect::new(source_map, decls, ignore_mark, global_mark); + trace_bailouts: bool, +) -> Result<(Module, HoistResult, Vec), Vec> { + let mut collect = Collect::new(source_map, decls, ignore_mark, global_mark, trace_bailouts); module.visit_with(&Invalid { span: DUMMY_SP } as _, &mut collect); let mut hoist = Hoist::new(module_id, &collect); @@ -44,7 +45,14 @@ pub fn hoist( return Err(hoist.diagnostics); } - Ok((module, hoist.get_result())) + if let Some(bailouts) = &collect.bailouts { + hoist + .diagnostics + .extend(bailouts.iter().map(|bailout| bailout.to_diagnostic())); + } + + let diagnostics = std::mem::take(&mut hoist.diagnostics); + Ok((module, hoist.get_result(), diagnostics)) } struct Hoist<'a> { @@ -554,7 +562,7 @@ impl<'a> Fold for Hoist<'a> { // If there are any non-static accesses of the namespace, don't perform any replacement. // This will be handled in the Ident visitor below, which replaces y -> $id$import$10b1f2ceae7ab64e. if specifier == "*" - && !self.collect.non_static_access.contains(&id!(ident)) + && !self.collect.non_static_access.contains_key(&id!(ident)) && !self.collect.non_const_bindings.contains_key(&id!(ident)) && !self.collect.non_static_requires.contains(source) { @@ -771,7 +779,7 @@ impl<'a> Fold for Hoist<'a> { self .imported_symbols .insert(name, (source.clone(), specifier.clone(), loc.clone())); - } else if self.collect.non_static_access.contains(&id!(node)) { + } else if self.collect.non_static_access.contains_key(&id!(node)) { let name: JsWord = format!("${}$importAsync${:x}", self.module_id, hash!(source)).into(); self @@ -1101,7 +1109,7 @@ pub struct Collect { should_wrap: bool, pub imports: HashMap, exports: HashMap, - non_static_access: HashSet, + non_static_access: HashMap>, non_const_bindings: HashMap>, non_static_requires: HashSet, wrapped_requires: HashSet, @@ -1110,6 +1118,7 @@ pub struct Collect { in_export_decl: bool, in_function: bool, in_assign: bool, + bailouts: Option>, } impl Collect { @@ -1118,6 +1127,7 @@ impl Collect { decls: HashSet, ignore_mark: Mark, global_mark: Mark, + trace_bailouts: bool, ) -> Self { Collect { source_map, @@ -1130,7 +1140,7 @@ impl Collect { should_wrap: false, imports: HashMap::new(), exports: HashMap::new(), - non_static_access: HashSet::new(), + non_static_access: HashMap::new(), non_const_bindings: HashMap::new(), non_static_requires: HashSet::new(), wrapped_requires: HashSet::new(), @@ -1139,6 +1149,7 @@ impl Collect { in_export_decl: false, in_function: false, in_assign: false, + bailouts: if trace_bailouts { Some(vec![]) } else { None }, } } } @@ -1150,6 +1161,21 @@ impl Visit for Collect { self.in_function = false; node.visit_children_with(self); self.in_module_this = false; + + if let Some(bailouts) = &mut self.bailouts { + for key in self.imports.keys() { + if let Some(spans) = self.non_static_access.get(key) { + for span in spans { + bailouts.push(Bailout { + loc: SourceLocation::from(&self.source_map, *span), + reason: BailoutReason::NonStaticAccess, + }) + } + } + } + + bailouts.sort_by(|a, b| a.loc.partial_cmp(&b.loc).unwrap()); + } } collect_visit_fn!(visit_function, Function); @@ -1317,6 +1343,7 @@ impl Visit for Collect { fn visit_return_stmt(&mut self, node: &ReturnStmt, _parent: &dyn Node) { if !self.in_function { self.should_wrap = true; + self.add_bailout(node.span, BailoutReason::TopLevelReturn); } node.visit_children_with(self) @@ -1378,6 +1405,7 @@ impl Visit for Collect { self.has_cjs_exports = true; if !is_static { self.static_cjs_exports = false; + self.add_bailout(node.span, BailoutReason::NonStaticExports); } } return; @@ -1387,7 +1415,8 @@ impl Visit for Collect { if ident.sym == exports && !self.decls.contains(&id!(ident)) { self.has_cjs_exports = true; if !is_static { - self.static_cjs_exports = false + self.static_cjs_exports = false; + self.add_bailout(node.span, BailoutReason::NonStaticExports); } } @@ -1395,11 +1424,16 @@ impl Visit for Collect { self.has_cjs_exports = true; self.static_cjs_exports = false; self.should_wrap = true; + self.add_bailout(node.span, BailoutReason::FreeModule); } // `import` isn't really an identifier... if !is_static && ident.sym != js_word!("import") { - self.non_static_access.insert(id!(ident)); + self + .non_static_access + .entry(id!(ident)) + .or_default() + .push(node.span); } return; } @@ -1408,6 +1442,7 @@ impl Visit for Collect { self.has_cjs_exports = true; if !is_static { self.static_cjs_exports = false; + self.add_bailout(node.span, BailoutReason::NonStaticExports); } } return; @@ -1439,11 +1474,21 @@ impl Visit for Collect { // declaration. We need to wrap the referenced module to preserve side effect ordering. if let Some(source) = self.match_require(node) { self.wrapped_requires.insert(source); + let span = match node { + Expr::Call(c) => c.span, + _ => unreachable!(), + }; + self.add_bailout(span, BailoutReason::NonTopLevelRequire); } if let Some(source) = match_import(node, self.ignore_mark) { self.non_static_requires.insert(source.clone()); self.wrapped_requires.insert(source); + let span = match node { + Expr::Call(c) => c.span, + _ => unreachable!(), + }; + self.add_bailout(span, BailoutReason::NonStaticDynamicImport); } match node { @@ -1457,12 +1502,19 @@ impl Visit for Collect { self.static_cjs_exports = false; if is_module { self.should_wrap = true; + self.add_bailout(ident.span, BailoutReason::FreeModule); + } else { + self.add_bailout(ident.span, BailoutReason::FreeExports); } } // `import` isn't really an identifier... if ident.sym != js_word!("import") { - self.non_static_access.insert(id!(ident)); + self + .non_static_access + .entry(id!(ident)) + .or_default() + .push(ident.span); } } _ => { @@ -1471,10 +1523,11 @@ impl Visit for Collect { } } - fn visit_this_expr(&mut self, _node: &ThisExpr, _parent: &dyn Node) { + fn visit_this_expr(&mut self, node: &ThisExpr, _parent: &dyn Node) { if self.in_module_this { self.has_cjs_exports = true; self.static_cjs_exports = false; + self.add_bailout(node.span, BailoutReason::FreeExports); } } @@ -1504,6 +1557,13 @@ impl Visit for Collect { self.static_cjs_exports = false; self.has_cjs_exports = true; self.should_wrap = true; + self.add_bailout(node.span, BailoutReason::ExportsReassignment); + } else if has_binding_identifier(pat, &"module".into(), &self.decls) { + // Same for `module`. If it is reassigned we can't correctly statically analyze. + self.static_cjs_exports = false; + self.has_cjs_exports = true; + self.should_wrap = true; + self.add_bailout(node.span, BailoutReason::ModuleReassignment); } } } @@ -1582,7 +1642,8 @@ impl Visit for Collect { match &**expr { Expr::Ident(ident) => { if ident.sym == js_word!("eval") && !self.decls.contains(&id!(ident)) { - self.should_wrap = true + self.should_wrap = true; + self.add_bailout(node.span, BailoutReason::Eval); } } Expr::Member(member) => { @@ -1609,6 +1670,7 @@ impl Visit for Collect { } else { self.non_static_requires.insert(source.clone()); self.wrapped_requires.insert(source); + self.add_bailout(node.span, BailoutReason::NonStaticDynamicImport); } expr.visit_with(node, self); @@ -1636,6 +1698,16 @@ impl Collect { self.wrapped_requires.insert(src.clone()); if kind != ImportKind::DynamicImport { self.non_static_requires.insert(src.clone()); + let span = match node { + Pat::Ident(id) => id.id.span, + Pat::Array(arr) => arr.span, + Pat::Object(obj) => obj.span, + Pat::Rest(rest) => rest.span, + Pat::Assign(assign) => assign.span, + Pat::Invalid(i) => i.span, + Pat::Expr(_) => DUMMY_SP, + }; + self.add_bailout(span, BailoutReason::NonTopLevelRequire); } } @@ -1663,6 +1735,7 @@ impl Collect { _ => { // Non-static. E.g. computed property. self.non_static_requires.insert(src.clone()); + self.add_bailout(object.span, BailoutReason::NonStaticDestructuring); continue; } }; @@ -1692,6 +1765,7 @@ impl Collect { _ => { // Non-static. self.non_static_requires.insert(src.clone()); + self.add_bailout(object.span, BailoutReason::NonStaticDestructuring); } } } @@ -1718,6 +1792,7 @@ impl Collect { // let {x, ...y} = require('y'); // Non-static. We don't know what keys are used. self.non_static_requires.insert(src.clone()); + self.add_bailout(object.span, BailoutReason::NonStaticDestructuring); } } } @@ -1725,6 +1800,16 @@ impl Collect { _ => { // Non-static. self.non_static_requires.insert(src.clone()); + let span = match node { + Pat::Ident(id) => id.id.span, + Pat::Array(arr) => arr.span, + Pat::Object(obj) => obj.span, + Pat::Rest(rest) => rest.span, + Pat::Assign(assign) => assign.span, + Pat::Invalid(i) => i.span, + Pat::Expr(_) => DUMMY_SP, + }; + self.add_bailout(span, BailoutReason::NonStaticDestructuring); } } } @@ -1761,6 +1846,15 @@ impl Collect { _ => {} } } + + fn add_bailout(&mut self, span: Span, reason: BailoutReason) { + if let Some(bailouts) = &mut self.bailouts { + bailouts.push(Bailout { + loc: SourceLocation::from(&self.source_map, span), + reason, + }) + } + } } fn has_binding_identifier(node: &Pat, sym: &JsWord, decls: &HashSet) -> bool { @@ -1847,6 +1941,7 @@ mod tests { collect_decls(&module), Mark::fresh(Mark::root()), global_mark, + false, ); module.visit_with(&Invalid { span: DUMMY_SP } as _, &mut collect); @@ -1990,7 +2085,7 @@ mod tests { collect.imports, map! { w!("x") => (w!("other"), w!("*"), false) } ); - assert_eq!(collect.non_static_access, set! {}); + assert_eq!(collect.non_static_access, map! {}); let (_collect, _code, hoist) = parse( r#" @@ -2012,7 +2107,7 @@ mod tests { collect.imports, map! { w!("x") => (w!("other"), w!("*"), false) } ); - assert_eq_set!(collect.non_static_access, set! { w!("x") }); + assert_eq_set!(collect.non_static_access.into_keys(), set! { w!("x") }); let (collect, _code, _hoist) = parse( r#" @@ -2024,7 +2119,7 @@ mod tests { collect.imports, map! { w!("x") => (w!("other"), w!("*"), false) } ); - assert_eq_set!(collect.non_static_access, set! { w!("x") }); + assert_eq_set!(collect.non_static_access.into_keys(), set! { w!("x") }); } #[test] @@ -2050,6 +2145,13 @@ mod tests { "#, ); assert!(collect.should_wrap); + + let (collect, _code, _hoist) = parse( + r#" + module = 2; + "#, + ); + assert!(collect.should_wrap); } #[test] @@ -2228,7 +2330,7 @@ mod tests { collect.imports, map! { w!("x") => (w!("other"), w!("*"), true) } ); - assert_eq_set!(collect.non_static_access, set! {}); + assert_eq_set!(collect.non_static_access.into_keys(), set! {}); assert_eq!(collect.non_static_requires, set! {}); assert_eq!(collect.wrapped_requires, set! {w!("other")}); @@ -2244,7 +2346,7 @@ mod tests { collect.imports, map! { w!("x") => (w!("other"), w!("*"), true) } ); - assert_eq_set!(collect.non_static_access, set! { w!("x") }); + assert_eq_set!(collect.non_static_access.into_keys(), set! { w!("x") }); assert_eq!(collect.non_static_requires, set! {}); assert_eq!(collect.wrapped_requires, set! {w!("other")}); @@ -2285,7 +2387,7 @@ mod tests { collect.imports, map! { w!("x") => (w!("other"), w!("*"), true) } ); - assert_eq_set!(collect.non_static_access, set! {}); + assert_eq_set!(collect.non_static_access.into_keys(), set! {}); assert_eq!(collect.non_static_requires, set! {}); assert_eq!(collect.wrapped_requires, set! {w!("other")}); @@ -2298,7 +2400,7 @@ mod tests { collect.imports, map! { w!("x") => (w!("other"), w!("*"), true) } ); - assert_eq_set!(collect.non_static_access, set! { w!("x") }); + assert_eq_set!(collect.non_static_access.into_keys(), set! { w!("x") }); assert_eq!(collect.non_static_requires, set! {}); assert_eq!(collect.wrapped_requires, set! {w!("other")}); @@ -2335,7 +2437,7 @@ mod tests { collect.imports, map! { w!("x") => (w!("other"), w!("*"), true) } ); - assert_eq_set!(collect.non_static_access, set! {}); + assert_eq_set!(collect.non_static_access.into_keys(), set! {}); assert_eq!(collect.non_static_requires, set! {}); assert_eq!(collect.wrapped_requires, set! {w!("other")}); @@ -2348,7 +2450,7 @@ mod tests { collect.imports, map! { w!("x") => (w!("other"), w!("*"), true) } ); - assert_eq_set!(collect.non_static_access, set! { w!("x") }); + assert_eq_set!(collect.non_static_access.into_keys(), set! { w!("x") }); assert_eq!(collect.non_static_requires, set! {}); assert_eq!(collect.wrapped_requires, set! {w!("other")}); diff --git a/packages/transformers/js/core/src/lib.rs b/packages/transformers/js/core/src/lib.rs index 280d68a22ca..112cb43974b 100644 --- a/packages/transformers/js/core/src/lib.rs +++ b/packages/transformers/js/core/src/lib.rs @@ -83,6 +83,7 @@ pub struct Config { supports_module_workers: bool, is_library: bool, is_esm_output: bool, + trace_bailouts: bool, } #[derive(Serialize, Debug, Deserialize, Default)] @@ -381,10 +382,12 @@ pub fn transform(config: Config) -> Result { decls, ignore_mark, global_mark, + config.trace_bailouts, ); match res { - Ok((module, hoist_result)) => { + Ok((module, hoist_result, hoist_diagnostics)) => { result.hoist_result = Some(hoist_result); + diagnostics.extend(hoist_diagnostics); module } Err(diagnostics) => { diff --git a/packages/transformers/js/core/src/utils.rs b/packages/transformers/js/core/src/utils.rs index 6b55938e4ab..34d22c05017 100644 --- a/packages/transformers/js/core/src/utils.rs +++ b/packages/transformers/js/core/src/utils.rs @@ -1,3 +1,4 @@ +use std::cmp::Ordering; use std::collections::HashSet; use serde::{Deserialize, Serialize}; @@ -170,6 +171,18 @@ impl SourceLocation { } } +impl PartialOrd for SourceLocation { + fn partial_cmp(&self, other: &SourceLocation) -> Option { + if self.start_line < other.start_line { + Some(Ordering::Less) + } else if self.start_line == other.start_line { + self.start_col.partial_cmp(&other.start_col) + } else { + Some(Ordering::Greater) + } + } +} + #[derive(Serialize, Deserialize, Debug)] pub struct CodeHighlight { pub message: Option, @@ -201,3 +214,90 @@ pub enum SourceType { Script, Module, } + +pub struct Bailout { + pub loc: SourceLocation, + pub reason: BailoutReason, +} + +impl Bailout { + pub fn to_diagnostic(&self) -> Diagnostic { + let (message, documentation_url) = self.reason.info(); + Diagnostic { + message: message.into(), + documentation_url: Some(documentation_url.into()), + code_highlights: Some(vec![CodeHighlight { + loc: self.loc.clone(), + message: None, + }]), + show_environment: false, + severity: DiagnosticSeverity::Warning, + hints: None, + } + } +} + +pub enum BailoutReason { + NonTopLevelRequire, + NonStaticDestructuring, + TopLevelReturn, + Eval, + NonStaticExports, + FreeModule, + FreeExports, + ExportsReassignment, + ModuleReassignment, + NonStaticDynamicImport, + NonStaticAccess, +} + +impl BailoutReason { + fn info(&self) -> (&str, &str) { + match self { + BailoutReason::NonTopLevelRequire => ( + "Conditional or non-top-level `require()` call. This causes the resolved module and all dependendencies to be wrapped.", + "https://v2.parceljs.org/features/scope-hoisting/#avoid-conditional-require()" + ), + BailoutReason::NonStaticDestructuring => ( + "Non-static destructuring of `require` or dynamic `import()`. This causes all exports of the resolved module to be included.", + "https://v2.parceljs.org/features/scope-hoisting/#commonjs" + ), + BailoutReason::TopLevelReturn => ( + "Module contains a top-level `return` statement. This causes the module to be wrapped in a function and tree shaking to be disabled.", + "https://v2.parceljs.org/features/scope-hoisting/#avoid-top-level-return" + ), + BailoutReason::Eval => ( + "Module contains usage of `eval`. This causes the module to be wrapped in a function and minification to be disabled.", + "https://v2.parceljs.org/features/scope-hoisting/#avoid-eval" + ), + BailoutReason::NonStaticExports => ( + "Non-static access of CommonJS `exports` object. This causes tree shaking to be disabled for the module.", + "https://v2.parceljs.org/features/scope-hoisting/#commonjs" + ), + BailoutReason::FreeModule => ( + "Unknown usage of CommonJS `module` object. This causes the module to be wrapped, and tree shaking to be disabled.", + "https://v2.parceljs.org/features/scope-hoisting/#commonjs" + ), + BailoutReason::FreeExports => ( + "Unknown usage of CommonJS `exports` object. This causes tree shaking to be disabled.", + "https://v2.parceljs.org/features/scope-hoisting/#commonjs" + ), + BailoutReason::ExportsReassignment => ( + "Module contains a reassignment of the CommonJS `exports` object. This causes the module to be wrapped and tree-shaking to be disabled.", + "https://v2.parceljs.org/features/scope-hoisting/#avoid-module-and-exports-re-assignment" + ), + BailoutReason::ModuleReassignment => ( + "Module contains a reassignment of the CommonJS `module` object. This causes the module to be wrapped and tree-shaking to be disabled.", + "https://v2.parceljs.org/features/scope-hoisting/#avoid-module-and-exports-re-assignment" + ), + BailoutReason::NonStaticDynamicImport => ( + "Unknown dynamic import usage. This causes tree shaking to be disabled for the resolved module.", + "https://v2.parceljs.org/features/scope-hoisting/#dynamic-imports" + ), + BailoutReason::NonStaticAccess => ( + "Non-static access of an `import` or `require`. This causes tree shaking to be disabled for the resolved module.", + "https://v2.parceljs.org/features/scope-hoisting/#dynamic-member-accesses" + ), + } + } +} diff --git a/packages/transformers/js/src/JSTransformer.js b/packages/transformers/js/src/JSTransformer.js index 87b28c401f1..4a3eee31836 100644 --- a/packages/transformers/js/src/JSTransformer.js +++ b/packages/transformers/js/src/JSTransformer.js @@ -400,6 +400,7 @@ export default (new Transformer({ supports_module_workers: supportsModuleWorkers, is_library: asset.env.isLibrary, is_esm_output: asset.env.outputFormat === 'esmodule', + trace_bailouts: options.logLevel === 'verbose', }); let convertLoc = loc => { diff --git a/packages/transformers/posthtml/package.json b/packages/transformers/posthtml/package.json index 64f138a57ae..b9180495d18 100644 --- a/packages/transformers/posthtml/package.json +++ b/packages/transformers/posthtml/package.json @@ -23,9 +23,9 @@ "@parcel/plugin": "2.0.0-rc.0", "@parcel/utils": "2.0.0-rc.0", "nullthrows": "^1.1.1", - "posthtml": "^0.16.4", - "posthtml-parser": "^0.9.0", - "posthtml-render": "^2.0.6", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", "semver": "^5.4.1" } } diff --git a/packages/transformers/posthtml/src/PostHTMLTransformer.js b/packages/transformers/posthtml/src/PostHTMLTransformer.js index c3767d1c175..49d3b3f7606 100644 --- a/packages/transformers/posthtml/src/PostHTMLTransformer.js +++ b/packages/transformers/posthtml/src/PostHTMLTransformer.js @@ -4,8 +4,8 @@ import {Transformer} from '@parcel/plugin'; import path from 'path'; import posthtml from 'posthtml'; -import parse from 'posthtml-parser'; -import render from 'posthtml-render'; +import {parser as parse} from 'posthtml-parser'; +import {render} from 'posthtml-render'; import nullthrows from 'nullthrows'; import semver from 'semver'; import {relativePath} from '@parcel/utils'; diff --git a/packages/transformers/svg/package.json b/packages/transformers/svg/package.json index 86db0487877..6d83419813f 100644 --- a/packages/transformers/svg/package.json +++ b/packages/transformers/svg/package.json @@ -23,9 +23,9 @@ "@parcel/hash": "2.0.0-rc.0", "@parcel/plugin": "2.0.0-rc.0", "nullthrows": "^1.1.1", - "posthtml": "^0.16.4", - "posthtml-parser": "^0.9.0", - "posthtml-render": "^2.0.6", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", "semver": "^5.4.1" } } diff --git a/packages/transformers/svg/src/SVGTransformer.js b/packages/transformers/svg/src/SVGTransformer.js index 21667f797de..2ad54bb13a3 100644 --- a/packages/transformers/svg/src/SVGTransformer.js +++ b/packages/transformers/svg/src/SVGTransformer.js @@ -3,8 +3,8 @@ import {Transformer} from '@parcel/plugin'; import nullthrows from 'nullthrows'; import semver from 'semver'; -import parse from 'posthtml-parser'; -import render from 'posthtml-render'; +import {parser as parse} from 'posthtml-parser'; +import {render} from 'posthtml-render'; import collectDependencies from './dependencies'; import extractInlineAssets from './inline'; diff --git a/yarn.lock b/yarn.lock index 24cfacb8237..c4176549c41 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5029,6 +5029,13 @@ domhandler@^4.0.0, domhandler@^4.2.0: dependencies: domelementtype "^2.2.0" +domhandler@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.2.tgz#e825d721d19a86b8c201a35264e226c678ee755f" + integrity sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w== + dependencies: + domelementtype "^2.2.0" + domutils@^1.5.1, domutils@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" @@ -6083,10 +6090,10 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== -flow-bin@0.158.0: - version "0.158.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.158.0.tgz#0a09763d41eb8ec7135ced6a3b9f8fa370a393d8" - integrity sha512-Gk5md8XTwk/M+J5M+rFyS1LJfFen6ldY60jM9+meWixlKf4b0vwdoUO8R7oo471pze+GY+blrnskUeqLDxFJfg== +flow-bin@0.160.1: + version "0.160.1" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.160.1.tgz#ae24ad6def1f05ae37789b6cc332b58975d29de0" + integrity sha512-LvQ9lB/vwW+lPjYIyACcGQCSLvL9f9hOM9jJJtfHQRrIgIShWqjvyv5V24M57HSxh0+6dBbVDYhUiZjjeArf7A== flush-write-stream@^1.0.0, flush-write-stream@^1.0.2: version "1.1.1" @@ -7046,12 +7053,12 @@ htmlparser2@^6.0.0: entities "^2.0.0" htmlparser2@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-7.1.1.tgz#ef251d16e5b40818ba162aa24bc051c297eb3f76" - integrity sha512-hZb0lfG0hbhR/hB879zbBr8Opv0Be9Zp+JYHgqTw5epF++aotu/zmMTPLy/60iJyR1MaD/3pYRp7xYteXsZMEA== + version "7.1.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-7.1.2.tgz#587923d38f03bc89e03076e00cba2c7473f37f7c" + integrity sha512-d6cqsbJba2nRdg8WW2okyD4ceonFHn9jLFxhwlNcLhQWcFPdxXeJulgOLjLKtAK9T6ahd+GQNZwG9fjmGW7lyg== dependencies: domelementtype "^2.0.1" - domhandler "^4.0.0" + domhandler "^4.2.2" domutils "^2.8.0" entities "^3.0.1" @@ -10546,7 +10553,7 @@ posthtml-obfuscate@^0.1.5: resolved "https://registry.yarnpkg.com/posthtml-obfuscate/-/posthtml-obfuscate-0.1.5.tgz#d65f6642c96349002d33a2208845b2f7517d0fc8" integrity sha1-1l9mQsljSQAtM6IgiEWy91F9D8g= -posthtml-parser@^0.10.0: +posthtml-parser@^0.10.0, posthtml-parser@^0.10.1: version "0.10.1" resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.10.1.tgz#63c41931a9339cc2c32aba14f06286d98f107abf" integrity sha512-i7w2QEHqiGtsvNNPty0Mt/+ERch7wkgnFh3+JnBI2VgDbGlBqKW9eDVd3ENUhE1ujGFe3e3E/odf7eKhvLUyDg==