mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Merge branch 'master' into devel
This commit is contained in:
102
History.md
102
History.md
@@ -5,6 +5,106 @@
|
||||
this is to prevent duplicate name error on reloads. Initial data is now
|
||||
properly serialized.
|
||||
|
||||
## v1.5, 2017-05-30
|
||||
|
||||
* The `meteor-base` package implies a new `dynamic-import` package, which
|
||||
provides runtime support for [the proposed ECMAScript dynamic
|
||||
`import(...)` syntax](https://github.com/tc39/proposal-dynamic-import),
|
||||
enabling asynchronous module fetching or "code splitting." If your app
|
||||
does not use the `meteor-base` package, you can use the package by
|
||||
simply running `meteor add dynamic-import`. See this [blog
|
||||
post](https://blog.meteor.com/meteor-1-5-react-loadable-f029a320e59c)
|
||||
and [PR #8327](https://github.com/meteor/meteor/pull/8327) for more
|
||||
information about how dynamic `import(...)` works in Meteor, and how to
|
||||
use it in your applications.
|
||||
|
||||
* The `ecmascript-runtime` package, which provides polyfills for various
|
||||
new ECMAScript runtime APIs and language features, has been split into
|
||||
`ecmascript-runtime-client` and `ecmascript-runtime-server`, to reflect
|
||||
the different needs of browsers versus Node 4. The client runtime now
|
||||
relies on the `core-js` library found in the `node_modules` directory of
|
||||
the application, rather than a private duplicate installed via
|
||||
`Npm.depends`. This is unlikely to be a disruptive change for most
|
||||
developers, since the `babel-runtime` npm package is expected to be
|
||||
installed, and `core-js` is a dependency of `babel-runtime`, so
|
||||
`node_modules/core-js` should already be present. If that's not the
|
||||
case, just run `meteor npm install --save core-js` to install it.
|
||||
|
||||
* The `npm` npm package has been upgraded to version 4.6.1.
|
||||
|
||||
* The `meteor-babel` npm package has been upgraded to version 0.21.4,
|
||||
enabling the latest Reify compiler and the transform-class-properties
|
||||
plugin, among other improvements.
|
||||
|
||||
* The `reify` npm package has been upgraded to version 0.11.21, fixing
|
||||
[issue #8595](https://github.com/meteor/meteor/issues/8595) and
|
||||
improving compilation and runtime performance.
|
||||
|
||||
> Note: With this version of Reify, `import` declarations are compiled to
|
||||
`module.watch(require(id), ...)` instead of `module.importSync(id, ...)`
|
||||
or the older `module.import(id, ...)`. The behavior of the compiled code
|
||||
should be the same as before, but the details seemed different enough to
|
||||
warrant a note.
|
||||
|
||||
* The `install` npm package has been upgraded to version 0.10.1.
|
||||
|
||||
* The `meteor-promise` npm package has been upgraded to version 0.8.4.
|
||||
|
||||
* The `uglify-js` npm package has been upgraded to version 3.0.13, fixing
|
||||
[#8704](https://github.com/meteor/meteor/issues/8704).
|
||||
|
||||
* If you're using the `standard-minifier-js` Meteor package, as most
|
||||
Meteor developers do, it will now produce a detailed analysis of package
|
||||
and module sizes within your production `.js` bundle whenever you run
|
||||
`meteor build` or `meteor run --production`. These data are served by
|
||||
the application web server at the same URL as the minified `.js` bundle,
|
||||
except with a `.stats.json` file extension instead of `.js`. If you're
|
||||
using a different minifier plugin, and would like to support similar
|
||||
functionality, refer to
|
||||
[these](https://github.com/meteor/meteor/pull/8327/commits/084801237a8c288d99ec82b0fbc1c76bdf1aab16)
|
||||
[commits](https://github.com/meteor/meteor/pull/8327/commits/1c8bc7353e9a8d526880634a58c506b423c4a55e)
|
||||
for inspiration.
|
||||
|
||||
* To visualize the bundle size data produced by `standard-minifier-js`,
|
||||
run `meteor add bundle-visualizer` and then start your development
|
||||
server in production mode with `meteor run --production`. Be sure to
|
||||
remove the `bundle-visualizer` package before actually deploying your
|
||||
app, or the visualization will be displayed to your users.
|
||||
|
||||
* If you've been developing an app with multiple versions of Meteor, or
|
||||
testing with beta versions, and you haven't recently run `meteor reset`,
|
||||
your `.meteor/local/bundler-cache` directory may have become quite
|
||||
large. This is just a friendly reminder that this directory is perfectly
|
||||
safe to delete, and Meteor will repopulate it with only the most recent
|
||||
cached bundles.
|
||||
|
||||
* Apps created with `meteor create --bare` now use the `static-html`
|
||||
package for processing `.html` files instead of `blaze-html-templates`,
|
||||
to avoid large unnecessary dependencies like the `jquery` package.
|
||||
|
||||
* Babel plugins now receive file paths without leading `/` characters,
|
||||
which should prevent confusion about whether the path should be treated
|
||||
as absolute. [PR #8610](https://github.com/meteor/meteor/pull/8610)
|
||||
|
||||
* It is now possible to override the Cordova iOS and/or Android
|
||||
compatibility version by setting the `METEOR_CORDOVA_COMPAT_VERSION_IOS`
|
||||
and/or `METEOR_CORDOVA_COMPAT_VERSION_ANDROID` environment variables.
|
||||
[PR #8581](https://github.com/meteor/meteor/pull/8581)
|
||||
|
||||
* Modules in `node_modules` directories will no longer automatically have
|
||||
access to the `Buffer` polyfill on the client, since that polyfill
|
||||
contributed more than 22KB of minified JavaScript to the client bundle,
|
||||
and was rarely used. If you really need the Buffer API on the client,
|
||||
you should now obtain it explicitly with `require("buffer").Buffer`.
|
||||
[Issue #8645](https://github.com/meteor/meteor/issues/8645).
|
||||
|
||||
* Packages in `node_modules` directories are now considered non-portable
|
||||
(and thus may be automatically rebuilt for the current architecture), if
|
||||
their `package.json` files contain any of the following install hooks:
|
||||
`install`, `preinstall`, or `postinstall`. Previously, a package was
|
||||
considered non-portable only if it contained any `.node` binary modules.
|
||||
[Issue #8225](https://github.com/meteor/meteor/issues/8225)
|
||||
|
||||
## v1.4.4.3, 2017-05-22
|
||||
|
||||
* Node has been upgraded to version 4.8.3.
|
||||
@@ -310,6 +410,8 @@
|
||||
fixing [#8021](https://github.com/meteor/meteor/issues/8021) and
|
||||
[#7662](https://github.com/meteor/meteor/issues/7662).
|
||||
|
||||
* The `reify` npm package has been upgraded to 0.4.7.
|
||||
|
||||
* Added support for frame-ancestors CSP option in browser-policy.
|
||||
[#7970](https://github.com/meteor/meteor/pull/7970)
|
||||
|
||||
|
||||
2
meteor
2
meteor
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BUNDLE_VERSION=4.7.27
|
||||
BUNDLE_VERSION=4.8.17
|
||||
|
||||
# OS Check. Put here because here is where we download the precompiled
|
||||
# bundles that are arch specific.
|
||||
|
||||
132
packages/babel-compiler/.npm/package/npm-shrinkwrap.json
generated
132
packages/babel-compiler/.npm/package/npm-shrinkwrap.json
generated
@@ -81,9 +81,9 @@
|
||||
"from": "babel-helper-is-void-0@>=0.0.1 <0.0.2"
|
||||
},
|
||||
"babel-helper-mark-eval-scopes": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.0.3.tgz",
|
||||
"from": "babel-helper-mark-eval-scopes@>=0.0.3 <0.0.4"
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.1.1.tgz",
|
||||
"from": "babel-helper-mark-eval-scopes@>=0.1.1 <0.2.0"
|
||||
},
|
||||
"babel-helper-optimise-call-expression": {
|
||||
"version": "6.24.1",
|
||||
@@ -96,9 +96,9 @@
|
||||
"from": "babel-helper-regex@>=6.24.1 <7.0.0"
|
||||
},
|
||||
"babel-helper-remove-or-void": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.0.1.tgz",
|
||||
"from": "babel-helper-remove-or-void@>=0.0.1 <0.0.2"
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.1.1.tgz",
|
||||
"from": "babel-helper-remove-or-void@>=0.1.1 <0.2.0"
|
||||
},
|
||||
"babel-helper-replace-supers": {
|
||||
"version": "6.24.1",
|
||||
@@ -131,15 +131,15 @@
|
||||
"from": "babel-plugin-minify-constant-folding@>=0.0.4 <0.0.5",
|
||||
"dependencies": {
|
||||
"jsesc": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.0.tgz",
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz",
|
||||
"from": "jsesc@>=2.4.0 <3.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-plugin-minify-dead-code-elimination": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.1.4.tgz",
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.1.6.tgz",
|
||||
"from": "babel-plugin-minify-dead-code-elimination@>=0.1.3 <0.2.0"
|
||||
},
|
||||
"babel-plugin-minify-flip-comparisons": {
|
||||
@@ -199,6 +199,11 @@
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz",
|
||||
"from": "babel-plugin-syntax-async-generators@>=6.13.0 <7.0.0"
|
||||
},
|
||||
"babel-plugin-syntax-class-properties": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
|
||||
"from": "babel-plugin-syntax-class-properties@>=6.8.0 <7.0.0"
|
||||
},
|
||||
"babel-plugin-syntax-dynamic-import": {
|
||||
"version": "6.18.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
|
||||
@@ -224,6 +229,11 @@
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
|
||||
"from": "babel-plugin-syntax-trailing-function-commas@>=6.22.0 <7.0.0"
|
||||
},
|
||||
"babel-plugin-transform-class-properties": {
|
||||
"version": "6.24.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz",
|
||||
"from": "babel-plugin-transform-class-properties@>=6.24.1 <7.0.0"
|
||||
},
|
||||
"babel-plugin-transform-es2015-arrow-functions": {
|
||||
"version": "6.22.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
|
||||
@@ -270,9 +280,9 @@
|
||||
"from": "babel-plugin-transform-es2015-modules-commonjs@>=6.22.0 <7.0.0"
|
||||
},
|
||||
"babel-plugin-transform-es2015-modules-reify": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.7.0.tgz",
|
||||
"from": "babel-plugin-transform-es2015-modules-reify@>=0.7.0 <0.8.0"
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-reify/-/babel-plugin-transform-es2015-modules-reify-0.11.0.tgz",
|
||||
"from": "babel-plugin-transform-es2015-modules-reify@>=0.11.0 <0.12.0"
|
||||
},
|
||||
"babel-plugin-transform-es2015-object-super": {
|
||||
"version": "6.24.1",
|
||||
@@ -330,18 +340,18 @@
|
||||
"from": "babel-plugin-transform-inline-consecutive-adds@>=0.0.2 <0.0.3"
|
||||
},
|
||||
"babel-plugin-transform-member-expression-literals": {
|
||||
"version": "6.8.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.8.1.tgz",
|
||||
"version": "6.8.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.8.3.tgz",
|
||||
"from": "babel-plugin-transform-member-expression-literals@>=6.8.1 <7.0.0"
|
||||
},
|
||||
"babel-plugin-transform-merge-sibling-variables": {
|
||||
"version": "6.8.2",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.8.2.tgz",
|
||||
"version": "6.8.4",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.8.4.tgz",
|
||||
"from": "babel-plugin-transform-merge-sibling-variables@>=6.8.2 <7.0.0"
|
||||
},
|
||||
"babel-plugin-transform-minify-booleans": {
|
||||
"version": "6.8.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.8.0.tgz",
|
||||
"version": "6.8.2",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.8.2.tgz",
|
||||
"from": "babel-plugin-transform-minify-booleans@>=6.8.0 <7.0.0"
|
||||
},
|
||||
"babel-plugin-transform-object-rest-spread": {
|
||||
@@ -350,8 +360,8 @@
|
||||
"from": "babel-plugin-transform-object-rest-spread@>=6.22.0 <7.0.0"
|
||||
},
|
||||
"babel-plugin-transform-property-literals": {
|
||||
"version": "6.8.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.1.tgz",
|
||||
"version": "6.8.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.3.tgz",
|
||||
"from": "babel-plugin-transform-property-literals@>=6.8.1 <7.0.0"
|
||||
},
|
||||
"babel-plugin-transform-react-display-name": {
|
||||
@@ -385,13 +395,13 @@
|
||||
"from": "babel-plugin-transform-regexp-constructors@>=0.0.5 <0.0.6"
|
||||
},
|
||||
"babel-plugin-transform-remove-console": {
|
||||
"version": "6.8.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.8.1.tgz",
|
||||
"version": "6.8.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.8.3.tgz",
|
||||
"from": "babel-plugin-transform-remove-console@>=6.8.0 <7.0.0"
|
||||
},
|
||||
"babel-plugin-transform-remove-debugger": {
|
||||
"version": "6.8.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.8.1.tgz",
|
||||
"version": "6.8.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.8.3.tgz",
|
||||
"from": "babel-plugin-transform-remove-debugger@>=6.8.0 <7.0.0"
|
||||
},
|
||||
"babel-plugin-transform-remove-undefined": {
|
||||
@@ -405,8 +415,8 @@
|
||||
"from": "babel-plugin-transform-runtime@>=6.22.0 <7.0.0"
|
||||
},
|
||||
"babel-plugin-transform-simplify-comparison-operators": {
|
||||
"version": "6.8.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.8.1.tgz",
|
||||
"version": "6.8.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.8.3.tgz",
|
||||
"from": "babel-plugin-transform-simplify-comparison-operators@>=6.8.1 <7.0.0"
|
||||
},
|
||||
"babel-plugin-transform-strict-mode": {
|
||||
@@ -415,8 +425,8 @@
|
||||
"from": "babel-plugin-transform-strict-mode@>=6.24.1 <7.0.0"
|
||||
},
|
||||
"babel-plugin-transform-undefined-to-void": {
|
||||
"version": "6.8.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.8.0.tgz",
|
||||
"version": "6.8.2",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.8.2.tgz",
|
||||
"from": "babel-plugin-transform-undefined-to-void@>=6.8.0 <7.0.0"
|
||||
},
|
||||
"babel-preset-babili": {
|
||||
@@ -465,8 +475,8 @@
|
||||
"from": "babel-types@>=6.22.0 <7.0.0"
|
||||
},
|
||||
"babylon": {
|
||||
"version": "6.16.1",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz",
|
||||
"version": "6.17.1",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.1.tgz",
|
||||
"from": "babylon@>=6.15.0 <7.0.0"
|
||||
},
|
||||
"balanced-match": {
|
||||
@@ -477,7 +487,7 @@
|
||||
"brace-expansion": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz",
|
||||
"from": "brace-expansion@>=1.0.0 <2.0.0"
|
||||
"from": "brace-expansion@>=1.1.7 <2.0.0"
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
@@ -500,8 +510,8 @@
|
||||
"from": "core-js@>=2.4.0 <3.0.0"
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.3.tgz",
|
||||
"version": "2.6.8",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
|
||||
"from": "debug@>=2.1.1 <3.0.0"
|
||||
},
|
||||
"detect-indent": {
|
||||
@@ -580,9 +590,9 @@
|
||||
"from": "loose-envify@>=1.0.0 <2.0.0"
|
||||
},
|
||||
"meteor-babel": {
|
||||
"version": "0.20.1",
|
||||
"resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.20.1.tgz",
|
||||
"from": "meteor-babel@0.20.1"
|
||||
"version": "0.21.4",
|
||||
"resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-0.21.4.tgz",
|
||||
"from": "meteor-babel@0.21.4"
|
||||
},
|
||||
"meteor-babel-helpers": {
|
||||
"version": "0.0.3",
|
||||
@@ -590,8 +600,8 @@
|
||||
"from": "meteor-babel-helpers@0.0.3"
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz",
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"from": "minimatch@>=3.0.2 <4.0.0"
|
||||
},
|
||||
"minimist": {
|
||||
@@ -599,15 +609,25 @@
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"from": "minimist@0.0.8"
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.0.2.tgz",
|
||||
"from": "minipass@>=2.0.0 <3.0.0"
|
||||
},
|
||||
"minizlib": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.3.tgz",
|
||||
"from": "minizlib@>=1.0.3 <2.0.0"
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"from": "mkdirp@>=0.5.1 <0.6.0"
|
||||
},
|
||||
"ms": {
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
|
||||
"from": "ms@0.7.2"
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"from": "ms@2.0.0"
|
||||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
@@ -640,8 +660,8 @@
|
||||
"from": "regenerate@>=1.2.1 <2.0.0"
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.10.3",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz",
|
||||
"version": "0.10.5",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
|
||||
"from": "regenerator-runtime@>=0.10.0 <0.11.0"
|
||||
},
|
||||
"regenerator-transform": {
|
||||
@@ -672,15 +692,20 @@
|
||||
}
|
||||
},
|
||||
"reify": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/reify/-/reify-0.7.4.tgz",
|
||||
"from": "reify@>=0.7.2 <0.8.0"
|
||||
"version": "0.11.21",
|
||||
"resolved": "https://registry.npmjs.org/reify/-/reify-0.11.21.tgz",
|
||||
"from": "reify@>=0.11.18 <0.12.0"
|
||||
},
|
||||
"repeating": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
|
||||
"from": "repeating@>=2.0.0 <3.0.0"
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
|
||||
"from": "semver@>=5.3.0 <6.0.0"
|
||||
},
|
||||
"slash": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
|
||||
@@ -692,8 +717,8 @@
|
||||
"from": "source-map@>=0.5.0 <0.6.0"
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.4.14",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.14.tgz",
|
||||
"version": "0.4.15",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz",
|
||||
"from": "source-map-support@>=0.4.2 <0.5.0"
|
||||
},
|
||||
"strip-ansi": {
|
||||
@@ -707,14 +732,19 @@
|
||||
"from": "supports-color@>=2.0.0 <3.0.0"
|
||||
},
|
||||
"to-fast-properties": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.2.tgz",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
|
||||
"from": "to-fast-properties@>=1.0.1 <2.0.0"
|
||||
},
|
||||
"trim-right": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
|
||||
"from": "trim-right@>=1.0.1 <2.0.0"
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
|
||||
"from": "yallist@>=3.0.0 <4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@ Babel = {
|
||||
// Deprecated, now a no-op.
|
||||
validateExtraFeatures: Function.prototype,
|
||||
|
||||
parse: function (source) {
|
||||
return Npm.require('meteor-babel').parse(source);
|
||||
},
|
||||
|
||||
compile: function (source, options) {
|
||||
var meteorBabel = Npm.require('meteor-babel');
|
||||
options = options || getDefaultOptions();
|
||||
|
||||
@@ -6,15 +6,15 @@ Package.describe({
|
||||
// isn't possible because you can't publish a non-recommended
|
||||
// release with package versions that don't have a pre-release
|
||||
// identifier at the end (eg, -dev)
|
||||
version: '6.18.2'
|
||||
version: '6.19.1'
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
'meteor-babel': '0.20.1'
|
||||
'meteor-babel': '0.21.4'
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
api.use('ecmascript-runtime');
|
||||
api.use('ecmascript-runtime', 'server');
|
||||
|
||||
api.addFiles([
|
||||
'babel.js',
|
||||
|
||||
@@ -73,7 +73,10 @@ Boilerplate.prototype._generateBoilerplateFromManifestAndSource =
|
||||
if (item.type === 'css' && item.where === 'client') {
|
||||
boilerplateBaseData.css.push(itemObj);
|
||||
}
|
||||
if (item.type === 'js' && item.where === 'client') {
|
||||
if (item.type === 'js' && item.where === 'client' &&
|
||||
// Dynamic JS modules should not be loaded eagerly in the
|
||||
// initial HTML of the app.
|
||||
! item.path.startsWith('dynamic/')) {
|
||||
boilerplateBaseData.js.push(itemObj);
|
||||
}
|
||||
if (item.type === 'head') {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
Package.describe({
|
||||
summary: "Generates the boilerplate html from program's manifest",
|
||||
version: '1.0.11'
|
||||
version: '1.1.0'
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
api.use([
|
||||
'underscore@1.0.9',
|
||||
'spacebars-compiler@1.0.12',
|
||||
'spacebars@1.0.12',
|
||||
'htmljs@1.0.10',
|
||||
'ui@1.0.11',
|
||||
'underscore',
|
||||
'spacebars-compiler',
|
||||
'spacebars',
|
||||
'htmljs',
|
||||
'ui',
|
||||
], 'server');
|
||||
api.addFiles(['boilerplate-generator.js'], 'server');
|
||||
api.export(['Boilerplate'], 'server');
|
||||
|
||||
13
packages/dynamic-import/README.md
Normal file
13
packages/dynamic-import/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
This package implements the `Module.prototype.dynamicImport(id)` runtime
|
||||
API needed for fetching modules dynamically from the server, so that those
|
||||
modules don't have to be included in the initial JavaScript bundle.
|
||||
|
||||
With this package installed, supporting the [dynamic `import(...)`
|
||||
proposal](https://github.com/tc39/proposal-dynamic-import) is as easy as
|
||||
compiling `import(...)` to `module.dynamicImport(...)`.
|
||||
|
||||
Any version of a module that has been fetched previously will be
|
||||
permanently cached and should never need to be fetched again by the same
|
||||
client, even after the window is closed or the browser is restarted.
|
||||
|
||||
Meteor 1.5 is necessary for this package to work properly.
|
||||
43
packages/dynamic-import/TODO.md
Normal file
43
packages/dynamic-import/TODO.md
Normal file
@@ -0,0 +1,43 @@
|
||||
### Basic implementation:
|
||||
|
||||
- [x] Future-proof `findImportedModuleIdentifiers` for real `import(...)`
|
||||
- [x] Source maps in development
|
||||
- [x] Debugger stops at reasonable points in dev tools
|
||||
- [x] Open another WebSocket? NO
|
||||
- [x] Make `import(...)` work on the server
|
||||
- [x] Modules are minified but not merged in production
|
||||
- [x] Wrap modules with function to enable better minification
|
||||
- [x] Babel transform from `import(...)` to `module.importAsync(...)`
|
||||
- [x] Local module caching.
|
||||
- [x] Prototype with `localStorage`.
|
||||
- [x] Reimplement using `indexedDB` (much larger size limits).
|
||||
- [x] Compact `previous` state representation
|
||||
- [x] Improve dependency resolution in `packages/dynamic-import/server.js`
|
||||
- [x] Report static import/syntax/etc. errors for async files
|
||||
- [x] What about old/new versions of code?
|
||||
- [x] What about package pseudo-globals (imports)?
|
||||
- [x] What about dynamic stubs?
|
||||
- [x] Avoid creating dynamic files on the server.
|
||||
- [ ] ~~`Mp.dynamicImport` could be implemented without the fallback on the server if we were sure the server had no dynamic files.~~
|
||||
- [x] Make sure client-only reloads work (revisit _read caching).
|
||||
- [x] Make sure path manipulation is Windows-safe.
|
||||
- [x] Install dynamic modules with correct `meteorInstall` options.
|
||||
- [x] Tests!
|
||||
|
||||
### Future work:
|
||||
|
||||
- [ ] Batch multiple `__dynamicImport` method calls?
|
||||
- [ ] Detect modules unevaluated during page load and recommend importing them dynamically.
|
||||
- [ ] Quantify the impact of using `import(...)`.
|
||||
- [ ] Report initial bundle sizes.
|
||||
- [ ] Warn about `import(...)` calls before `Meteor.startup`, since they should probably be static.
|
||||
- [ ] Analyze module graph to suggest dynamic cut points (e.g. in router callbacks).
|
||||
- [ ] Warn if dynamically imported modules are imported statically elsewhere (killing the benefit of the dynamic import).
|
||||
- [ ] Use `Cache-Control: immutable` for the initial bundle.
|
||||
- [ ] Upgrade caching to `ServiceWorker` and `Cache` in supporting browsers (if actually faster!).
|
||||
- [ ] Preload modules that are often dynamically imported, when page becomes idle.
|
||||
- [ ] Allow the client to overfetch soon-to-be-needed modules to avoid waterfalls.
|
||||
- [ ] Write [Meteor Guide](https://guide.meteor.com/) article about techniques for optimizing page load times.
|
||||
- [ ] Inlining imports.
|
||||
- [ ] Making eager modules in apps and packages lazy.
|
||||
- [ ] Using dynamic `import(...)` in the right places.
|
||||
189
packages/dynamic-import/cache.js
Normal file
189
packages/dynamic-import/cache.js
Normal file
@@ -0,0 +1,189 @@
|
||||
var hasOwn = Object.prototype.hasOwnProperty;
|
||||
var dbPromise;
|
||||
|
||||
var canUseCache =
|
||||
// The server doesn't benefit from dynamic module fetching, and almost
|
||||
// certainly doesn't support IndexedDB.
|
||||
Meteor.isClient &&
|
||||
// Cordova bundles all modules into the monolithic initial bundle, so
|
||||
// the dynamic module cache won't be necessary.
|
||||
! Meteor.isCordova &&
|
||||
// Caching can be confusing in development, and is designed to be a
|
||||
// transparent optimization for production performance.
|
||||
Meteor.isProduction;
|
||||
|
||||
function getIDB() {
|
||||
if (typeof indexedDB !== "undefined") return indexedDB;
|
||||
if (typeof webkitIndexedDB !== "undefined") return webkitIndexedDB;
|
||||
if (typeof mozIndexedDB !== "undefined") return mozIndexedDB;
|
||||
if (typeof OIndexedDB !== "undefined") return OIndexedDB;
|
||||
if (typeof msIndexedDB !== "undefined") return msIndexedDB;
|
||||
}
|
||||
|
||||
function withDB(callback) {
|
||||
dbPromise = dbPromise || new Promise(function (resolve, reject) {
|
||||
var idb = getIDB();
|
||||
if (! idb) {
|
||||
throw new Error("IndexedDB not available");
|
||||
}
|
||||
|
||||
// Incrementing the version number causes all existing object stores
|
||||
// to be deleted and recreates those specified by objectStoreMap.
|
||||
var request = idb.open("MeteorDynamicImportCache", 2);
|
||||
|
||||
request.onupgradeneeded = function (event) {
|
||||
var db = event.target.result;
|
||||
|
||||
// It's fine to delete existing object stores since onupgradeneeded
|
||||
// is only called when we change the DB version number, and the data
|
||||
// we're storing is disposable/reconstructible.
|
||||
Array.from(db.objectStoreNames).forEach(db.deleteObjectStore, db);
|
||||
|
||||
Object.keys(objectStoreMap).forEach(function (name) {
|
||||
db.createObjectStore(name, objectStoreMap[name]);
|
||||
});
|
||||
};
|
||||
|
||||
request.onerror = makeOnError(reject, "indexedDB.open");
|
||||
request.onsuccess = function (event) {
|
||||
resolve(event.target.result);
|
||||
};
|
||||
});
|
||||
|
||||
return dbPromise.then(callback, function (error) {
|
||||
return callback(null);
|
||||
});
|
||||
}
|
||||
|
||||
var objectStoreMap = {
|
||||
sourcesByVersion: { keyPath: "version" }
|
||||
};
|
||||
|
||||
function makeOnError(reject, source) {
|
||||
return function (event) {
|
||||
reject(new Error(
|
||||
"IndexedDB failure in " + source + " " +
|
||||
JSON.stringify(event.target)
|
||||
));
|
||||
|
||||
// Returning true from an onerror callback function prevents an
|
||||
// InvalidStateError in Firefox during Private Browsing. Silencing
|
||||
// that error is safe because we handle the error more gracefully by
|
||||
// passing it to the Promise reject function above.
|
||||
// https://github.com/meteor/meteor/issues/8697
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
var checkCount = 0;
|
||||
|
||||
exports.checkMany = function (versions) {
|
||||
var ids = Object.keys(versions);
|
||||
var sourcesById = Object.create(null);
|
||||
|
||||
// Initialize sourcesById with null values to indicate all sources are
|
||||
// missing (unless replaced with actual sources below).
|
||||
ids.forEach(function (id) {
|
||||
sourcesById[id] = null;
|
||||
});
|
||||
|
||||
if (! canUseCache) {
|
||||
return Promise.resolve(sourcesById);
|
||||
}
|
||||
|
||||
return withDB(function (db) {
|
||||
if (! db) {
|
||||
// We thought we could used IndexedDB, but something went wrong
|
||||
// while opening the database, so err on the side of safety.
|
||||
return sourcesById;
|
||||
}
|
||||
|
||||
var txn = db.transaction([
|
||||
"sourcesByVersion"
|
||||
], "readonly");
|
||||
|
||||
var sourcesByVersion = txn.objectStore("sourcesByVersion");
|
||||
|
||||
++checkCount;
|
||||
|
||||
function finish() {
|
||||
--checkCount;
|
||||
return sourcesById;
|
||||
}
|
||||
|
||||
return Promise.all(ids.map(function (id) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var version = versions[id];
|
||||
if (version) {
|
||||
var sourceRequest = sourcesByVersion.get(versions[id]);
|
||||
sourceRequest.onerror = makeOnError(reject, "sourcesByVersion.get");
|
||||
sourceRequest.onsuccess = function (event) {
|
||||
var result = event.target.result;
|
||||
if (result) {
|
||||
sourcesById[id] = result.source;
|
||||
}
|
||||
resolve();
|
||||
};
|
||||
} else resolve();
|
||||
});
|
||||
})).then(finish, finish);
|
||||
});
|
||||
};
|
||||
|
||||
var pendingVersionsAndSourcesById = Object.create(null);
|
||||
|
||||
exports.setMany = function (versionsAndSourcesById) {
|
||||
if (canUseCache) {
|
||||
Object.assign(
|
||||
pendingVersionsAndSourcesById,
|
||||
versionsAndSourcesById
|
||||
);
|
||||
|
||||
// Delay the call to flushSetMany so that it doesn't contribute to the
|
||||
// amount of time it takes to call module.dynamicImport.
|
||||
if (! flushSetMany.timer) {
|
||||
flushSetMany.timer = setTimeout(flushSetMany, 100);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function flushSetMany() {
|
||||
if (checkCount > 0) {
|
||||
// If checkMany is currently underway, postpone the flush until later,
|
||||
// since updating the cache is less important than reading from it.
|
||||
return flushSetMany.timer = setTimeout(flushSetMany, 100);
|
||||
}
|
||||
|
||||
flushSetMany.timer = null;
|
||||
|
||||
var versionsAndSourcesById = pendingVersionsAndSourcesById;
|
||||
pendingVersionsAndSourcesById = Object.create(null);
|
||||
|
||||
return withDB(function (db) {
|
||||
if (! db) {
|
||||
// We thought we could used IndexedDB, but something went wrong
|
||||
// while opening the database, so err on the side of safety.
|
||||
return;
|
||||
}
|
||||
|
||||
var setTxn = db.transaction([
|
||||
"sourcesByVersion"
|
||||
], "readwrite");
|
||||
|
||||
var sourcesByVersion = setTxn.objectStore("sourcesByVersion");
|
||||
|
||||
return Promise.all(
|
||||
Object.keys(versionsAndSourcesById).map(function (id) {
|
||||
var info = versionsAndSourcesById[id];
|
||||
return new Promise(function (resolve, reject) {
|
||||
var request = sourcesByVersion.put({
|
||||
version: info.version,
|
||||
source: info.source
|
||||
});
|
||||
request.onerror = makeOnError(reject, "sourcesByVersion.put");
|
||||
request.onsuccess = resolve;
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
158
packages/dynamic-import/client.js
Normal file
158
packages/dynamic-import/client.js
Normal file
@@ -0,0 +1,158 @@
|
||||
var Module = module.constructor;
|
||||
var cache = require("./cache.js");
|
||||
|
||||
// Call module.dynamicImport(id) to fetch a module and any/all of its
|
||||
// dependencies that have not already been fetched, and evaluate them as
|
||||
// soon as they arrive. This runtime API makes it very easy to implement
|
||||
// ECMAScript dynamic import(...) syntax.
|
||||
Module.prototype.dynamicImport = function (id) {
|
||||
var module = this;
|
||||
return module.prefetch(id).then(function () {
|
||||
return getNamespace(module, id);
|
||||
});
|
||||
};
|
||||
|
||||
// Called by Module.prototype.prefetch if there are any missing dynamic
|
||||
// modules that need to be fetched.
|
||||
meteorInstall.fetch = function (ids) {
|
||||
var tree = Object.create(null);
|
||||
var versions = Object.create(null);
|
||||
var dynamicVersions = require("./dynamic-versions.js");
|
||||
var missing;
|
||||
|
||||
Object.keys(ids).forEach(function (id) {
|
||||
var version = getFromTree(dynamicVersions, id);
|
||||
if (version) {
|
||||
versions[id] = version;
|
||||
} else {
|
||||
addToTree(missing = missing || Object.create(null), id, 1);
|
||||
}
|
||||
});
|
||||
|
||||
return cache.checkMany(versions).then(function (sources) {
|
||||
Object.keys(sources).forEach(function (id) {
|
||||
var source = sources[id];
|
||||
if (source) {
|
||||
var info = ids[id];
|
||||
addToTree(tree, id, makeModuleFunction(id, source, info.options));
|
||||
} else {
|
||||
addToTree(missing = missing || Object.create(null), id, 1);
|
||||
}
|
||||
});
|
||||
|
||||
return missing && fetchMissing(missing).then(function (results) {
|
||||
var versionsAndSourcesById = Object.create(null);
|
||||
var flatResults = flattenModuleTree(results);
|
||||
|
||||
Object.keys(flatResults).forEach(function (id) {
|
||||
var source = flatResults[id];
|
||||
var info = ids[id];
|
||||
|
||||
addToTree(tree, id, makeModuleFunction(id, source, info.options));
|
||||
|
||||
var version = getFromTree(dynamicVersions, id);
|
||||
if (version) {
|
||||
versionsAndSourcesById[id] = {
|
||||
version: version,
|
||||
source: source
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
cache.setMany(versionsAndSourcesById);
|
||||
});
|
||||
|
||||
}).then(function () {
|
||||
return tree;
|
||||
});
|
||||
};
|
||||
|
||||
function flattenModuleTree(tree) {
|
||||
var parts = [""];
|
||||
var result = Object.create(null);
|
||||
|
||||
function walk(t) {
|
||||
if (t && typeof t === "object") {
|
||||
Object.keys(t).forEach(function (key) {
|
||||
parts.push(key);
|
||||
walk(t[key]);
|
||||
parts.pop();
|
||||
});
|
||||
} else if (typeof t === "string") {
|
||||
result[parts.join("/")] = t;
|
||||
}
|
||||
}
|
||||
|
||||
walk(tree);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function makeModuleFunction(id, source, options) {
|
||||
// By calling (options && options.eval || eval) in a wrapper function,
|
||||
// we delay the cost of parsing and evaluating the module code until the
|
||||
// module is first imported.
|
||||
return function () {
|
||||
// If an options.eval function was provided in the second argument to
|
||||
// meteorInstall when this bundle was first installed, use that
|
||||
// function to parse and evaluate the dynamic module code in the scope
|
||||
// of the package. Otherwise fall back to indirect (global) eval.
|
||||
return (options && options.eval || eval)(
|
||||
// Wrap the function(require,exports,module){...} expression in
|
||||
// parentheses to force it to be parsed as an expression.
|
||||
"(" + source + ")\n//# sourceURL=" + id
|
||||
).apply(this, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
function fetchMissing(missingTree) {
|
||||
// Update lastFetchMissingPromise immediately, without waiting for
|
||||
// the results to be delivered.
|
||||
return new Promise(function (resolve, reject) {
|
||||
Meteor.call(
|
||||
"__dynamicImport",
|
||||
missingTree,
|
||||
function (error, resultsTree) {
|
||||
error ? reject(error) : resolve(resultsTree);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function getFromTree(tree, id) {
|
||||
id.split("/").every(function (part) {
|
||||
return ! part || (tree = tree[part]);
|
||||
});
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
function addToTree(tree, id, value) {
|
||||
var parts = id.split("/");
|
||||
var lastIndex = parts.length - 1;
|
||||
parts.forEach(function (part, i) {
|
||||
if (part) {
|
||||
tree = tree[part] = tree[part] ||
|
||||
(i < lastIndex ? Object.create(null) : value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getNamespace(module, id) {
|
||||
var namespace;
|
||||
|
||||
module.watch(module.require(id), {
|
||||
"*": function (ns) {
|
||||
namespace = ns;
|
||||
}
|
||||
});
|
||||
|
||||
// This helps with Babel interop, since we're not just returning the
|
||||
// module.exports object.
|
||||
Object.defineProperty(namespace, "__esModule", {
|
||||
value: true,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
return namespace;
|
||||
}
|
||||
4
packages/dynamic-import/dynamic-versions.js
Normal file
4
packages/dynamic-import/dynamic-versions.js
Normal file
@@ -0,0 +1,4 @@
|
||||
// This magic double-underscored identifier gets replaced in
|
||||
// tools/isobuild/bundler.js with a tree of hashes of all dynamic
|
||||
// modules, for use in client.js and cache.js.
|
||||
module.exports = __DYNAMIC_VERSIONS__;
|
||||
23
packages/dynamic-import/package.js
Normal file
23
packages/dynamic-import/package.js
Normal file
@@ -0,0 +1,23 @@
|
||||
Package.describe({
|
||||
name: "dynamic-import",
|
||||
version: "0.1.0",
|
||||
summary: "Runtime support for Meteor 1.5 dynamic import(...) syntax",
|
||||
documentation: "README.md"
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
// Do not allow this package to be used in pre-Meteor 1.5 apps.
|
||||
api.use("isobuild:dynamic-import@1.5.0");
|
||||
|
||||
// Modify browser policy only if browser-policy packages are used.
|
||||
api.use("browser-policy-content", { weak: true });
|
||||
|
||||
api.use("modules");
|
||||
api.use("promise");
|
||||
api.use("ddp");
|
||||
api.use("check");
|
||||
api.use("ecmascript", "server");
|
||||
|
||||
api.mainModule("client.js", "client");
|
||||
api.mainModule("server.js", "server");
|
||||
});
|
||||
20
packages/dynamic-import/security.js
Normal file
20
packages/dynamic-import/security.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const bpc = Package["browser-policy-content"];
|
||||
const BP = bpc && bpc.BrowserPolicy;
|
||||
const BPc = BP && BP.content;
|
||||
if (BPc) {
|
||||
// The ability to evaluate new code is essential for loading dynamic
|
||||
// modules. Without eval, we would be forced to load modules using
|
||||
// <script src=...> tags, and then there would be no way to save those
|
||||
// modules to a local cache (or load them from the cache) without the
|
||||
// unique response caching abilities of service workers, which are not
|
||||
// available in all browsers, and cannot be polyfilled in a way that
|
||||
// satisfies Content Security Policy eval restrictions. Moreover, eval
|
||||
// allows us to evaluate dynamic module code in the original package
|
||||
// scope, which would never be possible using <script> tags. If you're
|
||||
// deploying an app in an environment that demands a Content Security
|
||||
// Policy that forbids eval, your only option is to bundle all dynamic
|
||||
// modules in the initial bundle. Fortunately, that works perfectly
|
||||
// well; you just won't get the performance benefits of dynamic module
|
||||
// fetching.
|
||||
BPc.allowEval();
|
||||
}
|
||||
76
packages/dynamic-import/server.js
Normal file
76
packages/dynamic-import/server.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import assert from "assert";
|
||||
import { readFileSync } from "fs";
|
||||
import {
|
||||
join as pathJoin,
|
||||
normalize as pathNormalize,
|
||||
} from "path";
|
||||
|
||||
import { check } from "meteor/check";
|
||||
|
||||
import "./security.js";
|
||||
import "./client.js";
|
||||
|
||||
const hasOwn = Object.prototype.hasOwnProperty;
|
||||
|
||||
Object.keys(dynamicImportInfo).forEach(platform => {
|
||||
const info = dynamicImportInfo[platform];
|
||||
if (info.dynamicRoot) {
|
||||
info.dynamicRoot = pathNormalize(info.dynamicRoot);
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.methods({
|
||||
__dynamicImport(tree) {
|
||||
check(tree, Object);
|
||||
this.unblock();
|
||||
|
||||
const platform = this.connection ? "web.browser" : "server";
|
||||
const pathParts = [];
|
||||
|
||||
function walk(node) {
|
||||
if (node && typeof node === "object") {
|
||||
Object.keys(node).forEach(name => {
|
||||
pathParts.push(name);
|
||||
node[name] = walk(node[name]);
|
||||
assert.strictEqual(pathParts.pop(), name);
|
||||
});
|
||||
} else {
|
||||
return read(pathParts, platform);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
return walk(tree);
|
||||
}
|
||||
});
|
||||
|
||||
function read(pathParts, platform) {
|
||||
const { dynamicRoot } = dynamicImportInfo[platform];
|
||||
const absPath = pathNormalize(pathJoin(dynamicRoot, ...pathParts));
|
||||
|
||||
if (! absPath.startsWith(dynamicRoot)) {
|
||||
throw new Meteor.Error("bad dynamic module path");
|
||||
}
|
||||
|
||||
const cache = getCache(platform);
|
||||
return hasOwn.call(cache, absPath)
|
||||
? cache[absPath]
|
||||
: cache[absPath] = readFileSync(absPath, "utf8");
|
||||
}
|
||||
|
||||
const cachesByPlatform = Object.create(null);
|
||||
function getCache(platform) {
|
||||
return hasOwn.call(cachesByPlatform, platform)
|
||||
? cachesByPlatform[platform]
|
||||
: cachesByPlatform[platform] = Object.create(null);
|
||||
}
|
||||
|
||||
process.on("message", msg => {
|
||||
// The cache for the "web.browser" platform needs to be discarded
|
||||
// whenever a client-only refresh occurs, so that new client code does
|
||||
// not receive stale module data from __dynamicImport. This code handles
|
||||
// the same message listened for by the autoupdate package.
|
||||
if (msg && msg.refresh === "client") {
|
||||
delete cachesByPlatform["web.browser"];
|
||||
}
|
||||
});
|
||||
6
packages/ecmascript-runtime-client/README.md
Normal file
6
packages/ecmascript-runtime-client/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# ecmascript-runtime-client
|
||||
[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/ecmascript-runtime-client) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/ecmascript-runtime-client)
|
||||
***
|
||||
|
||||
[](https://travis-ci.org/meteor/ecmascript-runtime)
|
||||
Polyfills for new ECMAScript 2015 APIs like Map and Set
|
||||
20
packages/ecmascript-runtime-client/package.js
Normal file
20
packages/ecmascript-runtime-client/package.js
Normal file
@@ -0,0 +1,20 @@
|
||||
Package.describe({
|
||||
name: "ecmascript-runtime-client",
|
||||
version: "0.4.1",
|
||||
summary: "Polyfills for new ECMAScript 2015 APIs like Map and Set",
|
||||
git: "https://github.com/meteor/meteor/tree/devel/packages/ecmascript-runtime-client",
|
||||
documentation: "README.md"
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
// If the es5-shim package is installed, make sure it loads before
|
||||
// ecmascript-runtime-server, since the runtime uses some ES5 APIs like
|
||||
// Object.defineProperties that are buggy in older browsers.
|
||||
api.use("es5-shim", { weak: true });
|
||||
api.use("modules", "client");
|
||||
api.use("promise", "client");
|
||||
api.mainModule("runtime.js", "client");
|
||||
api.export("Symbol", "client");
|
||||
api.export("Map", "client");
|
||||
api.export("Set", "client");
|
||||
});
|
||||
52
packages/ecmascript-runtime-client/runtime.js
Normal file
52
packages/ecmascript-runtime-client/runtime.js
Normal file
@@ -0,0 +1,52 @@
|
||||
try {
|
||||
require("core-js/modules/es6.symbol");
|
||||
require("core-js/modules/es6.map");
|
||||
require("core-js/modules/es6.set");
|
||||
|
||||
var core = function () {
|
||||
try {
|
||||
return require("core-js/modules/_core");
|
||||
} catch (e) {
|
||||
// Older versions of core-js had a different file layout.
|
||||
return require("core-js/modules/$.core");
|
||||
}
|
||||
}();
|
||||
|
||||
} catch (e) {
|
||||
throw new Error([
|
||||
"The core-js npm package could not be found in your node_modules ",
|
||||
"directory. Please run the following command to install it:",
|
||||
"",
|
||||
" meteor npm install --save core-js",
|
||||
""
|
||||
].join("\n"));
|
||||
}
|
||||
|
||||
Symbol = exports.Symbol = core.Symbol;
|
||||
Map = exports.Map = core.Map;
|
||||
Set = exports.Set = core.Set;
|
||||
|
||||
// ECMAScript 2015 polyfills.
|
||||
require("core-js/es6/array");
|
||||
require("core-js/es6/function");
|
||||
require("core-js/es6/math");
|
||||
require("core-js/es6/object");
|
||||
require("core-js/es6/string");
|
||||
require("core-js/es6/weak-map");
|
||||
require("core-js/es6/weak-set");
|
||||
|
||||
// ECMAScript 2017 polyfills.
|
||||
require("core-js/es7/array");
|
||||
require("core-js/es7/object");
|
||||
|
||||
// We want everything from the core-js/es6/number module except
|
||||
// es6.number.constructor.
|
||||
require('core-js/modules/es6.number.epsilon');
|
||||
require('core-js/modules/es6.number.is-finite');
|
||||
require('core-js/modules/es6.number.is-integer');
|
||||
require('core-js/modules/es6.number.is-nan');
|
||||
require('core-js/modules/es6.number.is-safe-integer');
|
||||
require('core-js/modules/es6.number.max-safe-integer');
|
||||
require('core-js/modules/es6.number.min-safe-integer');
|
||||
require('core-js/modules/es6.number.parse-float');
|
||||
require('core-js/modules/es6.number.parse-int');
|
||||
9
packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json
generated
Normal file
9
packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz",
|
||||
"from": "core-js@2.4.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
6
packages/ecmascript-runtime-server/README.md
Normal file
6
packages/ecmascript-runtime-server/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# ecmascript-runtime-server
|
||||
[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/ecmascript-runtime-server) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/ecmascript-runtime-server)
|
||||
***
|
||||
|
||||
[](https://travis-ci.org/meteor/ecmascript-runtime)
|
||||
Polyfills for new ECMAScript 2015 APIs like Map and Set
|
||||
23
packages/ecmascript-runtime-server/package.js
Normal file
23
packages/ecmascript-runtime-server/package.js
Normal file
@@ -0,0 +1,23 @@
|
||||
Package.describe({
|
||||
name: "ecmascript-runtime-server",
|
||||
version: "0.4.1",
|
||||
summary: "Polyfills for new ECMAScript 2015 APIs like Map and Set",
|
||||
git: "https://github.com/meteor/meteor/tree/devel/packages/ecmascript-runtime-client",
|
||||
documentation: "README.md"
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
"core-js": "2.4.1"
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
// If the es5-shim package is installed, make sure it loads before
|
||||
// ecmascript-runtime-server, since the runtime uses some ES5 APIs like
|
||||
// Object.defineProperties that are buggy in older browsers.
|
||||
api.use("es5-shim", { weak: true });
|
||||
api.use(["modules", "promise"], "server");
|
||||
api.mainModule("runtime.js", "server");
|
||||
api.export("Symbol", "server");
|
||||
api.export("Map", "server");
|
||||
api.export("Set", "server");
|
||||
});
|
||||
71
packages/ecmascript-runtime-server/runtime.js
Normal file
71
packages/ecmascript-runtime-server/runtime.js
Normal file
@@ -0,0 +1,71 @@
|
||||
// The ecmascript-runtime-server package depends on its own copy of
|
||||
// core-js using Npm.depends, so we don't have to check that core-js is
|
||||
// available (as we do in ecmascript-runtime-client/runtime.js).
|
||||
|
||||
require("core-js/modules/es6.symbol");
|
||||
require("core-js/modules/es6.map");
|
||||
require("core-js/modules/es6.set");
|
||||
|
||||
var core = require("core-js/modules/_core");
|
||||
Symbol = exports.Symbol = core.Symbol;
|
||||
Map = exports.Map = core.Map;
|
||||
Set = exports.Set = core.Set;
|
||||
|
||||
// List of polyfills generated by babel-preset-env with the following
|
||||
// .babelrc configuration:
|
||||
//
|
||||
// {
|
||||
// "presets": [
|
||||
// ["env", {
|
||||
// "targets": {
|
||||
// "node": 4
|
||||
// },
|
||||
// "polyfill": true,
|
||||
// "useBuiltIns": true
|
||||
// }]
|
||||
// ]
|
||||
// }
|
||||
//
|
||||
// Note that the es6.reflect.* and es6.typed.* modules have been commented
|
||||
// out for bundle size reasons.
|
||||
|
||||
// require("core-js/modules/es6.typed.array-buffer");
|
||||
// require("core-js/modules/es6.typed.int8-array");
|
||||
// require("core-js/modules/es6.typed.uint8-array");
|
||||
// require("core-js/modules/es6.typed.uint8-clamped-array");
|
||||
// require("core-js/modules/es6.typed.int16-array");
|
||||
// require("core-js/modules/es6.typed.uint16-array");
|
||||
// require("core-js/modules/es6.typed.int32-array");
|
||||
// require("core-js/modules/es6.typed.uint32-array");
|
||||
// require("core-js/modules/es6.typed.float32-array");
|
||||
// require("core-js/modules/es6.typed.float64-array");
|
||||
require("core-js/modules/es6.weak-map");
|
||||
require("core-js/modules/es6.weak-set");
|
||||
// require("core-js/modules/es6.reflect.apply");
|
||||
// require("core-js/modules/es6.reflect.construct");
|
||||
// require("core-js/modules/es6.reflect.define-property");
|
||||
// require("core-js/modules/es6.reflect.delete-property");
|
||||
// require("core-js/modules/es6.reflect.get");
|
||||
// require("core-js/modules/es6.reflect.get-own-property-descriptor");
|
||||
// require("core-js/modules/es6.reflect.get-prototype-of");
|
||||
// require("core-js/modules/es6.reflect.has");
|
||||
// require("core-js/modules/es6.reflect.is-extensible");
|
||||
// require("core-js/modules/es6.reflect.own-keys");
|
||||
// require("core-js/modules/es6.reflect.prevent-extensions");
|
||||
// require("core-js/modules/es6.reflect.set");
|
||||
// require("core-js/modules/es6.reflect.set-prototype-of");
|
||||
require("core-js/modules/es6.function.bind");
|
||||
require("core-js/modules/es6.function.name");
|
||||
require("core-js/modules/es6.function.has-instance");
|
||||
require("core-js/modules/es6.regexp.flags");
|
||||
require("core-js/modules/es6.regexp.match");
|
||||
require("core-js/modules/es6.regexp.replace");
|
||||
require("core-js/modules/es6.regexp.split");
|
||||
require("core-js/modules/es6.regexp.search");
|
||||
require("core-js/modules/es6.array.from");
|
||||
require("core-js/modules/es7.array.includes");
|
||||
require("core-js/modules/es7.object.values");
|
||||
require("core-js/modules/es7.object.entries");
|
||||
require("core-js/modules/es7.object.get-own-property-descriptors");
|
||||
require("core-js/modules/es7.string.pad-start");
|
||||
require("core-js/modules/es7.string.pad-end");
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz",
|
||||
"from": "core-js@2.4.1"
|
||||
},
|
||||
"meteor-ecmascript-runtime": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/meteor-ecmascript-runtime/-/meteor-ecmascript-runtime-0.2.9.tgz",
|
||||
"from": "meteor-ecmascript-runtime@0.2.9"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,14 @@
|
||||
Package.describe({
|
||||
name: "ecmascript-runtime",
|
||||
version: "0.3.15",
|
||||
version: "0.4.1",
|
||||
summary: "Polyfills for new ECMAScript 2015 APIs like Map and Set",
|
||||
git: "https://github.com/meteor/ecmascript-runtime",
|
||||
documentation: "README.md"
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
"meteor-ecmascript-runtime": "0.2.9",
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
// If the es5-shim package is installed, make sure it loads before
|
||||
// ecmascript-runtime, since ecmascript-runtime uses some ES5 APIs like
|
||||
// Object.defineProperties that are buggy in older browsers.
|
||||
api.use("es5-shim@4.6.13", { weak: true });
|
||||
|
||||
api.use("modules@0.7.5");
|
||||
api.use("promise@0.8.3");
|
||||
|
||||
api.mainModule("runtime.js");
|
||||
|
||||
api.export("Symbol");
|
||||
api.export("Map");
|
||||
api.export("Set");
|
||||
api.imply("ecmascript-runtime-client", "client");
|
||||
api.imply("ecmascript-runtime-server", "server");
|
||||
});
|
||||
|
||||
Package.onTest(function(api) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: 'ecmascript',
|
||||
version: '0.7.3',
|
||||
version: '0.8.0',
|
||||
summary: 'Compiler plugin that supports ES2015+ in all .js files',
|
||||
documentation: 'README.md'
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Facebook OAuth flow",
|
||||
version: "1.3.0"
|
||||
version: "1.3.1"
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
|
||||
@@ -5,52 +5,44 @@
|
||||
// trying to use it throws.
|
||||
// Accessing window.localStorage can also immediately throw an error in IE (#1291).
|
||||
|
||||
var hasOwn = Object.prototype.hasOwnProperty;
|
||||
var key = '_localstorage_test_' + Random.id();
|
||||
var retrieved;
|
||||
var storage;
|
||||
|
||||
try {
|
||||
if (window.localStorage) {
|
||||
window.localStorage.setItem(key, key);
|
||||
retrieved = window.localStorage.getItem(key);
|
||||
window.localStorage.removeItem(key);
|
||||
storage = global.localStorage;
|
||||
|
||||
if (storage) {
|
||||
storage.setItem(key, key);
|
||||
retrieved = storage.getItem(key);
|
||||
storage.removeItem(key);
|
||||
}
|
||||
} catch (e) {
|
||||
// ... ignore
|
||||
}
|
||||
} catch (ignored) {}
|
||||
|
||||
if (key === retrieved) {
|
||||
Meteor._localStorage = {
|
||||
getItem: function (key) {
|
||||
return window.localStorage.getItem(key);
|
||||
},
|
||||
setItem: function (key, value) {
|
||||
window.localStorage.setItem(key, value);
|
||||
},
|
||||
removeItem: function (key) {
|
||||
window.localStorage.removeItem(key);
|
||||
}
|
||||
};
|
||||
Meteor._localStorage = storage;
|
||||
}
|
||||
|
||||
if (!Meteor._localStorage) {
|
||||
Meteor._debug(
|
||||
"You are running a browser with no localStorage or userData "
|
||||
+ "support. Logging in from one tab will not cause another "
|
||||
+ "tab to be logged in.");
|
||||
|
||||
Meteor._localStorage = {
|
||||
_data: {},
|
||||
if (! Meteor._localStorage) {
|
||||
if (Meteor.isClient) {
|
||||
Meteor._debug(
|
||||
"You are running a browser with no localStorage or userData "
|
||||
+ "support. Logging in from one tab will not cause another "
|
||||
+ "tab to be logged in.");
|
||||
}
|
||||
|
||||
Meteor._localStorage = Object.create({
|
||||
setItem: function (key, val) {
|
||||
this._data[key] = val;
|
||||
this[key] = val;
|
||||
},
|
||||
|
||||
removeItem: function (key) {
|
||||
delete this._data[key];
|
||||
delete this[key];
|
||||
},
|
||||
|
||||
getItem: function (key) {
|
||||
var value = this._data[key];
|
||||
if (value === undefined)
|
||||
return null;
|
||||
else
|
||||
return value;
|
||||
return hasOwn.call(this, key) ? this[key] : null;
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
Package.describe({
|
||||
summary: "Simulates local storage on IE 6,7 using userData",
|
||||
version: "1.0.12"
|
||||
version: "1.1.0"
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
api.use('random', 'client');
|
||||
|
||||
api.addFiles('localstorage.js', 'client');
|
||||
api.use('random');
|
||||
api.addFiles('localstorage.js');
|
||||
});
|
||||
|
||||
Package.onTest(function (api) {
|
||||
api.use('localstorage', 'client');
|
||||
api.use('localstorage');
|
||||
api.use('tinytest');
|
||||
|
||||
api.addFiles('localstorage_tests.js', 'client');
|
||||
api.addFiles('localstorage_tests.js');
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: 'meteor-base',
|
||||
version: '1.0.4',
|
||||
version: '1.1.0',
|
||||
// Brief, one-line summary of the package.
|
||||
summary: 'Packages that every Meteor app needs',
|
||||
// By default, Meteor will default to using README.md for documentation.
|
||||
@@ -25,6 +25,9 @@ Package.onUse(function(api) {
|
||||
'ddp',
|
||||
'livedata', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.
|
||||
|
||||
// Runtime support for Meteor 1.5 dynamic import(...) syntax.
|
||||
'dynamic-import',
|
||||
|
||||
// Push code changes to the client and automatically reload the page
|
||||
'hot-code-push'
|
||||
]);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "The Meteor command-line tool",
|
||||
version: '1.4.4_3'
|
||||
version: '1.5.0'
|
||||
});
|
||||
|
||||
Package.includeTool();
|
||||
|
||||
@@ -1,59 +1,14 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"align-text": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
|
||||
"from": "align-text@>=0.1.3 <0.2.0"
|
||||
"commander": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
|
||||
"from": "commander@>=2.9.0 <2.10.0"
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
|
||||
"from": "camelcase@>=1.0.2 <2.0.0"
|
||||
},
|
||||
"center-align": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
|
||||
"from": "center-align@>=0.1.1 <0.2.0"
|
||||
},
|
||||
"cliui": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
|
||||
"from": "cliui@>=2.1.0 <3.0.0"
|
||||
},
|
||||
"decamelize": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"from": "decamelize@>=1.0.0 <2.0.0"
|
||||
},
|
||||
"is-buffer": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz",
|
||||
"from": "is-buffer@>=1.0.2 <2.0.0"
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.1.0.tgz",
|
||||
"from": "kind-of@>=3.0.2 <4.0.0"
|
||||
},
|
||||
"lazy-cache": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
|
||||
"from": "lazy-cache@>=1.0.3 <2.0.0"
|
||||
},
|
||||
"longest": {
|
||||
"graceful-readlink": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
|
||||
"from": "longest@>=1.0.1 <2.0.0"
|
||||
},
|
||||
"repeat-string": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
|
||||
"from": "repeat-string@>=1.5.2 <2.0.0"
|
||||
},
|
||||
"right-align": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
|
||||
"from": "right-align@>=0.1.1 <0.2.0"
|
||||
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
|
||||
"from": "graceful-readlink@>=1.0.0"
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.5.6",
|
||||
@@ -61,29 +16,9 @@
|
||||
"from": "source-map@>=0.5.1 <0.6.0"
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "2.8.21",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.21.tgz",
|
||||
"from": "uglify-js@2.8.21"
|
||||
},
|
||||
"uglify-to-browserify": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
|
||||
"from": "uglify-to-browserify@>=1.0.0 <1.1.0"
|
||||
},
|
||||
"window-size": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
|
||||
"from": "window-size@0.1.0"
|
||||
},
|
||||
"wordwrap": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
|
||||
"from": "wordwrap@0.0.2"
|
||||
},
|
||||
"yargs": {
|
||||
"version": "3.10.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
|
||||
"from": "yargs@>=3.10.0 <3.11.0"
|
||||
"version": "3.0.13",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.0.13.tgz",
|
||||
"from": "uglify-js@3.0.13"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,20 @@ meteorJsMinify = function (source) {
|
||||
uglify = uglify || Npm.require("uglify-js");
|
||||
|
||||
try {
|
||||
result.code = uglify.minify(source, {
|
||||
fromString: true,
|
||||
var uglifyResult = uglify.minify(source, {
|
||||
compress: {
|
||||
drop_debugger: false,
|
||||
unused: false,
|
||||
dead_code: false
|
||||
}
|
||||
}).code;
|
||||
});
|
||||
|
||||
if (typeof uglifyResult.code === "string") {
|
||||
result.code = uglifyResult.code;
|
||||
} else {
|
||||
throw uglifyResult.error ||
|
||||
new Error("unknown uglify.minify failure");
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
// Although Babel.minify can handle a wider variety of ECMAScript
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Package.describe({
|
||||
summary: "JavaScript minifier",
|
||||
version: "2.0.0"
|
||||
version: "2.1.0"
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
"uglify-js": "2.8.21"
|
||||
"uglify-js": "3.0.13"
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Meteor's client-side datastore: a port of MongoDB to Javascript",
|
||||
version: '1.0.23'
|
||||
version: '1.2.0'
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"install": {
|
||||
"version": "0.8.8",
|
||||
"resolved": "https://registry.npmjs.org/install/-/install-0.8.8.tgz",
|
||||
"from": "install@0.8.8"
|
||||
"version": "0.10.1",
|
||||
"resolved": "https://registry.npmjs.org/install/-/install-0.10.1.tgz",
|
||||
"from": "install@0.10.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
packages/modules-runtime/client.js
Normal file
5
packages/modules-runtime/client.js
Normal file
@@ -0,0 +1,5 @@
|
||||
// On the client, make package resolution prefer the "browser" field of
|
||||
// package.json files to the "main" field.
|
||||
makeInstallerOptions.browser = true;
|
||||
|
||||
meteorInstall = makeInstaller(makeInstallerOptions);
|
||||
@@ -1,86 +0,0 @@
|
||||
var options = {};
|
||||
var hasOwn = options.hasOwnProperty;
|
||||
|
||||
// RegExp matching strings that don't start with a `.` or a `/`.
|
||||
var topLevelIdPattern = /^[^./]/;
|
||||
|
||||
if (typeof Profile === "function" &&
|
||||
process.env.METEOR_PROFILE) {
|
||||
options.wrapRequire = function (require) {
|
||||
return Profile(function (id) {
|
||||
return "require(" + JSON.stringify(id) + ")";
|
||||
}, require);
|
||||
};
|
||||
}
|
||||
|
||||
// On the client, make package resolution prefer the "browser" field of
|
||||
// package.json files to the "main" field.
|
||||
options.browser = Meteor.isClient;
|
||||
|
||||
// This function will be called whenever a module identifier that hasn't
|
||||
// been installed is required. For backwards compatibility, and so that we
|
||||
// can require binary dependencies on the server, we implement the
|
||||
// fallback in terms of Npm.require.
|
||||
options.fallback = function (id, parentId, error) {
|
||||
// For simplicity, we honor only top-level module identifiers here.
|
||||
// We could try to honor relative and absolute module identifiers by
|
||||
// somehow combining `id` with `dir`, but we'd have to be really careful
|
||||
// that the resulting modules were located in a known directory (not
|
||||
// some arbitrary location on the file system), and we only really need
|
||||
// the fallback for dependencies installed in node_modules directories.
|
||||
if (topLevelIdPattern.test(id)) {
|
||||
if (typeof Npm === "object" &&
|
||||
typeof Npm.require === "function") {
|
||||
return Npm.require(id);
|
||||
}
|
||||
}
|
||||
|
||||
throw error;
|
||||
};
|
||||
|
||||
options.fallback.resolve = function (id, parentId, error) {
|
||||
if (Meteor.isServer &&
|
||||
topLevelIdPattern.test(id)) {
|
||||
// Allow any top-level identifier to resolve to itself on the server,
|
||||
// so that options.fallback can have a chance to handle it.
|
||||
return id;
|
||||
}
|
||||
|
||||
throw error;
|
||||
};
|
||||
|
||||
meteorInstall = makeInstaller(options);
|
||||
var Mp = meteorInstall.Module.prototype;
|
||||
|
||||
if (Meteor.isServer) {
|
||||
Mp.useNode = function () {
|
||||
if (typeof npmRequire !== "function") {
|
||||
// Can't use Node if npmRequire is not defined.
|
||||
return false;
|
||||
}
|
||||
|
||||
var parts = this.id.split("/");
|
||||
var start = 0;
|
||||
if (parts[start] === "") ++start;
|
||||
if (parts[start] === "node_modules" &&
|
||||
parts[start + 1] === "meteor") {
|
||||
start += 2;
|
||||
}
|
||||
|
||||
if (parts.indexOf("node_modules", start) < 0) {
|
||||
// Don't try to use Node for modules that aren't in node_modules
|
||||
// directories.
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
npmRequire.resolve(this.id);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.exports = npmRequire(this.id);
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
10
packages/modules-runtime/options.js
Normal file
10
packages/modules-runtime/options.js
Normal file
@@ -0,0 +1,10 @@
|
||||
makeInstallerOptions = {};
|
||||
|
||||
if (typeof Profile === "function" &&
|
||||
process.env.METEOR_PROFILE) {
|
||||
makeInstallerOptions.wrapRequire = function (require) {
|
||||
return Profile(function (id) {
|
||||
return "require(" + JSON.stringify(id) + ")";
|
||||
}, require);
|
||||
};
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
Package.describe({
|
||||
name: "modules-runtime",
|
||||
version: "0.7.10",
|
||||
version: "0.8.0",
|
||||
summary: "CommonJS module system",
|
||||
git: "https://github.com/benjamn/install",
|
||||
documentation: "README.md"
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
install: "0.8.8"
|
||||
install: "0.10.1"
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
@@ -18,7 +18,10 @@ Package.onUse(function(api) {
|
||||
bare: true
|
||||
});
|
||||
|
||||
api.addFiles("modules-runtime.js");
|
||||
api.addFiles("options.js");
|
||||
api.addFiles("client.js", "client");
|
||||
api.addFiles("server.js", "server");
|
||||
|
||||
api.export("meteorInstall");
|
||||
});
|
||||
|
||||
|
||||
67
packages/modules-runtime/server.js
Normal file
67
packages/modules-runtime/server.js
Normal file
@@ -0,0 +1,67 @@
|
||||
// RegExp matching strings that don't start with a `.` or a `/`.
|
||||
var topLevelIdPattern = /^[^./]/;
|
||||
|
||||
// This function will be called whenever a module identifier that hasn't
|
||||
// been installed is required. For backwards compatibility, and so that we
|
||||
// can require binary dependencies on the server, we implement the
|
||||
// fallback in terms of Npm.require.
|
||||
makeInstallerOptions.fallback = function (id, parentId, error) {
|
||||
// For simplicity, we honor only top-level module identifiers here.
|
||||
// We could try to honor relative and absolute module identifiers by
|
||||
// somehow combining `id` with `dir`, but we'd have to be really careful
|
||||
// that the resulting modules were located in a known directory (not
|
||||
// some arbitrary location on the file system), and we only really need
|
||||
// the fallback for dependencies installed in node_modules directories.
|
||||
if (topLevelIdPattern.test(id)) {
|
||||
if (typeof Npm === "object" &&
|
||||
typeof Npm.require === "function") {
|
||||
return Npm.require(id);
|
||||
}
|
||||
}
|
||||
|
||||
throw error;
|
||||
};
|
||||
|
||||
makeInstallerOptions.fallback.resolve = function (id, parentId, error) {
|
||||
if (topLevelIdPattern.test(id)) {
|
||||
// Allow any top-level identifier to resolve to itself on the server,
|
||||
// so that makeInstallerOptions.fallback has a chance to handle it.
|
||||
return id;
|
||||
}
|
||||
|
||||
throw error;
|
||||
};
|
||||
|
||||
meteorInstall = makeInstaller(makeInstallerOptions);
|
||||
var Module = meteorInstall.Module;
|
||||
|
||||
Module.prototype.useNode = function () {
|
||||
if (typeof npmRequire !== "function") {
|
||||
// Can't use Node if npmRequire is not defined.
|
||||
return false;
|
||||
}
|
||||
|
||||
var parts = this.id.split("/");
|
||||
var start = 0;
|
||||
if (parts[start] === "") ++start;
|
||||
if (parts[start] === "node_modules" &&
|
||||
parts[start + 1] === "meteor") {
|
||||
start += 2;
|
||||
}
|
||||
|
||||
if (parts.indexOf("node_modules", start) < 0) {
|
||||
// Don't try to use Node for modules that aren't in node_modules
|
||||
// directories.
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
npmRequire.resolve(this.id);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.exports = npmRequire(this.id);
|
||||
|
||||
return true;
|
||||
};
|
||||
26
packages/modules/.npm/package/npm-shrinkwrap.json
generated
26
packages/modules/.npm/package/npm-shrinkwrap.json
generated
@@ -5,10 +5,30 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz",
|
||||
"from": "acorn@>=5.0.0 <5.1.0"
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.0.2.tgz",
|
||||
"from": "minipass@>=2.0.0 <3.0.0"
|
||||
},
|
||||
"minizlib": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.3.tgz",
|
||||
"from": "minizlib@>=1.0.3 <2.0.0"
|
||||
},
|
||||
"reify": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/reify/-/reify-0.7.4.tgz",
|
||||
"from": "reify@0.7.4"
|
||||
"version": "0.11.21",
|
||||
"resolved": "https://registry.npmjs.org/reify/-/reify-0.11.21.tgz",
|
||||
"from": "reify@0.11.21"
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
|
||||
"from": "semver@>=5.3.0 <6.0.0"
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
|
||||
"from": "yallist@>=3.0.0 <4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
try {
|
||||
Buffer = global.Buffer || require("buffer").Buffer;
|
||||
} catch (noBuffer) {}
|
||||
@@ -1,6 +1,5 @@
|
||||
require("./install-packages.js");
|
||||
require("./stubs.js");
|
||||
require("./buffer.js");
|
||||
require("./process.js");
|
||||
require("./reify.js");
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ function install(name, mainModule) {
|
||||
// /node_modules/meteor/<name>/index.js, in the rare but possible event
|
||||
// that the package contains a file called index.js (#6590).
|
||||
|
||||
if (mainModule) {
|
||||
meteorDir[name + ".js"] = [mainModule, function (require, e, module) {
|
||||
module.exports = require(mainModule);
|
||||
}];
|
||||
if (typeof mainModule === "string") {
|
||||
// Set up an alias from /node_modules/meteor/<package>.js to the main
|
||||
// module, e.g. meteor/<package>/index.js.
|
||||
meteorDir[name + ".js"] = mainModule;
|
||||
} else {
|
||||
// back compat with old Meteor packages
|
||||
meteorDir[name + ".js"] = function (r, e, module) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Package.describe({
|
||||
name: "modules",
|
||||
version: "0.8.2",
|
||||
version: "0.9.0",
|
||||
summary: "CommonJS module system",
|
||||
documentation: "README.md"
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
reify: "0.7.4"
|
||||
reify: "0.11.21"
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
@@ -15,6 +15,5 @@ Package.onUse(function(api) {
|
||||
api.mainModule("client.js", "client");
|
||||
api.mainModule("server.js", "server");
|
||||
api.export("meteorInstall");
|
||||
api.export("Buffer");
|
||||
api.export("process");
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var Module = module.constructor;
|
||||
require("reify/lib/runtime").enable(Module);
|
||||
var Mp = Module.prototype;
|
||||
require("reify/lib/runtime").enable(Mp);
|
||||
Mp.importSync = Mp.importSync || Mp.import;
|
||||
Mp.import = Mp.import || Mp.importSync;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
require("./install-packages.js");
|
||||
require("./buffer.js");
|
||||
require("./process.js");
|
||||
require("./reify.js");
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
Package.describe({
|
||||
summary: "Adaptor for using MongoDB and Minimongo over DDP",
|
||||
version: '1.1.17'
|
||||
version: '1.1.18'
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
|
||||
1
packages/non-core/bundle-visualizer/.npm/package/.gitignore
vendored
Normal file
1
packages/non-core/bundle-visualizer/.npm/package/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
node_modules
|
||||
7
packages/non-core/bundle-visualizer/.npm/package/README
Normal file
7
packages/non-core/bundle-visualizer/.npm/package/README
Normal file
@@ -0,0 +1,7 @@
|
||||
This directory and the files immediately inside it are automatically generated
|
||||
when you change this package's NPM dependencies. Commit the files in this
|
||||
directory (npm-shrinkwrap.json, .gitignore, and this README) to source control
|
||||
so that others run the same versions of sub-dependencies.
|
||||
|
||||
You should NOT check in the node_modules directory that Meteor automatically
|
||||
creates; if you are using git, the .gitignore file tells git to ignore it.
|
||||
189
packages/non-core/bundle-visualizer/.npm/package/npm-shrinkwrap.json
generated
Normal file
189
packages/non-core/bundle-visualizer/.npm/package/npm-shrinkwrap.json
generated
Normal file
@@ -0,0 +1,189 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
|
||||
"from": "commander@>=2.0.0 <3.0.0"
|
||||
},
|
||||
"d3": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/d3/-/d3-4.8.0.tgz",
|
||||
"from": "d3@4.8.0"
|
||||
},
|
||||
"d3-array": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.0.tgz",
|
||||
"from": "d3-array@1.2.0"
|
||||
},
|
||||
"d3-axis": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.6.tgz",
|
||||
"from": "d3-axis@1.0.6"
|
||||
},
|
||||
"d3-brush": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.4.tgz",
|
||||
"from": "d3-brush@1.0.4"
|
||||
},
|
||||
"d3-chord": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.4.tgz",
|
||||
"from": "d3-chord@1.0.4"
|
||||
},
|
||||
"d3-collection": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.3.tgz",
|
||||
"from": "d3-collection@1.0.3"
|
||||
},
|
||||
"d3-color": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.3.tgz",
|
||||
"from": "d3-color@1.0.3"
|
||||
},
|
||||
"d3-dispatch": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.3.tgz",
|
||||
"from": "d3-dispatch@1.0.3"
|
||||
},
|
||||
"d3-drag": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.0.4.tgz",
|
||||
"from": "d3-drag@1.0.4"
|
||||
},
|
||||
"d3-dsv": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.5.tgz",
|
||||
"from": "d3-dsv@1.0.5"
|
||||
},
|
||||
"d3-ease": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.3.tgz",
|
||||
"from": "d3-ease@1.0.3"
|
||||
},
|
||||
"d3-force": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.0.6.tgz",
|
||||
"from": "d3-force@1.0.6"
|
||||
},
|
||||
"d3-format": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.2.0.tgz",
|
||||
"from": "d3-format@1.2.0"
|
||||
},
|
||||
"d3-geo": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.6.3.tgz",
|
||||
"from": "d3-geo@1.6.3"
|
||||
},
|
||||
"d3-hierarchy": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.4.tgz",
|
||||
"from": "d3-hierarchy@1.1.4"
|
||||
},
|
||||
"d3-interpolate": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.4.tgz",
|
||||
"from": "d3-interpolate@1.1.4"
|
||||
},
|
||||
"d3-path": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.5.tgz",
|
||||
"from": "d3-path@1.0.5"
|
||||
},
|
||||
"d3-polygon": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.3.tgz",
|
||||
"from": "d3-polygon@1.0.3"
|
||||
},
|
||||
"d3-quadtree": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.3.tgz",
|
||||
"from": "d3-quadtree@1.0.3"
|
||||
},
|
||||
"d3-queue": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/d3-queue/-/d3-queue-3.0.5.tgz",
|
||||
"from": "d3-queue@3.0.5"
|
||||
},
|
||||
"d3-random": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.0.3.tgz",
|
||||
"from": "d3-random@1.0.3"
|
||||
},
|
||||
"d3-request": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/d3-request/-/d3-request-1.0.5.tgz",
|
||||
"from": "d3-request@1.0.5"
|
||||
},
|
||||
"d3-scale": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.5.tgz",
|
||||
"from": "d3-scale@1.0.5"
|
||||
},
|
||||
"d3-selection": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.0.5.tgz",
|
||||
"from": "d3-selection@1.0.5"
|
||||
},
|
||||
"d3-shape": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.0.6.tgz",
|
||||
"from": "d3-shape@1.0.6"
|
||||
},
|
||||
"d3-time": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.6.tgz",
|
||||
"from": "d3-time@1.0.6"
|
||||
},
|
||||
"d3-time-format": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.0.5.tgz",
|
||||
"from": "d3-time-format@2.0.5"
|
||||
},
|
||||
"d3-timer": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.5.tgz",
|
||||
"from": "d3-timer@1.0.5"
|
||||
},
|
||||
"d3-transition": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.0.4.tgz",
|
||||
"from": "d3-transition@1.0.4"
|
||||
},
|
||||
"d3-voronoi": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz",
|
||||
"from": "d3-voronoi@1.1.2"
|
||||
},
|
||||
"d3-zoom": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.1.4.tgz",
|
||||
"from": "d3-zoom@1.1.4"
|
||||
},
|
||||
"graceful-readlink": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
|
||||
"from": "graceful-readlink@>=1.0.0"
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.17",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.17.tgz",
|
||||
"from": "iconv-lite@>=0.4.0 <0.5.0"
|
||||
},
|
||||
"pretty-bytes": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz",
|
||||
"from": "pretty-bytes@4.0.2"
|
||||
},
|
||||
"rw": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
|
||||
"from": "rw@>=1.0.0 <2.0.0"
|
||||
},
|
||||
"xmlhttprequest": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
|
||||
"from": "xmlhttprequest@>=1.0.0 <2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
1
packages/non-core/bundle-visualizer/README.md
Normal file
1
packages/non-core/bundle-visualizer/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# bundle-visualizer
|
||||
3
packages/non-core/bundle-visualizer/classNames.js
Normal file
3
packages/non-core/bundle-visualizer/classNames.js
Normal file
@@ -0,0 +1,3 @@
|
||||
import { prefixedClass } from "./common.js";
|
||||
export const rootContainer = prefixedClass("rootContainer");
|
||||
export const mask = prefixedClass("mask");
|
||||
46
packages/non-core/bundle-visualizer/client.js
Normal file
46
packages/non-core/bundle-visualizer/client.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import { Meteor } from "meteor/meteor";
|
||||
import {
|
||||
classPrefix,
|
||||
methodNameStats,
|
||||
packageName,
|
||||
} from "./common.js";
|
||||
import * as classes from "./classNames.js";
|
||||
|
||||
import "./style.css";
|
||||
|
||||
Meteor.startup(() => {
|
||||
import("./sunburst.js").then(s => main(s.Sunburst));
|
||||
});
|
||||
|
||||
function main(builder) {
|
||||
const { container, mask } = frameStage();
|
||||
|
||||
document.body.appendChild(mask);
|
||||
document.body.appendChild(container);
|
||||
|
||||
Meteor.call(methodNameStats, (error, result) => {
|
||||
if (error) {
|
||||
console.error([
|
||||
`${packageName}: Couldn't load stats for visualization.`,
|
||||
"Are you using standard-minifier-js >= 2.1.0 as the minifier?",
|
||||
].join(" "));
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the JSON, which is `d3-hierarchy` digestible.
|
||||
if (result) {
|
||||
new builder({ container }).loadJson(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function frameStage() {
|
||||
// Create the mask which will block out the main application.
|
||||
const mask = document.createElement("div");
|
||||
mask.setAttribute("class", `${classPrefix} ${classes.mask}`);
|
||||
|
||||
// Create the container which the SVG elements will be drawn into.
|
||||
const container = document.createElement("div");
|
||||
container.setAttribute("class", `${classPrefix} ${classes.rootContainer}`);
|
||||
return { container, mask };
|
||||
}
|
||||
14
packages/non-core/bundle-visualizer/common.js
Normal file
14
packages/non-core/bundle-visualizer/common.js
Normal file
@@ -0,0 +1,14 @@
|
||||
export const packageName = "bundle-visualizer";
|
||||
export const classPrefix = "meteorBundleVisualizer";
|
||||
export const methodNameStats = `_meteor/${packageName}/stats`;
|
||||
export const typeBundle = "bundle";
|
||||
export const typePackage = "package";
|
||||
export const typeNodeModules = "node_modules";
|
||||
|
||||
function capitalizeFirstLetter(str) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
export function prefixedClass(className) {
|
||||
return `${classPrefix}${capitalizeFirstLetter(className)}`;
|
||||
}
|
||||
23
packages/non-core/bundle-visualizer/package.js
Normal file
23
packages/non-core/bundle-visualizer/package.js
Normal file
@@ -0,0 +1,23 @@
|
||||
Package.describe({
|
||||
version: '1.0.1',
|
||||
summary: 'Meteor bundle analysis and visualization.',
|
||||
documentation: 'README.md',
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
"d3-selection": "1.0.5",
|
||||
"d3-shape": "1.0.6",
|
||||
"d3-hierarchy": "1.1.4",
|
||||
"d3-transition": "1.0.4",
|
||||
"pretty-bytes": "4.0.2",
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.use('isobuild:dynamic-import@1.5.0');
|
||||
api.use([
|
||||
'ecmascript',
|
||||
'dynamic-import',
|
||||
]);
|
||||
api.mainModule('server.js', 'server');
|
||||
api.mainModule('client.js', 'client');
|
||||
});
|
||||
144
packages/non-core/bundle-visualizer/server.js
Normal file
144
packages/non-core/bundle-visualizer/server.js
Normal file
@@ -0,0 +1,144 @@
|
||||
import assert from "assert";
|
||||
import { readFileSync as fsReadFileSync } from "fs";
|
||||
|
||||
import { Meteor } from "meteor/meteor";
|
||||
import { WebAppInternals } from "meteor/webapp";
|
||||
|
||||
import {
|
||||
methodNameStats,
|
||||
packageName,
|
||||
typeBundle,
|
||||
typeNodeModules,
|
||||
typePackage,
|
||||
} from "./common.js";
|
||||
|
||||
if (Meteor.isProduction) {
|
||||
console.warn([
|
||||
`=> The "${packageName}" package is currently enabled. Visit your`,
|
||||
"application in a web browser to view the client bundle analysis and",
|
||||
"'meteor remove' the package before building/deploying the final bundle.",
|
||||
].join(" "));
|
||||
} else {
|
||||
console.warn([
|
||||
"=> In order to provide accurate measurements using minified bundles,",
|
||||
`the "${packageName}" package requires running 'meteor --production'`,
|
||||
"to simulate production bundling."
|
||||
].join(" "));
|
||||
}
|
||||
|
||||
function getStatBundles() {
|
||||
const statFileFilter = f =>
|
||||
f.type === "json" &&
|
||||
f.absolutePath &&
|
||||
f.absolutePath.endsWith(".stats.json");
|
||||
|
||||
// Read the stat file, but if it's in any way unusable just return null.
|
||||
const readOrNull = file => {
|
||||
try {
|
||||
return JSON.parse(fsReadFileSync(file, "utf8"));
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return Object.keys(WebAppInternals.staticFiles)
|
||||
.map(staticFile => WebAppInternals.staticFiles[staticFile])
|
||||
.filter(statFileFilter)
|
||||
.map(statFile => ({
|
||||
name: statFile.hash,
|
||||
stats: readOrNull(statFile.absolutePath),
|
||||
}));
|
||||
}
|
||||
|
||||
function _childModules(node) {
|
||||
return Object.keys(node)
|
||||
.map(module => {
|
||||
const result = {
|
||||
name: module,
|
||||
type: typeNodeModules,
|
||||
};
|
||||
|
||||
if (typeof node[module] === "object") {
|
||||
result.children = _childModules(node[module]);
|
||||
} else {
|
||||
result.size = node[module];
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function d3TreeFromStats(stats) {
|
||||
assert.strictEqual(typeof stats, "object",
|
||||
"Must pass a stats object");
|
||||
assert.strictEqual(typeof stats.minifiedBytesByPackage, "object",
|
||||
"Stats object must contain a `minifiedBytesByPackage` object");
|
||||
|
||||
const sizeOrDetail = (name, node) => {
|
||||
const result = {
|
||||
name,
|
||||
type: typePackage,
|
||||
};
|
||||
|
||||
// A non-leaf is: [size (Number), limb (Object)]
|
||||
// A leaf is size (Number)
|
||||
if (Array.isArray(node)) {
|
||||
const [, detail] = node;
|
||||
result.children = _childModules(detail);
|
||||
} else {
|
||||
result.size = node;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// Main entry into the stats is the `minifiedBytesByPackage` attribute.
|
||||
return Object.keys(stats.minifiedBytesByPackage)
|
||||
.map(name =>
|
||||
sizeOrDetail(name
|
||||
// Change the "packages/bundle.js" name to "(bundle)"
|
||||
.replace(/^[^\/]+\/(.*)\.js$/, "($1)"),
|
||||
stats.minifiedBytesByPackage[name]));
|
||||
}
|
||||
|
||||
Meteor.methods({
|
||||
[methodNameStats]() {
|
||||
const statBundles = getStatBundles();
|
||||
|
||||
// Silently return no data if not simulating production.
|
||||
if (! Meteor.isProduction) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! (statBundles && statBundles.length)) {
|
||||
throw new Meteor.Error("no-stats-bundles", "Unable to retrieve stats");
|
||||
}
|
||||
|
||||
const validStatBundles = statBundles.filter(statBundle => {
|
||||
if (statBundle &&
|
||||
statBundle.stats &&
|
||||
statBundle.stats.minifier &&
|
||||
statBundle.stats.minifier.name === "standard-minifier-js" &&
|
||||
statBundle.stats.minifier.version.startsWith("2.1.")
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (! validStatBundles.length) {
|
||||
throw new Meteor.Error("no-valid-stats", "No valid stats bundles")
|
||||
}
|
||||
|
||||
return {
|
||||
name: "main",
|
||||
children: validStatBundles.map((statBundle, index, array) => ({
|
||||
// TODO: If multiple bundles, could
|
||||
// show abbr. bundle names with:
|
||||
// `...${bundle.name.substr(-3)}`,
|
||||
name: "bundle" + (array.length > 1 ? ` (${index + 1})` : ""),
|
||||
type: typeBundle,
|
||||
children: d3TreeFromStats(statBundle.stats),
|
||||
})),
|
||||
};
|
||||
}
|
||||
});
|
||||
102
packages/non-core/bundle-visualizer/style.css
Normal file
102
packages/non-core/bundle-visualizer/style.css
Normal file
@@ -0,0 +1,102 @@
|
||||
.meteorBundleVisualizer.meteorBundleVisualizerMask {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: #cdcdcd;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.meteorBundleVisualizer.meteorBundleVisualizerRootContainer {
|
||||
position: absolute;
|
||||
z-index: 99999;
|
||||
top: 0;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
width: 960px;
|
||||
height: 700px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.meteorBundleVisualizer.meteorBundleVisualizerRootContainer
|
||||
.meteorBundleVisualizerMain
|
||||
{
|
||||
float: left;
|
||||
width: 950px;
|
||||
}
|
||||
|
||||
.meteorBundleVisualizer.meteorBundleVisualizerRootContainer
|
||||
.meteorBundleVisualizerSequence
|
||||
{
|
||||
width: 800px;
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.meteorBundleVisualizer.meteorBundleVisualizerRootContainer
|
||||
.meteorBundleVisualizerSequence text,
|
||||
{
|
||||
font-weight: 600;
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.meteorBundleVisualizer.meteorBundleVisualizerRootContainer
|
||||
.meteorBundleVisualizerChart
|
||||
{
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.meteorBundleVisualizer.meteorBundleVisualizerRootContainer
|
||||
.meteorBundleVisualizerChart path
|
||||
{
|
||||
stroke: #fff;
|
||||
}
|
||||
|
||||
.meteorBundleVisualizer.meteorBundleVisualizerRootContainer
|
||||
.meteorBundleVisualizerExplanation
|
||||
{
|
||||
position: absolute;
|
||||
top: 260px;
|
||||
left: 405px;
|
||||
width: 140px;
|
||||
text-align: center;
|
||||
color: #000;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.meteorBundleVisualizer.meteorBundleVisualizerRootContainer
|
||||
.meteorBundleVisualizerPercentage
|
||||
{
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
.meteorBundleVisualizer.meteorBundleVisualizerRootContainer
|
||||
.meteorBundleVisualizerBytes
|
||||
{
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.meteorBundleVisualizer.meteorBundleVisualizerRootContainer
|
||||
.meteorBundleVisualizerTrail
|
||||
{
|
||||
position: absolute;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 12px;
|
||||
left: 0;
|
||||
min-width: 180px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.meteorBundleVisualizer.meteorBundleVisualizerRootContainer
|
||||
.meteorBundleVisualizerTrail .meteorBundleVisualizerTrailSegment
|
||||
{
|
||||
height: 40px;
|
||||
border-radius: 3px;
|
||||
border: 2px dotted black;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
line-height: 40px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
275
packages/non-core/bundle-visualizer/sunburst.js
Normal file
275
packages/non-core/bundle-visualizer/sunburst.js
Normal file
@@ -0,0 +1,275 @@
|
||||
/**
|
||||
Inspired-by, borrowed-from and improved-upon another sundial provided under
|
||||
the Apache License:
|
||||
|
||||
https://bl.ocks.org/kerryrodden/766f8f6d31f645c39f488a0befa1e3c8
|
||||
|
||||
Copyright 2013 Google Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import assert from "assert";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
|
||||
// Make a custom "d3" object containing exactly what we need from the
|
||||
// modularized d3 bundles.
|
||||
const d3 = Object.assign({},
|
||||
{ selectAll, select, mouse } = require("d3-selection"),
|
||||
{ arc } = require("d3-shape"),
|
||||
{ hierarchy, partition } = require("d3-hierarchy"),
|
||||
{ keys, entries } = require("d3-collection"),
|
||||
);
|
||||
|
||||
// This is imported only for its side effects, which affect the d3 namespace.
|
||||
import "d3-transition";
|
||||
|
||||
import {
|
||||
typeBundle,
|
||||
typePackage,
|
||||
typeNodeModules,
|
||||
prefixedClass,
|
||||
} from "./common.js";
|
||||
|
||||
import * as classes from "./classNames.js";
|
||||
|
||||
// Dimensions of sunburst.
|
||||
const width = 950;
|
||||
const height = 600;
|
||||
const radius = Math.min(width, height) / 2;
|
||||
|
||||
// Mapping of step names to colors.
|
||||
const DEFAULT_COLORS = {
|
||||
"_default_": "#ababab",
|
||||
[typeBundle]: "#de4f4f",
|
||||
[typePackage]: "#de783b",
|
||||
[typeNodeModules]: "#7b615c",
|
||||
"meteor": "#6ab975",
|
||||
"javascript": "#a173d1",
|
||||
};
|
||||
|
||||
export class Sunburst {
|
||||
constructor({
|
||||
container,
|
||||
colors = DEFAULT_COLORS,
|
||||
} = {}) {
|
||||
this.elements = {};
|
||||
this.colors = colors;
|
||||
this.totalSize = 0;
|
||||
|
||||
assert.strictEqual(typeof container, "object",
|
||||
"Must pass a 'container' element");
|
||||
|
||||
this.elements.container = d3.select(container);
|
||||
|
||||
this.elements.main =
|
||||
this.elements.container
|
||||
.append("div")
|
||||
.attr("class", prefixedClass("main"));
|
||||
|
||||
this.elements.sequence =
|
||||
this.elements.main
|
||||
.append("div")
|
||||
.attr("class", prefixedClass("sequence"));
|
||||
|
||||
this.elements.chart =
|
||||
this.elements.main
|
||||
.append("div")
|
||||
.attr("class", prefixedClass("chart"));
|
||||
|
||||
this.elements.explanation =
|
||||
this.elements.chart
|
||||
.append("div")
|
||||
.attr("class", prefixedClass("explanation"));
|
||||
|
||||
this.elements.percentage =
|
||||
this.elements.explanation
|
||||
.append("span")
|
||||
.attr("class", prefixedClass("percentage"));
|
||||
|
||||
// BR between percentage and bytes.
|
||||
this.elements.explanation.append("br");
|
||||
|
||||
this.elements.bytes =
|
||||
this.elements.explanation
|
||||
.append("span")
|
||||
.attr("class", prefixedClass("bytes"));
|
||||
|
||||
this.svg = this.elements.chart
|
||||
.append("svg:svg")
|
||||
.attr("width", width)
|
||||
.attr("height", height);
|
||||
|
||||
this.vis = this.svg
|
||||
.append("svg:g")
|
||||
.attr("class", prefixedClass("top"))
|
||||
.attr("transform", `translate(${width / 2},${height / 2})`);
|
||||
|
||||
this.partition = d3.partition()
|
||||
.size([2 * Math.PI, radius * radius]);
|
||||
|
||||
this.arc = d3.arc()
|
||||
.startAngle(d => d.x0)
|
||||
.endAngle(d => d.x1)
|
||||
.innerRadius(d => Math.sqrt(d.y0))
|
||||
.outerRadius(d => Math.sqrt(d.y1));
|
||||
}
|
||||
|
||||
getColor(data) {
|
||||
if (data.type === typePackage) {
|
||||
return this.colors[typePackage];
|
||||
}
|
||||
|
||||
if (data.name.endsWith(".js")) {
|
||||
return this.colors.javascript;
|
||||
}
|
||||
|
||||
if (this.colors[data.name]) {
|
||||
return this.colors[data.name];
|
||||
}
|
||||
|
||||
return this.colors._default_;
|
||||
}
|
||||
|
||||
initializeBreadcrumbTrail() {
|
||||
// Add the svg area.
|
||||
this.elements.trail =
|
||||
this.elements.container
|
||||
.append("div")
|
||||
.attr("class", prefixedClass("trail"));
|
||||
}
|
||||
|
||||
loadJson(json) {
|
||||
// Basic setup of page elements.
|
||||
this.initializeBreadcrumbTrail();
|
||||
|
||||
// Bounding circle underneath the sunburst, to make it easier to detect
|
||||
// when the mouse leaves the parent g.
|
||||
this.vis
|
||||
.append("svg:circle")
|
||||
.attr("r", radius)
|
||||
.style("opacity", 0);
|
||||
|
||||
// Turn the data into a d3 hierarchy and calculate the sums.
|
||||
this.root = d3.hierarchy(json)
|
||||
.sum(d => d.size)
|
||||
.sort((a, b) => b.value - a.value);
|
||||
|
||||
// For efficiency, filter nodes to keep only those large enough to see.
|
||||
this.nodes = this
|
||||
.partition(this.root)
|
||||
.descendants()
|
||||
.filter(d => d.x1 - d.x0 > 0.005); // 0.005 radians = 0.29 degrees
|
||||
|
||||
this.path = this.vis.data([json]).selectAll("path")
|
||||
.data(this.nodes)
|
||||
.enter()
|
||||
.append("svg:path")
|
||||
.attr("display", d => d.depth ? null : "none")
|
||||
.attr("d", this.arc)
|
||||
.attr("fill-rule", "evenodd")
|
||||
.style("fill", d => this.getColor(d.data))
|
||||
.style("opacity", 1)
|
||||
.on("mouseover", this.mouseoverEvent());
|
||||
|
||||
// Add the mouseleave handler to the bounding circle.
|
||||
this.vis.on("mouseleave", this.mouseleaveEvent());
|
||||
|
||||
// // Get total size of the tree = value of root node from partition.
|
||||
this.totalSize = this.path.datum().value;
|
||||
}
|
||||
|
||||
mouseoverEvent() {
|
||||
const self = this;
|
||||
return self.mouseover || (self.mouseover = function (d) {
|
||||
const percentage = (100 * d.value / self.totalSize).toPrecision(3);
|
||||
let percentageString = `${percentage}%`;
|
||||
if (percentage < 0.1) {
|
||||
percentageString = "< 0.1%";
|
||||
}
|
||||
|
||||
self.elements.percentage
|
||||
.text(percentageString);
|
||||
|
||||
self.elements.bytes
|
||||
.text(prettyBytes(d.value || 0));
|
||||
|
||||
self.elements.explanation
|
||||
.style("display", null);
|
||||
|
||||
const sequenceArray = d.ancestors().reverse();
|
||||
sequenceArray.shift(); // remove root node from the array
|
||||
self.updateBreadcrumbs(sequenceArray, percentageString);
|
||||
|
||||
// Fade all the segments.
|
||||
d3.selectAll("path")
|
||||
.style("opacity", 0.3);
|
||||
|
||||
// Then highlight only those that are an ancestor of the current segment.
|
||||
self.vis.selectAll("path")
|
||||
.filter((node) => sequenceArray.indexOf(node) >= 0)
|
||||
.style("opacity", 1);
|
||||
});
|
||||
}
|
||||
|
||||
// Restore everything to full opacity when moving off the visualization.
|
||||
mouseleaveEvent() {
|
||||
const self = this;
|
||||
return self.mouseleave || (self.mouseleave = function (d) {
|
||||
// Hide the breadcrumb trail
|
||||
self.elements.trail
|
||||
.style("visibility", "hidden");
|
||||
|
||||
// Deactivate all segments during transition.
|
||||
d3.selectAll("path").on("mouseover", null);
|
||||
|
||||
// Transition each segment to full opacity and then reactivate it.
|
||||
d3.selectAll("path")
|
||||
.transition()
|
||||
.duration(1000)
|
||||
.style("opacity", 1)
|
||||
.on("end", function() {
|
||||
d3.select(this).on("mouseover", self.mouseoverEvent());
|
||||
});
|
||||
|
||||
self.elements.explanation
|
||||
.style("display", "none");
|
||||
});
|
||||
}
|
||||
|
||||
// Update the breadcrumb trail to show the current sequence and percentage.
|
||||
updateBreadcrumbs(nodeArray, percentageString) {
|
||||
// Data join; key function combines name and depth (= position in sequence).
|
||||
const trail = this.elements.trail
|
||||
.selectAll("div")
|
||||
.data(nodeArray, d => d.data.name + d.depth);
|
||||
|
||||
// Remove exiting nodes.
|
||||
trail.exit().remove();
|
||||
|
||||
// Add breadcrumb and label for entering nodes.
|
||||
const entering = trail.enter()
|
||||
.append("div")
|
||||
.attr("class", prefixedClass("trailSegment"))
|
||||
.style("background-color", d => this.getColor(d.data))
|
||||
.text(d => d.data.name);
|
||||
|
||||
// Merge enter and update selections; set position for all nodes.
|
||||
entering
|
||||
.merge(trail);
|
||||
|
||||
// Make the breadcrumb trail visible, if it's hidden.
|
||||
this.elements.trail
|
||||
.style("visibility", "");
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,9 @@
|
||||
"from": "asap@>=2.0.3 <2.1.0"
|
||||
},
|
||||
"meteor-promise": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/meteor-promise/-/meteor-promise-0.8.0.tgz",
|
||||
"from": "meteor-promise@0.8.0"
|
||||
"version": "0.8.4",
|
||||
"resolved": "https://registry.npmjs.org/meteor-promise/-/meteor-promise-0.8.4.tgz",
|
||||
"from": "meteor-promise@0.8.4"
|
||||
},
|
||||
"promise": {
|
||||
"version": "7.1.1",
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
Package.describe({
|
||||
name: "promise",
|
||||
version: "0.8.8",
|
||||
version: "0.8.9",
|
||||
summary: "ECMAScript 2015 Promise polyfill with Fiber support",
|
||||
git: "https://github.com/meteor/promise",
|
||||
documentation: "README.md"
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
"meteor-promise": "0.8.0",
|
||||
"meteor-promise": "0.8.4",
|
||||
"promise": "7.1.1"
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.use("modules@0.7.6");
|
||||
api.use("modules");
|
||||
api.mainModule("client.js", "client");
|
||||
api.mainModule("server.js", "server");
|
||||
api.export("Promise");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Reactive dictionary",
|
||||
version: '1.1.8'
|
||||
version: '1.1.9'
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: 'standard-minifier-js',
|
||||
version: '2.0.0',
|
||||
version: '2.1.0',
|
||||
summary: 'Standard javascript minifiers used with Meteor apps by default.',
|
||||
documentation: 'README.md',
|
||||
});
|
||||
@@ -9,9 +9,14 @@ Package.registerBuildPlugin({
|
||||
name: "minifyStdJS",
|
||||
use: [
|
||||
'minifier-js',
|
||||
'babel-compiler',
|
||||
'ecmascript'
|
||||
],
|
||||
sources: [
|
||||
'plugin/minify-js.js',
|
||||
'plugin/stats.js',
|
||||
'plugin/visitor.js',
|
||||
'plugin/utils.js',
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { extractModuleSizesTree } from "./stats.js";
|
||||
|
||||
Plugin.registerMinifier({
|
||||
extensions: ['js'],
|
||||
archMatching: 'web'
|
||||
@@ -108,37 +110,52 @@ MeteorBabelMinifier.prototype.processFilesForBundle = function(files, options) {
|
||||
}
|
||||
}
|
||||
|
||||
var allJs = '';
|
||||
files.forEach(function (file) {
|
||||
// Don't reminify *.min.js.
|
||||
if (/\.min\.js$/.test(file.getPathInBundle())) {
|
||||
allJs += file.getContentsAsString();
|
||||
} else {
|
||||
var minified;
|
||||
const toBeAdded = {
|
||||
data: "",
|
||||
stats: Object.create(null)
|
||||
};
|
||||
|
||||
try {
|
||||
minified = meteorJsMinify(file.getContentsAsString());
|
||||
files.forEach(file => {
|
||||
// Don't reminify *.min.js.
|
||||
if (/\.min\.js$/.test(file.getPathInBundle())) {
|
||||
toBeAdded.data += file.getContentsAsString();
|
||||
} else {
|
||||
var minified;
|
||||
|
||||
if (!(minified && typeof minified.code === "string")) {
|
||||
throw new Error();
|
||||
}
|
||||
} catch (err) {
|
||||
var filePath = file.getPathInBundle();
|
||||
try {
|
||||
minified = meteorJsMinify(file.getContentsAsString());
|
||||
|
||||
maybeThrowMinifyErrorBySourceFile(err, file);
|
||||
|
||||
err.message += " while minifying " + filePath;
|
||||
throw err;
|
||||
if (!(minified && typeof minified.code === "string")) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
allJs += minified.code;
|
||||
}
|
||||
allJs += '\n\n';
|
||||
} catch (err) {
|
||||
var filePath = file.getPathInBundle();
|
||||
|
||||
Plugin.nudge();
|
||||
});
|
||||
maybeThrowMinifyErrorBySourceFile(err, file);
|
||||
|
||||
err.message += " while minifying " + filePath;
|
||||
throw err;
|
||||
}
|
||||
|
||||
const tree = extractModuleSizesTree(minified.code);
|
||||
if (tree) {
|
||||
toBeAdded.stats[file.getPathInBundle()] =
|
||||
[Buffer.byteLength(minified.code), tree];
|
||||
} else {
|
||||
toBeAdded.stats[file.getPathInBundle()] =
|
||||
Buffer.byteLength(minified.code);
|
||||
}
|
||||
|
||||
toBeAdded.data += minified.code;
|
||||
}
|
||||
|
||||
toBeAdded.data += '\n\n';
|
||||
|
||||
Plugin.nudge();
|
||||
});
|
||||
|
||||
if (files.length) {
|
||||
files[0].addJavaScript({ data: allJs });
|
||||
files[0].addJavaScript(toBeAdded);
|
||||
}
|
||||
};
|
||||
|
||||
83
packages/standard-minifier-js/plugin/stats.js
Normal file
83
packages/standard-minifier-js/plugin/stats.js
Normal file
@@ -0,0 +1,83 @@
|
||||
import Visitor from "./visitor.js";
|
||||
|
||||
// This RegExp will be used to scan the source for calls to meteorInstall,
|
||||
// taking into consideration that the function name may have been mangled
|
||||
// to something other than "meteorInstall" by the minifier.
|
||||
const meteorInstallRegExp = new RegExp([
|
||||
// If meteorInstall is called by its unminified name, then that's what
|
||||
// we should be looking for in the AST.
|
||||
/\b(meteorInstall)\(\{/,
|
||||
// If the meteorInstall function name has been minified, we can figure
|
||||
// out its mangled name by examining the import assingment.
|
||||
/\b(\w+)=Package.modules.meteorInstall\b/,
|
||||
/\b(\w+)=Package\["modules-runtime"\].meteorInstall\b/,
|
||||
].map(exp => exp.source).join("|"));
|
||||
|
||||
export function extractModuleSizesTree(source) {
|
||||
const match = meteorInstallRegExp.exec(source);
|
||||
if (match) {
|
||||
const ast = Babel.parse(source);
|
||||
const name = match[1] || match[2] || match[3];
|
||||
meteorInstallVisitor.visit(ast, name, source);
|
||||
return meteorInstallVisitor.tree;
|
||||
}
|
||||
}
|
||||
|
||||
const meteorInstallVisitor = new (class extends Visitor {
|
||||
reset(root, meteorInstallName, source) {
|
||||
this.name = meteorInstallName;
|
||||
this.source = source;
|
||||
this.tree = null;
|
||||
}
|
||||
|
||||
visitCallExpression(node) {
|
||||
if (this.tree !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isIdWithName(node.callee, this.name)) {
|
||||
const source = this.source;
|
||||
|
||||
function walk(expr) {
|
||||
if (expr.type !== "ObjectExpression") {
|
||||
return Buffer.byteLength(source.slice(expr.start, expr.end));
|
||||
}
|
||||
|
||||
const contents = Object.create(null);
|
||||
|
||||
expr.properties.forEach(prop => {
|
||||
const keyName = getKeyName(prop.key);
|
||||
if (typeof keyName === "string") {
|
||||
contents[keyName] = walk(prop.value);
|
||||
}
|
||||
});
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
this.tree = walk(node.arguments[0]);
|
||||
|
||||
} else {
|
||||
this.visitChildren(node);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function isIdWithName(node, name) {
|
||||
return node &&
|
||||
node.type === "Identifier" &&
|
||||
node.name === name;
|
||||
}
|
||||
|
||||
function getKeyName(key) {
|
||||
if (key.type === "Identifier") {
|
||||
return key.name;
|
||||
}
|
||||
|
||||
if (key.type === "StringLiteral" ||
|
||||
key.type === "Literal") {
|
||||
return key.value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
26
packages/standard-minifier-js/plugin/utils.js
Normal file
26
packages/standard-minifier-js/plugin/utils.js
Normal file
@@ -0,0 +1,26 @@
|
||||
"use strict";
|
||||
|
||||
const codeOfA = "A".charCodeAt(0);
|
||||
const codeOfZ = "Z".charCodeAt(0);
|
||||
|
||||
export function isObject(value) {
|
||||
return typeof value === "object" && value !== null;
|
||||
}
|
||||
|
||||
// Without a complete list of Node .type names, we have to settle for this
|
||||
// fuzzy matching of object shapes. However, the infeasibility of
|
||||
// maintaining a complete list of type names is one of the reasons we're
|
||||
// using the FastPath/Visitor abstraction in the first place.
|
||||
export function isNodeLike(value) {
|
||||
return isObject(value) &&
|
||||
! Array.isArray(value) &&
|
||||
isCapitalized(value.type);
|
||||
}
|
||||
|
||||
function isCapitalized(string) {
|
||||
if (typeof string !== "string") {
|
||||
return false;
|
||||
}
|
||||
const code = string.charCodeAt(0);
|
||||
return code >= codeOfA && code <= codeOfZ;
|
||||
}
|
||||
57
packages/standard-minifier-js/plugin/visitor.js
Normal file
57
packages/standard-minifier-js/plugin/visitor.js
Normal file
@@ -0,0 +1,57 @@
|
||||
"use strict";
|
||||
|
||||
import {
|
||||
isObject,
|
||||
isNodeLike,
|
||||
} from "./utils.js";
|
||||
|
||||
const codeOfUnderscore = "_".charCodeAt(0);
|
||||
|
||||
export default class Visitor {
|
||||
visit(root) {
|
||||
this.reset.apply(this, arguments);
|
||||
this.visitWithoutReset(root);
|
||||
}
|
||||
|
||||
visitWithoutReset(node) {
|
||||
if (Array.isArray(node)) {
|
||||
node.forEach(this.visitWithoutReset, this);
|
||||
} else if (isNodeLike(node)) {
|
||||
const method = this["visit" + node.type];
|
||||
if (typeof method === "function") {
|
||||
// The method must call this.visitChildren(node) to continue
|
||||
// traversing.
|
||||
method.call(this, node);
|
||||
} else {
|
||||
this.visitChildren(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitChildren(node) {
|
||||
if (! isNodeLike(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const keys = Object.keys(node);
|
||||
const keyCount = keys.length;
|
||||
|
||||
for (let i = 0; i < keyCount; ++i) {
|
||||
const key = keys[i];
|
||||
|
||||
if (key === "loc" || // Ignore .loc.{start,end} objects.
|
||||
// Ignore "private" properties added by Babel.
|
||||
key.charCodeAt(0) === codeOfUnderscore) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const child = node[key];
|
||||
if (! isObject(child)) {
|
||||
// Ignore properties whose values aren't objects.
|
||||
continue;
|
||||
}
|
||||
|
||||
this.visitWithoutReset(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ export METEOR_HOME=`pwd`
|
||||
|
||||
export PATH=$METEOR_HOME:$PATH
|
||||
# synchronously get the dev bundle and NPM modules if they're not there.
|
||||
./meteor --get-ready || exit 1
|
||||
./meteor --help || exit 1
|
||||
|
||||
export URL='http://localhost:4096/'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Serves a Meteor app over HTTP",
|
||||
version: '1.3.15'
|
||||
version: '1.3.16'
|
||||
});
|
||||
|
||||
Npm.depends({connect: "2.30.2",
|
||||
|
||||
@@ -395,7 +395,8 @@ WebAppInternals.staticFilesMiddleware = function (staticFiles, req, res, next) {
|
||||
info.sourceMapUrl);
|
||||
}
|
||||
|
||||
if (info.type === "js") {
|
||||
if (info.type === "js" ||
|
||||
info.type === "dynamic js") {
|
||||
res.setHeader("Content-Type", "application/javascript; charset=UTF-8");
|
||||
} else if (info.type === "css") {
|
||||
res.setHeader("Content-Type", "text/css; charset=UTF-8");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"track": "METEOR",
|
||||
"version": "1.4.4.3-rc.0",
|
||||
"version": "1.5-rc.13",
|
||||
"recommended": false,
|
||||
"official": false,
|
||||
"description": "Meteor"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"track": "METEOR",
|
||||
"version": "1.4.4.3",
|
||||
"version": "1.5",
|
||||
"recommended": false,
|
||||
"official": true,
|
||||
"patchFrom": ["1.4.4.2"],
|
||||
"description": "The Official Meteor Distribution"
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ UNAME=$(uname)
|
||||
ARCH=$(uname -m)
|
||||
MONGO_VERSION=3.2.12
|
||||
NODE_VERSION=4.8.3
|
||||
NPM_VERSION=4.5.0
|
||||
NPM_VERSION=4.6.1
|
||||
|
||||
if [ "$UNAME" == "Linux" ] ; then
|
||||
if [ "$ARCH" != "i686" -a "$ARCH" != "x86_64" ] ; then
|
||||
|
||||
@@ -9,7 +9,7 @@ var packageJson = {
|
||||
// Version is not important but is needed to prevent warnings.
|
||||
version: "0.0.0",
|
||||
dependencies: {
|
||||
"meteor-promise": "0.8.0",
|
||||
"meteor-promise": "0.8.4",
|
||||
fibers: "1.0.15",
|
||||
promise: "7.1.1",
|
||||
// Not yet upgrading Underscore from 1.5.2 to 1.7.0 (which should be done
|
||||
|
||||
@@ -11,17 +11,18 @@ var packageJson = {
|
||||
dependencies: {
|
||||
// Explicit dependency because we are replacing it with a bundled version
|
||||
// and we want to make sure there are no dependencies on a higher version
|
||||
npm: "4.5.0",
|
||||
npm: "4.6.1",
|
||||
"node-gyp": "3.6.0",
|
||||
"node-pre-gyp": "0.6.34",
|
||||
"meteor-babel": "0.20.1",
|
||||
"meteor-promise": "0.8.0",
|
||||
"meteor-babel": "0.21.4",
|
||||
reify: "0.11.21",
|
||||
"meteor-promise": "0.8.4",
|
||||
fibers: "1.0.15",
|
||||
promise: "7.1.1",
|
||||
// So that Babel 6 can emit require("babel-runtime/helpers/...") calls.
|
||||
"babel-runtime": "6.9.2",
|
||||
// For various ES2015 polyfills, such as Map and Set.
|
||||
"meteor-ecmascript-runtime": "0.2.9",
|
||||
"meteor-ecmascript-runtime": "0.3.0",
|
||||
// Not yet upgrading Underscore from 1.5.2 to 1.7.0 (which should be done
|
||||
// in the package too) because we should consider using lodash instead
|
||||
// (and there are backwards-incompatible changes either way).
|
||||
|
||||
@@ -1788,8 +1788,10 @@ main.registerCommand({
|
||||
" are available:");
|
||||
_.each(nonlatestIndirectDeps, printItem);
|
||||
Console.info([
|
||||
"To update one or more of these packages, pass their names to ",
|
||||
"`meteor update`, or just run `meteor update --all-packages`."
|
||||
"These versions may not be compatible with your project.",
|
||||
"To update one or more of these packages to their latest",
|
||||
"compatible versions, pass their names to `meteor update`,",
|
||||
"or just run `meteor update --all-packages`.",
|
||||
].join("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,6 +159,7 @@ import Builder from './builder.js';
|
||||
var compilerPluginModule = require('./compiler-plugin.js');
|
||||
import { JsFile, CssFile } from './minifier-plugin.js';
|
||||
var meteorNpm = require('./meteor-npm.js');
|
||||
import { addToTree } from "./linker.js";
|
||||
|
||||
var files = require('../fs/files.js');
|
||||
var archinfo = require('../utils/archinfo.js');
|
||||
@@ -170,6 +171,7 @@ var packageVersionParser = require('../packaging/package-version-parser.js');
|
||||
var release = require('../packaging/release.js');
|
||||
import { load as loadIsopacket } from '../tool-env/isopackets.js';
|
||||
import { CORDOVA_PLATFORM_VERSIONS } from '../cordova';
|
||||
import { gzipSync } from "zlib";
|
||||
|
||||
// files to ignore when bundling. node has no globs, so use regexps
|
||||
exports.ignoreFiles = [
|
||||
@@ -693,7 +695,7 @@ class File {
|
||||
|
||||
setTargetPathFromRelPath(relPath) {
|
||||
// XXX hack
|
||||
if (relPath.match(/^packages\//) || relPath.match(/^assets\//)) {
|
||||
if (relPath.match(/^(packages|assets|dynamic)\//)) {
|
||||
this.targetPath = relPath;
|
||||
} else {
|
||||
this.targetPath = files.pathJoin('app', relPath);
|
||||
@@ -1056,6 +1058,9 @@ class Target {
|
||||
const jsOutputFilesMap = compilerPluginModule.PackageSourceBatch
|
||||
.computeJsOutputFilesMap(sourceBatches);
|
||||
|
||||
const versions = {};
|
||||
const dynamicImportFiles = new Set;
|
||||
|
||||
// Copy their resources into the bundle in order
|
||||
sourceBatches.forEach((sourceBatch) => {
|
||||
const unibuild = sourceBatch.unibuild;
|
||||
@@ -1177,6 +1182,16 @@ class Target {
|
||||
throw new Error('Unknown type ' + resource.type);
|
||||
});
|
||||
|
||||
this.js.forEach(file => {
|
||||
if (file.targetPath === "packages/dynamic-import.js") {
|
||||
dynamicImportFiles.add(file);
|
||||
}
|
||||
|
||||
if (file.targetPath.startsWith("dynamic/")) {
|
||||
addToTree(file.hash(), file.targetPath, versions);
|
||||
}
|
||||
});
|
||||
|
||||
// Depend on the source files that produced these resources.
|
||||
this.watchSet.merge(unibuild.watchSet);
|
||||
|
||||
@@ -1185,33 +1200,78 @@ class Target {
|
||||
// XXX assumes that this merges cleanly
|
||||
this.watchSet.merge(unibuild.pkg.pluginWatchSet);
|
||||
});
|
||||
|
||||
dynamicImportFiles.forEach(file => {
|
||||
file.setContents(
|
||||
new Buffer(file.contents("utf8").replace(
|
||||
"__DYNAMIC_VERSIONS__",
|
||||
() => JSON.stringify(versions.dynamic || {})
|
||||
), "utf8")
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Minify the JS in this target
|
||||
minifyJs(minifierDef, minifyMode) {
|
||||
const sources = _.map(this.js, function (file) {
|
||||
return new JsFile(file, {
|
||||
arch: this.arch
|
||||
});
|
||||
const staticFiles = [];
|
||||
const dynamicFiles = [];
|
||||
|
||||
this.js.forEach(file => {
|
||||
const jsf = new JsFile(file, { arch: this.arch });
|
||||
|
||||
if (file.targetPath.startsWith("dynamic/")) {
|
||||
// Make sure file._hash is cached.
|
||||
file.hash();
|
||||
|
||||
// Dynamic files consist of a single anonymous function
|
||||
// expression, which some minifiers (e.g. UglifyJS) either fail to
|
||||
// parse or mistakenly eliminate as dead code. To avoid these
|
||||
// problems, we temporarily name the function __minifyJs.
|
||||
file._contents = new Buffer(
|
||||
file.contents()
|
||||
.toString("utf8")
|
||||
.replace(/^\s*function\s*\(/,
|
||||
"function __minifyJs("),
|
||||
"utf8"
|
||||
);
|
||||
|
||||
dynamicFiles.push(jsf);
|
||||
|
||||
} else {
|
||||
staticFiles.push(jsf);
|
||||
}
|
||||
});
|
||||
var minifier = minifierDef.userPlugin.processFilesForBundle.bind(
|
||||
minifierDef.userPlugin);
|
||||
|
||||
var minifier = minifierDef.userPlugin.processFilesForBundle
|
||||
.bind(minifierDef.userPlugin);
|
||||
|
||||
buildmessage.enterJob('minifying app code', function () {
|
||||
try {
|
||||
var markedMinifier = buildmessage.markBoundary(minifier);
|
||||
markedMinifier(sources, { minifyMode });
|
||||
markedMinifier(staticFiles, { minifyMode });
|
||||
dynamicFiles.forEach(file => {
|
||||
markedMinifier([file], { minifyMode });
|
||||
});
|
||||
} catch (e) {
|
||||
buildmessage.exception(e);
|
||||
}
|
||||
});
|
||||
|
||||
this.js = _.flatten(sources.map((source) => {
|
||||
return source._minifiedFiles.map((file) => {
|
||||
const js = [];
|
||||
|
||||
function handle(source, dynamic) {
|
||||
source._minifiedFiles.forEach(file => {
|
||||
// Remove the function name __minifyJs that was added above.
|
||||
file.data = file.data
|
||||
.toString("utf8")
|
||||
.replace(/^\s*function\s+__minifyJs\s*\(/,
|
||||
"function(");
|
||||
|
||||
const newFile = new File({
|
||||
info: 'minified js',
|
||||
data: new Buffer(file.data, 'utf8')
|
||||
data: new Buffer(file.data, 'utf8'),
|
||||
});
|
||||
|
||||
if (file.sourceMap) {
|
||||
newFile.setSourceMap(file.sourceMap, '/');
|
||||
}
|
||||
@@ -1219,13 +1279,58 @@ class Target {
|
||||
if (file.path) {
|
||||
newFile.setUrlFromRelPath(file.path);
|
||||
newFile.targetPath = file.path;
|
||||
} else if (dynamic) {
|
||||
const { targetPath } = source._source;
|
||||
newFile.setUrlFromRelPath(targetPath);
|
||||
newFile.targetPath = targetPath;
|
||||
} else {
|
||||
newFile.setUrlToHash('.js', '?meteor_js_resource=true');
|
||||
}
|
||||
|
||||
return newFile;
|
||||
js.push(newFile);
|
||||
|
||||
if (file.stats &&
|
||||
! dynamic &&
|
||||
minifyMode === "production") {
|
||||
// If the minifier reported any statistics, serve those data as
|
||||
// a .stats.json file alongside the newFile.
|
||||
const contents = newFile.contents();
|
||||
const statsFile = new File({
|
||||
info: "bundle size stats JSON",
|
||||
data: new Buffer(JSON.stringify({
|
||||
minifier: {
|
||||
name: minifierDef.isopack.name,
|
||||
version: minifierDef.isopack.version,
|
||||
},
|
||||
totalMinifiedBytes: contents.length,
|
||||
totalMinifiedGzipBytes: gzipSync(contents).length,
|
||||
minifiedBytesByPackage: file.stats,
|
||||
}, null, 2) + "\n", "utf8")
|
||||
});
|
||||
|
||||
statsFile.url = newFile.url.replace(/\.js\b/, ".stats.json");
|
||||
statsFile.targetPath =
|
||||
newFile.targetPath.replace(/\.js\b/, ".stats.json");
|
||||
statsFile.cacheable = true;
|
||||
statsFile.type = "json";
|
||||
|
||||
if (statsFile.url !== newFile.url &&
|
||||
statsFile.targetPath !== newFile.targetPath) {
|
||||
// If the minifier used a file extension other than .js, the
|
||||
// .replace calls above won't inject the .stats.json extension
|
||||
// into the statsFile.{url,targetPath} strings, and it would
|
||||
// be a mistake to serve the statsFile with the same URL as
|
||||
// the real JS bundle. This should be a very uncommon case.
|
||||
js.push(statsFile);
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
staticFiles.forEach(file => handle(file, false));
|
||||
dynamicFiles.forEach(file => handle(file, true));
|
||||
|
||||
this.js = js;
|
||||
}
|
||||
|
||||
// For every source file we process, sets the domain name to
|
||||
@@ -1437,7 +1542,7 @@ class ClientTarget extends Target {
|
||||
const eachResource = function (f) {
|
||||
["js", "css", "asset"].forEach((type) => {
|
||||
this[type].forEach((file) => {
|
||||
f(file, type);
|
||||
f(file, file.type || type);
|
||||
});
|
||||
});
|
||||
}.bind(this);
|
||||
@@ -1493,9 +1598,57 @@ class ClientTarget extends Target {
|
||||
manifestItem.size = file.size();
|
||||
manifestItem.hash = file.hash();
|
||||
|
||||
writeFile(file, builder);
|
||||
if (! file.targetPath.startsWith("dynamic/")) {
|
||||
writeFile(file, builder);
|
||||
manifest.push(manifestItem);
|
||||
return;
|
||||
}
|
||||
|
||||
// Another measure for preventing this file from being loaded
|
||||
// eagerly as a <script> tag, in addition to manifestItem.path being
|
||||
// prefixed with "dynamic/".
|
||||
manifestItem.type = "dynamic js";
|
||||
|
||||
// Add the dynamic module to the manifest so that it can be
|
||||
// requested via HTTP from the web server. Note, however, that we
|
||||
// typically request dynamic modules via DDP, since we can compress
|
||||
// the entire response more easily that way. We expose dynamic
|
||||
// modules via HTTP here mostly to unlock future experimentation.
|
||||
manifest.push(manifestItem);
|
||||
|
||||
if (manifestItem.sourceMap &&
|
||||
manifestItem.sourceMapUrl) {
|
||||
// If the file is a dynamic module, we don't embed its source map
|
||||
// in the file itself (because base64-encoded data: URLs for
|
||||
// source maps can be very large), but rather include a normal URL
|
||||
// referring to the source map (as a comment), so that it can be
|
||||
// loaded from the web server when needed.
|
||||
writeFile(file, builder, {
|
||||
sourceMapUrl: manifestItem.sourceMapUrl,
|
||||
});
|
||||
|
||||
manifest.push({
|
||||
type: "json",
|
||||
path: manifestItem.sourceMap,
|
||||
url: manifestItem.sourceMapUrl,
|
||||
where: manifestItem.where,
|
||||
cacheable: manifestItem.cacheable,
|
||||
hash: manifestItem.hash,
|
||||
});
|
||||
|
||||
// Now that we've written the module with a source map URL comment
|
||||
// embedded in it, and also made sure the source map is exposed by
|
||||
// the web server, we do not need to include the source map URL in
|
||||
// the manifest, because then it would also be provided via the
|
||||
// X-SourceMap HTTP header, redundantly.
|
||||
delete manifestItem.sourceMap;
|
||||
delete manifestItem.sourceMapUrl;
|
||||
|
||||
} else {
|
||||
// If the dynamic module does not have a source map, just write it
|
||||
// normally.
|
||||
writeFile(file, builder);
|
||||
}
|
||||
});
|
||||
|
||||
['head', 'body'].forEach((type) => {
|
||||
@@ -1966,11 +2119,11 @@ class JsImage {
|
||||
);
|
||||
|
||||
var sourceMapFileName = files.pathBasename(loadItem.sourceMap);
|
||||
|
||||
// Remove any existing sourceMappingURL line. (eg, if roundtripping
|
||||
// through JsImage.readFromDisk, don't end up with two!)
|
||||
item.source = item.source.replace(
|
||||
/\n\/\/# sourceMappingURL=.+\n?$/g, '');
|
||||
item.source += "\n//# sourceMappingURL=" + sourceMapFileName + "\n";
|
||||
item.source = addSourceMappingURL(item.source, sourceMapFileName);
|
||||
|
||||
if (item.sourceMapRoot) {
|
||||
loadItem.sourceMapRoot = item.sourceMapRoot;
|
||||
}
|
||||
@@ -2007,7 +2160,9 @@ class JsImage {
|
||||
});
|
||||
}
|
||||
|
||||
load.push(loadItem);
|
||||
if (! item.targetPath.startsWith("dynamic/")) {
|
||||
load.push(loadItem);
|
||||
}
|
||||
});
|
||||
|
||||
const rebuildDirs = Object.create(null);
|
||||
@@ -2351,7 +2506,7 @@ class ServerTarget extends JsImageTarget {
|
||||
ServerTarget.prototype[method] = Profile(`ServerTarget#${method}`, ServerTarget.prototype[method]);
|
||||
});
|
||||
|
||||
var writeFile = Profile("bundler writeFile", function (file, builder) {
|
||||
var writeFile = Profile("bundler writeFile", function (file, builder, options) {
|
||||
if (! file.targetPath) {
|
||||
throw new Error("No targetPath?");
|
||||
}
|
||||
@@ -2363,9 +2518,33 @@ var writeFile = Profile("bundler writeFile", function (file, builder) {
|
||||
// to wait until the server is actually driven by the manifest
|
||||
// (rather than just serving all of the files in a certain
|
||||
// directories)
|
||||
builder.write(file.targetPath, { data: file.contents(), hash: file.hash() });
|
||||
|
||||
let data = file.contents();
|
||||
const hash = file.hash();
|
||||
|
||||
if (options && options.sourceMapUrl) {
|
||||
data = addSourceMappingURL(data, options.sourceMapUrl);
|
||||
}
|
||||
|
||||
if (! Buffer.isBuffer(data)) {
|
||||
data = new Buffer(data, "utf8");
|
||||
}
|
||||
|
||||
builder.write(file.targetPath, { data, hash });
|
||||
});
|
||||
|
||||
// The data argument may be either a Buffer or a string, but this function
|
||||
// always returns a string.
|
||||
function addSourceMappingURL(data, url) {
|
||||
const dataString = data
|
||||
// If data is a Buffer, convert it to a string.
|
||||
.toString("utf8")
|
||||
// Remove any existing source map comments.
|
||||
.replace(/\n\/\/# sourceMappingURL=[^\n]+/g, "");
|
||||
// Append the new source map comment to the end of the code.
|
||||
return dataString + "\n//# sourceMappingURL=" + url + "\n";
|
||||
}
|
||||
|
||||
// Writes a target a path in 'programs'
|
||||
var writeTargetToPath = Profile(
|
||||
"bundler writeTargetToPath",
|
||||
|
||||
@@ -10,7 +10,6 @@ var _ = require('underscore');
|
||||
var Profile = require('../tool-env/profile.js').Profile;
|
||||
import {sha1, readAndWatchFileWithHash} from '../fs/watch.js';
|
||||
import LRU from 'lru-cache';
|
||||
import Fiber from 'fibers';
|
||||
import {sourceMapLength} from '../utils/utils.js';
|
||||
import {Console} from '../console/console.js';
|
||||
import ImportScanner from './import-scanner.js';
|
||||
@@ -62,7 +61,7 @@ import { isTestFilePath } from './test-files.js';
|
||||
// Cache the (slightly post-processed) results of linker.fullLink.
|
||||
const CACHE_SIZE = process.env.METEOR_LINKER_CACHE_SIZE || 1024*1024*100;
|
||||
const CACHE_DEBUG = !! process.env.METEOR_TEST_PRINT_LINKER_CACHE_DEBUG;
|
||||
const LINKER_CACHE_SALT = 13; // Increment this number to force relinking.
|
||||
const LINKER_CACHE_SALT = 17; // Increment this number to force relinking.
|
||||
const LINKER_CACHE = new LRU({
|
||||
max: CACHE_SIZE,
|
||||
// Cache is measured in bytes. We don't care about servePath.
|
||||
@@ -1292,12 +1291,12 @@ export class PackageSourceBatch {
|
||||
noLineNumbers: !isWeb
|
||||
};
|
||||
|
||||
const cacheKey = sha1(JSON.stringify({
|
||||
LINKER_CACHE_SALT,
|
||||
const fileHashes = [];
|
||||
const cacheKeyPrefix = sha1(JSON.stringify({
|
||||
linkerOptions,
|
||||
files: jsResources.map((inputFile) => {
|
||||
fileHashes.push(inputFile.hash);
|
||||
return {
|
||||
hash: inputFile.hash,
|
||||
installPath: inputFile.installPath,
|
||||
sourceMap: !! inputFile.sourceMap,
|
||||
mainModule: inputFile.mainModule,
|
||||
@@ -1307,20 +1306,25 @@ export class PackageSourceBatch {
|
||||
};
|
||||
})
|
||||
}));
|
||||
const cacheKeySuffix = sha1(JSON.stringify({
|
||||
LINKER_CACHE_SALT,
|
||||
fileHashes
|
||||
}));
|
||||
const cacheKey = `${cacheKeyPrefix}_${cacheKeySuffix}`;
|
||||
|
||||
{
|
||||
const inMemoryCached = LINKER_CACHE.get(cacheKey);
|
||||
if (inMemoryCached) {
|
||||
if (CACHE_DEBUG) {
|
||||
console.log('LINKER IN-MEMORY CACHE HIT:',
|
||||
linkerOptions.name, bundleArch);
|
||||
}
|
||||
return inMemoryCached;
|
||||
if (LINKER_CACHE.has(cacheKey)) {
|
||||
if (CACHE_DEBUG) {
|
||||
console.log('LINKER IN-MEMORY CACHE HIT:',
|
||||
linkerOptions.name, bundleArch);
|
||||
}
|
||||
return LINKER_CACHE.get(cacheKey);
|
||||
}
|
||||
|
||||
const cacheFilename = self.linkerCacheDir && files.pathJoin(
|
||||
self.linkerCacheDir, cacheKey + '.cache');
|
||||
const cacheFilename = self.linkerCacheDir &&
|
||||
files.pathJoin(self.linkerCacheDir, cacheKey + '.cache');
|
||||
|
||||
const wildcardCacheFilename = cacheFilename &&
|
||||
files.pathJoin(self.linkerCacheDir, cacheKeyPrefix + "_*.cache");
|
||||
|
||||
// The return value from _linkJS includes Buffers, but we want everything to
|
||||
// be JSON for writing to the disk cache. This function converts the string
|
||||
@@ -1395,7 +1399,13 @@ export class PackageSourceBatch {
|
||||
LINKER_CACHE.set(cacheKey, ret);
|
||||
if (cacheFilename) {
|
||||
// Write asynchronously.
|
||||
Fiber(() => files.writeFileAtomically(cacheFilename, retAsJSON)).run();
|
||||
Promise.resolve().then(() => {
|
||||
try {
|
||||
files.rm_recursive(wildcardCacheFilename);
|
||||
} finally {
|
||||
files.writeFileAtomically(cacheFilename, retAsJSON);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ var compiler = exports;
|
||||
// dependencies. (At least for now, packages only used in target creation (eg
|
||||
// minifiers) don't require you to update BUILT_BY, though you will need to quit
|
||||
// and rerun "meteor run".)
|
||||
compiler.BUILT_BY = 'meteor/26';
|
||||
compiler.BUILT_BY = 'meteor/29';
|
||||
|
||||
// This is a list of all possible architectures that a build can target. (Client
|
||||
// is expanded into 'web.browser' and 'web.cordova')
|
||||
@@ -1021,5 +1021,9 @@ export const KNOWN_ISOBUILD_FEATURE_PACKAGES = {
|
||||
// One scenario is a package depending on a Cordova plugin or version
|
||||
// that is only available on npm, which means downloading the plugin is not
|
||||
// supported on versions of Cordova below 5.0.0.
|
||||
'isobuild:cordova': ['5.4.0']
|
||||
'isobuild:cordova': ['5.4.0'],
|
||||
|
||||
// This package requires functionality introduced in meteor-tool@1.5.0
|
||||
// to enable dynamic module fetching via import(...).
|
||||
'isobuild:dynamic-import': ['1.5.0'],
|
||||
};
|
||||
|
||||
@@ -52,8 +52,10 @@ const defaultExtensionHandlers = {
|
||||
},
|
||||
|
||||
".json"(dataString) {
|
||||
const file = this;
|
||||
file.jsonData = JSON.parse(dataString);
|
||||
return "module.exports = " +
|
||||
JSON.stringify(JSON.parse(dataString), null, 2) +
|
||||
JSON.stringify(file.jsonData, null, 2) +
|
||||
";\n";
|
||||
},
|
||||
|
||||
@@ -191,8 +193,11 @@ export default class ImportScanner {
|
||||
|
||||
const dotExt = "." + file.type;
|
||||
const dataString = file.data.toString("utf8");
|
||||
file.dataString = defaultExtensionHandlers[dotExt](
|
||||
dataString, file.hash);
|
||||
file.dataString = defaultExtensionHandlers[dotExt].call(
|
||||
file,
|
||||
dataString,
|
||||
file.hash,
|
||||
);
|
||||
|
||||
if (! (file.data instanceof Buffer) ||
|
||||
file.dataString !== dataString) {
|
||||
@@ -255,17 +260,10 @@ export default class ImportScanner {
|
||||
file.installPath = this._getInstallPath(absTargetPath);
|
||||
file.sourcePath = file.targetPath;
|
||||
|
||||
let relativeId = convertToPosixPath(pathRelative(
|
||||
pathDirname(absSourcePath),
|
||||
absTargetPath
|
||||
));
|
||||
|
||||
// If the result of pathRelative does not already start with a "."
|
||||
// or a "/", prepend a "./" to make it a valid relative identifier
|
||||
// according to CommonJS syntax.
|
||||
if ("./".indexOf(relativeId.charAt(0)) < 0) {
|
||||
relativeId = "./" + relativeId;
|
||||
}
|
||||
const relativeId = this._getRelativeImportId(
|
||||
absSourcePath,
|
||||
absTargetPath,
|
||||
);
|
||||
|
||||
// Set the contents of the source module to import the target
|
||||
// module(s). Note that module.exports will be set to the exports of
|
||||
@@ -336,7 +334,17 @@ export default class ImportScanner {
|
||||
oldFile.dataString = combinedDataString;
|
||||
oldFile.data = new Buffer(oldFile.dataString, "utf8");
|
||||
oldFile.hash = sha1(oldFile.data);
|
||||
oldFile.imported = oldFile.imported || newFile.imported;
|
||||
|
||||
// If either oldFile or newFile has been imported non-dynamically,
|
||||
// then oldFile.imported needs to be === true. Otherwise we simply set
|
||||
// oldFile.imported = oldFile.imported || newFile.imported, which
|
||||
// could be either false, "dynamic", or "fake" (see addNodeModules).
|
||||
oldFile.imported =
|
||||
oldFile.imported === true ||
|
||||
newFile.imported === true ||
|
||||
oldFile.imported ||
|
||||
newFile.imported;
|
||||
|
||||
oldFile.sourceMap = combinedSourceMap.toJSON();
|
||||
if (! oldFile.sourceMap.mappings) {
|
||||
oldFile.sourceMap = null;
|
||||
@@ -346,7 +354,7 @@ export default class ImportScanner {
|
||||
scanImports() {
|
||||
this.outputFiles.forEach(file => {
|
||||
if (! file.lazy || file.imported) {
|
||||
this._scanFile(file);
|
||||
this._scanFile(file, file.imported === "dynamic");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -368,6 +376,11 @@ export default class ImportScanner {
|
||||
try {
|
||||
this._scanFile({
|
||||
sourcePath: "fake.js",
|
||||
// It's important that the fake.js file itself never gets
|
||||
// scanned or bundled. See the _scanFile and getOutputFiles
|
||||
// methods for logic that deals with file.imported values.
|
||||
imported: "fake",
|
||||
lazy: true,
|
||||
// By specifying the .deps property of this fake file ahead of
|
||||
// time, we can avoid calling findImportedModuleIdentifiers in the
|
||||
// _scanFile method.
|
||||
@@ -403,11 +416,14 @@ export default class ImportScanner {
|
||||
};
|
||||
}
|
||||
|
||||
getOutputFiles(options) {
|
||||
getOutputFiles() {
|
||||
// Return all installable output files that are either eager or
|
||||
// imported by another module.
|
||||
// imported (statically or dynamically).
|
||||
return this.outputFiles.filter(file => {
|
||||
return file.installPath && (! file.lazy || file.imported);
|
||||
return file.installPath &&
|
||||
(! file.lazy ||
|
||||
file.imported === true ||
|
||||
file.imported === "dynamic");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -467,23 +483,61 @@ export default class ImportScanner {
|
||||
return result;
|
||||
}
|
||||
|
||||
_resolve(id, absPath) {
|
||||
_resolve(parentFile, id, forDynamicImport = false) {
|
||||
const absPath = pathJoin(this.sourceRoot, parentFile.sourcePath);
|
||||
const resolved = this.resolver.resolve(id, absPath);
|
||||
|
||||
if (resolved === "missing") {
|
||||
return this._onMissing(id, absPath);
|
||||
return this._onMissing(parentFile, id, forDynamicImport);
|
||||
}
|
||||
|
||||
if (resolved && resolved.packageJsonMap) {
|
||||
const info = parentFile.deps[id];
|
||||
info.helpers = info.helpers || {};
|
||||
|
||||
each(resolved.packageJsonMap, (pkg, path) => {
|
||||
this._addPkgJsonToOutput(path, pkg);
|
||||
const packageJsonFile =
|
||||
this._addPkgJsonToOutput(path, pkg, forDynamicImport);
|
||||
|
||||
if (! parentFile.installPath) {
|
||||
// If parentFile is not installable, then we won't return it
|
||||
// from getOutputFiles, so we don't need to worry about
|
||||
// recording any parentFile.deps[id].helpers.
|
||||
return;
|
||||
}
|
||||
|
||||
const relativeId = this._getRelativeImportId(
|
||||
parentFile.installPath,
|
||||
packageJsonFile.installPath
|
||||
);
|
||||
|
||||
// Although not explicitly imported, any package.json modules
|
||||
// involved in resolving this import should be recorded as
|
||||
// implicit "helpers."
|
||||
info.helpers[relativeId] = forDynamicImport;
|
||||
});
|
||||
}
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
_scanFile(file) {
|
||||
_getRelativeImportId(parentPath, childPath) {
|
||||
const relativeId = convertToPosixPath(pathRelative(
|
||||
pathDirname(parentPath),
|
||||
childPath
|
||||
), true);
|
||||
|
||||
// If the result of pathRelative does not already start with a "." or
|
||||
// a "/", prepend a "./" to make it a valid relative identifier
|
||||
// according to CommonJS syntax.
|
||||
if ("./".indexOf(relativeId.charAt(0)) < 0) {
|
||||
return "./" + relativeId;
|
||||
}
|
||||
|
||||
return relativeId;
|
||||
}
|
||||
|
||||
_scanFile(file, forDynamicImport = false) {
|
||||
const absPath = pathJoin(this.sourceRoot, file.sourcePath);
|
||||
|
||||
try {
|
||||
@@ -501,7 +555,13 @@ export default class ImportScanner {
|
||||
}
|
||||
|
||||
each(file.deps, (info, id) => {
|
||||
const resolved = this._resolve(id, absPath);
|
||||
// Asynchronous module fetching only really makes sense in the
|
||||
// browser (even though it works equally well on the server), so
|
||||
// it's better if forDynamicImport never becomes true on the server.
|
||||
const dynamic = this.isWebBrowser() &&
|
||||
(forDynamicImport || info.dynamic);
|
||||
|
||||
const resolved = this._resolve(file, id, dynamic);
|
||||
if (! resolved) {
|
||||
return;
|
||||
}
|
||||
@@ -526,16 +586,30 @@ export default class ImportScanner {
|
||||
// as imported so we know to include them in the bundle if they
|
||||
// are lazy. Eager files and files that we have imported before do
|
||||
// not need to be scanned again. Lazy files that we have not
|
||||
// imported before still need to be scanned, however.
|
||||
// imported before still need to be scanned, however. Note that
|
||||
// alreadyScanned will be "dynamic" (which is truthy) if the file
|
||||
// has only been scanned because of a dynamic import(...).
|
||||
const alreadyScanned = ! depFile.lazy || depFile.imported;
|
||||
|
||||
// Whether the file is eager or lazy, mark it as imported. For
|
||||
// lazy files, this makes the difference between being included in
|
||||
// or omitted from the bundle. For eager files, this just ensures
|
||||
// we won't scan them again.
|
||||
depFile.imported = true;
|
||||
// we won't scan them again. If this scan began from a dynamic
|
||||
// import(...), we set depFile.imported = "dynamic" unless it's
|
||||
// already been set true.
|
||||
depFile.imported = dynamic
|
||||
? depFile.imported || "dynamic"
|
||||
: true;
|
||||
|
||||
if (! alreadyScanned) {
|
||||
const needsToBeScanned = ! alreadyScanned ||
|
||||
// If the file has already been scanned, but only because of a
|
||||
// dynamic import(...), then it needs to be scanned again, so that
|
||||
// we mark it and its dependencies as non-dynamic. This will be
|
||||
// cheaper than before because we've already computed depFile.deps.
|
||||
(alreadyScanned === "dynamic" &&
|
||||
depFile.imported === true);
|
||||
|
||||
if (needsToBeScanned) {
|
||||
if (depFile.error) {
|
||||
// Since this file is lazy, it might never have been imported,
|
||||
// so any errors reported to InputFile#error were saved but
|
||||
@@ -544,7 +618,7 @@ export default class ImportScanner {
|
||||
buildmessage.error(depFile.error.message,
|
||||
depFile.error.info);
|
||||
} else {
|
||||
this._scanFile(depFile);
|
||||
this._scanFile(depFile, dynamic);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,6 +631,8 @@ export default class ImportScanner {
|
||||
return;
|
||||
}
|
||||
|
||||
info.installPath = installPath;
|
||||
|
||||
// If the module is not readable, _readModule may return
|
||||
// null. Otherwise it will return an object with .data, .dataString,
|
||||
// and .hash properties.
|
||||
@@ -570,7 +646,7 @@ export default class ImportScanner {
|
||||
depFile.installPath = installPath;
|
||||
depFile.servePath = installPath;
|
||||
depFile.lazy = true;
|
||||
depFile.imported = true;
|
||||
depFile.imported = dynamic ? "dynamic" : true;
|
||||
|
||||
// Append this file to the output array and record its index.
|
||||
this._addFile(absImportedPath, depFile);
|
||||
@@ -591,12 +667,17 @@ export default class ImportScanner {
|
||||
return;
|
||||
}
|
||||
|
||||
this._scanFile(depFile);
|
||||
this._scanFile(depFile, dynamic);
|
||||
});
|
||||
}
|
||||
|
||||
isWeb() {
|
||||
return archMatches(this.bundleArch, "web");
|
||||
// Returns true for web.cordova as well as web.browser.
|
||||
return ! archMatches(this.bundleArch, "os");
|
||||
}
|
||||
|
||||
isWebBrowser() {
|
||||
return archMatches(this.bundleArch, "web.browser");
|
||||
}
|
||||
|
||||
_readFile(absPath) {
|
||||
@@ -653,7 +734,8 @@ export default class ImportScanner {
|
||||
}
|
||||
}
|
||||
|
||||
info.dataString = defaultExtensionHandlers[ext](
|
||||
info.dataString = defaultExtensionHandlers[ext].call(
|
||||
info,
|
||||
info.dataString,
|
||||
info.hash,
|
||||
);
|
||||
@@ -775,9 +857,12 @@ export default class ImportScanner {
|
||||
}
|
||||
|
||||
// Called by this.resolver when a module identifier cannot be resolved.
|
||||
_onMissing(id, absParentPath) {
|
||||
_onMissing(parentFile, id, forDynamicImport = false) {
|
||||
const isApp = ! this.name;
|
||||
const parentFile = this._getFile(absParentPath);
|
||||
const absParentPath = pathJoin(
|
||||
this.sourceRoot,
|
||||
parentFile.sourcePath,
|
||||
);
|
||||
|
||||
if (isApp &&
|
||||
Resolver.isNative(id) &&
|
||||
@@ -786,27 +871,33 @@ export default class ImportScanner {
|
||||
// a dependency on meteor-node-stubs/deps/<id>.js.
|
||||
const stubId = Resolver.getNativeStubId(id);
|
||||
if (isString(stubId) && stubId !== id) {
|
||||
if (parentFile &&
|
||||
parentFile.deps) {
|
||||
parentFile.deps[stubId] = parentFile.deps[id];
|
||||
}
|
||||
return this._resolve(stubId, absParentPath);
|
||||
const info = parentFile.deps[id];
|
||||
|
||||
// Although not explicitly imported, any stubs associated with
|
||||
// this native import should be recorded as implicit "helpers."
|
||||
info.helpers = info.helpers || {};
|
||||
info.helpers[stubId] = forDynamicImport;
|
||||
|
||||
return this._resolve(parentFile, stubId, forDynamicImport);
|
||||
}
|
||||
}
|
||||
|
||||
const possiblySpurious =
|
||||
parentFile &&
|
||||
parentFile.deps &&
|
||||
has(parentFile.deps, id) &&
|
||||
parentFile.deps[id].possiblySpurious;
|
||||
|
||||
const info = {
|
||||
packageName: this.name,
|
||||
parentPath: absParentPath,
|
||||
bundleArch: this.bundleArch,
|
||||
possiblySpurious,
|
||||
possiblySpurious: false,
|
||||
dynamic: false,
|
||||
};
|
||||
|
||||
if (parentFile &&
|
||||
parentFile.deps &&
|
||||
has(parentFile.deps, id)) {
|
||||
const importInfo = parentFile.deps[id];
|
||||
info.possiblySpurious = importInfo.possiblySpurious;
|
||||
info.dynamic = importInfo.dynamic;
|
||||
}
|
||||
|
||||
// If the imported identifier is neither absolute nor relative, but
|
||||
// top-level, then it might be satisfied by a package installed in
|
||||
// the top-level node_modules directory, and we should record the
|
||||
@@ -827,15 +918,25 @@ export default class ImportScanner {
|
||||
}
|
||||
}
|
||||
|
||||
_addPkgJsonToOutput(pkgJsonPath, pkg) {
|
||||
_addPkgJsonToOutput(pkgJsonPath, pkg, forDynamicImport = false) {
|
||||
const file = this._getFile(pkgJsonPath);
|
||||
|
||||
if (file) {
|
||||
// If the file already exists, don't modify or replace it.
|
||||
return;
|
||||
// If the file already exists, just update file.imported according
|
||||
// to the forDynamicImport parameter.
|
||||
file.imported = forDynamicImport
|
||||
? file.imported || "dynamic"
|
||||
: true;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
const data = new Buffer(map(pkg, (value, key) => {
|
||||
return `exports.${key} = ${JSON.stringify(value)};\n`;
|
||||
const isIdentifier = /^[_$a-zA-Z]\w*$/.test(key);
|
||||
const prop = isIdentifier
|
||||
? "." + key
|
||||
: "[" + JSON.stringify(key) + "]";
|
||||
return `exports${prop} = ${JSON.stringify(value)};\n`;
|
||||
}).join(""));
|
||||
|
||||
const relPkgJsonPath = pathRelative(this.sourceRoot, pkgJsonPath);
|
||||
@@ -843,13 +944,14 @@ export default class ImportScanner {
|
||||
const pkgFile = {
|
||||
type: "js", // We represent the JSON module with JS.
|
||||
data,
|
||||
jsonData: pkg,
|
||||
deps: {}, // Avoid accidentally re-scanning this file.
|
||||
sourcePath: relPkgJsonPath,
|
||||
installPath: this._getInstallPath(pkgJsonPath),
|
||||
servePath: relPkgJsonPath,
|
||||
hash: sha1(data),
|
||||
lazy: true,
|
||||
imported: true,
|
||||
imported: forDynamicImport ? "dynamic" : true,
|
||||
// Since _addPkgJsonToOutput is only ever called for package.json
|
||||
// files that are involved in resolving package directories, and pkg
|
||||
// is only a subset of the information in the actual package.json
|
||||
@@ -865,6 +967,8 @@ export default class ImportScanner {
|
||||
if (hash) {
|
||||
this.watchSet.addFile(pkgJsonPath, hash);
|
||||
}
|
||||
|
||||
return pkgFile;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,8 @@ function tryToParse(source, hash) {
|
||||
return ast;
|
||||
}
|
||||
|
||||
var dependencyKeywordPattern = /\b(?:require|import|importSync|export)\b/g;
|
||||
var dependencyKeywordPattern =
|
||||
/\b(?:require|import|importSync|dynamicImport|export)\b/g;
|
||||
|
||||
/**
|
||||
* The `findImportedModuleIdentifiers` function takes a string of module
|
||||
@@ -95,9 +96,14 @@ export function findImportedModuleIdentifiers(source, hash) {
|
||||
return addIdentifier(id, "require", requireIsBound);
|
||||
}
|
||||
|
||||
id = getImportedModuleId(node);
|
||||
if (typeof id === "string") {
|
||||
return addIdentifier(id, "import", requireIsBound);
|
||||
const importInfo = getImportedModuleInfo(node);
|
||||
if (importInfo) {
|
||||
return addIdentifier(
|
||||
importInfo.id,
|
||||
"import",
|
||||
requireIsBound,
|
||||
importInfo.dynamic
|
||||
);
|
||||
}
|
||||
|
||||
// Continue traversing the children of this node.
|
||||
@@ -117,10 +123,17 @@ export function findImportedModuleIdentifiers(source, hash) {
|
||||
}
|
||||
}
|
||||
|
||||
function addIdentifier(id, type, requireIsBound) {
|
||||
function addIdentifier(id, type, requireIsBound, isDynamic) {
|
||||
const entry = hasOwn.call(identifiers, id)
|
||||
? identifiers[id]
|
||||
: identifiers[id] = { possiblySpurious: true };
|
||||
: identifiers[id] = {
|
||||
possiblySpurious: true,
|
||||
dynamic: !! isDynamic
|
||||
};
|
||||
|
||||
if (! isDynamic) {
|
||||
entry.dynamic = false;
|
||||
}
|
||||
|
||||
if (type === "require") {
|
||||
// If the identifier comes from a require call, but require is not a
|
||||
@@ -182,6 +195,61 @@ function isStringLiteral(node) {
|
||||
typeof node.value === "string"));
|
||||
}
|
||||
|
||||
function getImportedModuleInfo(node) {
|
||||
switch (node.type) {
|
||||
case "CallExpression":
|
||||
if (node.callee.type === "Import" ||
|
||||
isIdWithName(node.callee, "import")) {
|
||||
const firstArg = node.arguments[0];
|
||||
if (isStringLiteral(firstArg)) {
|
||||
return {
|
||||
id: firstArg.value,
|
||||
dynamic: true,
|
||||
};
|
||||
}
|
||||
|
||||
} else if (node.callee.type === "MemberExpression" &&
|
||||
isIdWithName(node.callee.object, "module")) {
|
||||
const propertyName =
|
||||
isPropertyWithName(node.callee.property, "import") ||
|
||||
isPropertyWithName(node.callee.property, "importSync") ||
|
||||
isPropertyWithName(node.callee.property, "dynamicImport");
|
||||
|
||||
if (propertyName) {
|
||||
const dynamic = propertyName === "dynamicImport";
|
||||
const args = node.arguments;
|
||||
const argc = args.length;
|
||||
|
||||
if (argc > 0) {
|
||||
const arg = args[0];
|
||||
if (isStringLiteral(arg)) {
|
||||
return {
|
||||
id: arg.value,
|
||||
dynamic,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
case "ImportDeclaration":
|
||||
case "ExportAllDeclaration":
|
||||
case "ExportNamedDeclaration":
|
||||
// The .source of an ImportDeclaration or Export{Named,All}Declaration
|
||||
// is always a string-valued Literal node, if not null.
|
||||
if (isNode(node.source)) {
|
||||
return {
|
||||
id: node.source.value,
|
||||
dynamic: false,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function isPropertyWithName(node, name) {
|
||||
if (isIdWithName(node, name) ||
|
||||
(isStringLiteral(node) &&
|
||||
@@ -190,33 +258,6 @@ function isPropertyWithName(node, name) {
|
||||
}
|
||||
}
|
||||
|
||||
function getImportedModuleId(node) {
|
||||
if (node.type === "CallExpression" &&
|
||||
node.callee.type === "MemberExpression" &&
|
||||
isIdWithName(node.callee.object, "module") &&
|
||||
(isPropertyWithName(node.callee.property, "import") ||
|
||||
isPropertyWithName(node.callee.property, "importSync"))) {
|
||||
const args = node.arguments;
|
||||
const argc = args.length;
|
||||
if (argc > 0) {
|
||||
const arg = args[0];
|
||||
if (isStringLiteral(arg)) {
|
||||
return arg.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node.type === "ImportDeclaration" ||
|
||||
node.type === "ExportAllDeclaration" ||
|
||||
node.type === "ExportNamedDeclaration") {
|
||||
// The .source of an ImportDeclaration or Export{Named,All}Declaration
|
||||
// is always a string-valued Literal node, if not null.
|
||||
if (isNode(node.source)) {
|
||||
return node.source.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Analyze the JavaScript source code `source` and return a dictionary of all
|
||||
// globals which are assigned to in the package. The values in the dictionary
|
||||
// are all `true`.
|
||||
|
||||
@@ -162,13 +162,15 @@ _.extend(Module.prototype, {
|
||||
servePath: self.combinedServePath,
|
||||
};
|
||||
|
||||
const results = [result];
|
||||
|
||||
// An array of strings and SourceNode objects.
|
||||
let chunks = [];
|
||||
let fileCount = 0;
|
||||
|
||||
// Emit each file
|
||||
if (self.meteorInstallOptions) {
|
||||
const tree = self._buildModuleTree();
|
||||
const tree = self._buildModuleTree(results, sourceWidth);
|
||||
fileCount = self._chunkifyModuleTree(tree, chunks, sourceWidth);
|
||||
result.exportsName =
|
||||
self._chunkifyEagerRequires(chunks, fileCount, sourceWidth);
|
||||
@@ -216,19 +218,20 @@ _.extend(Module.prototype, {
|
||||
}
|
||||
);
|
||||
|
||||
return [result];
|
||||
return results;
|
||||
}),
|
||||
|
||||
// Builds a tree of nested objects where the properties are names of
|
||||
// files or directories, and the values are either nested objects
|
||||
// (representing directories) or File objects (representing modules).
|
||||
// Bare files and lazy files that are never imported are ignored.
|
||||
_buildModuleTree() {
|
||||
_buildModuleTree(results, sourceWidth) {
|
||||
assert.ok(this.meteorInstallOptions);
|
||||
|
||||
// Tree of File objects for all non-dynamic modules.
|
||||
const tree = {};
|
||||
|
||||
_.each(this.files, function (file) {
|
||||
_.each(this.files, file => {
|
||||
if (file.bare) {
|
||||
// Bare files will be added in between the synchronous require
|
||||
// calls in _chunkifyEagerRequires.
|
||||
@@ -242,22 +245,57 @@ _.extend(Module.prototype, {
|
||||
return;
|
||||
}
|
||||
|
||||
const parts = file.installPath.split("/");
|
||||
let t = tree;
|
||||
_.each(parts, function (part, i) {
|
||||
const isLastPart = i === parts.length - 1;
|
||||
t = _.has(t, part)
|
||||
? t[part]
|
||||
: t[part] = isLastPart ? file : {};
|
||||
});
|
||||
if (file.isDynamic()) {
|
||||
const servePath = "dynamic/" + file.installPath;
|
||||
const { code: source, map } =
|
||||
file.getPrelinkedOutput({
|
||||
sourceWidth: sourceWidth,
|
||||
noLineNumbers: this.noLineNumbers
|
||||
}).toStringWithSourceMap({
|
||||
file: servePath,
|
||||
});
|
||||
|
||||
results.push({
|
||||
source,
|
||||
servePath,
|
||||
sourceMap: map && map.toJSON(),
|
||||
dynamic: true,
|
||||
});
|
||||
|
||||
const stubArray = file.deps.slice(0);
|
||||
|
||||
if (file.installPath.endsWith("/package.json") &&
|
||||
file.jsonData) {
|
||||
const stub = {};
|
||||
|
||||
function tryMain(name) {
|
||||
const value = file.jsonData[name];
|
||||
if (_.isString(value)) {
|
||||
stub[name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
tryMain("browser");
|
||||
tryMain("main");
|
||||
|
||||
stubArray.push(stub);
|
||||
}
|
||||
|
||||
addToTree(stubArray, file.installPath, tree);
|
||||
|
||||
} else {
|
||||
// If the file is not dynamic, then it should be included in the
|
||||
// initial bundle, so we add it to the static tree.
|
||||
addToTree(file, file.installPath, tree);
|
||||
}
|
||||
});
|
||||
|
||||
return tree;
|
||||
},
|
||||
|
||||
// Takes the tree generated by _buildModuleTree and populates the chunks
|
||||
// Take the tree generated in getPrelinkedFiles and populate the chunks
|
||||
// array with strings and SourceNode objects that can be combined into a
|
||||
// single SourceNode object. Returns the count of modules in the tree.
|
||||
// single SourceNode object. Return the count of modules in the tree.
|
||||
_chunkifyModuleTree(tree, chunks, sourceWidth) {
|
||||
const self = this;
|
||||
|
||||
@@ -268,12 +306,18 @@ _.extend(Module.prototype, {
|
||||
let moduleCount = 0;
|
||||
|
||||
function walk(t) {
|
||||
if (t instanceof File) {
|
||||
if (Array.isArray(t)) {
|
||||
++moduleCount;
|
||||
chunks.push(JSON.stringify(t, null, 2));
|
||||
|
||||
} else if (t instanceof File) {
|
||||
++moduleCount;
|
||||
|
||||
chunks.push(t.getPrelinkedOutput({
|
||||
sourceWidth,
|
||||
noLineNumbers: self.noLineNumbers
|
||||
}));
|
||||
|
||||
} else if (_.isObject(t)) {
|
||||
chunks.push("{");
|
||||
const keys = _.keys(t);
|
||||
@@ -294,7 +338,7 @@ _.extend(Module.prototype, {
|
||||
// allows us to call meteorInstall just once to install everything.
|
||||
chunks.push("var require = meteorInstall(");
|
||||
walk(tree);
|
||||
chunks.push(",", JSON.stringify(self.meteorInstallOptions), ");");
|
||||
chunks.push(",", self._stringifyInstallOptions(), ");");
|
||||
|
||||
if (moduleCount === 0) {
|
||||
// If no files were actually added to the chunks array, roll back
|
||||
@@ -305,6 +349,40 @@ _.extend(Module.prototype, {
|
||||
return moduleCount;
|
||||
},
|
||||
|
||||
_stringifyInstallOptions() {
|
||||
let optionsString =
|
||||
JSON.stringify(this.meteorInstallOptions, null, 2);
|
||||
|
||||
if (this.useGlobalNamespace) {
|
||||
return optionsString;
|
||||
}
|
||||
|
||||
if (! this.files.some(file => file.isDynamic())) {
|
||||
// If the package contains no files that can be imported
|
||||
// dynamically, then we don't need to provide an options.eval
|
||||
// function for evaluating dynamic modules.
|
||||
return optionsString;
|
||||
}
|
||||
|
||||
assert.ok(optionsString.endsWith("\n}"));
|
||||
|
||||
// If this package is not using the global namespace, pass an
|
||||
// options.eval method to meteorInstall, so that code added later can
|
||||
// have access to the same shared package variables as other code in
|
||||
// the package.
|
||||
return optionsString.slice(0, optionsString.length - 2) + [
|
||||
",",
|
||||
" eval: function () {",
|
||||
" return eval(arguments[0]);",
|
||||
" }",
|
||||
"}"
|
||||
].join("\n");
|
||||
},
|
||||
|
||||
_hasDynamicModules() {
|
||||
return this.files.some(file => file.isDynamic());
|
||||
},
|
||||
|
||||
// Adds require calls to the chunks array for all modules that should be
|
||||
// eagerly evaluated, and also includes bare files in the appropriate
|
||||
// order with respect to the require calls. Returns the name of the
|
||||
@@ -344,6 +422,19 @@ _.extend(Module.prototype, {
|
||||
}
|
||||
});
|
||||
|
||||
// Insert the given value into the tree by splitting the path and
|
||||
// creating/following nested objects properties named by each component of
|
||||
// the split path.
|
||||
export function addToTree(value, path, tree) {
|
||||
const parts = path.split("/");
|
||||
const lastIndex = parts.length - 1;
|
||||
parts.forEach((part, i) => {
|
||||
tree = _.has(tree, part)
|
||||
? tree[part]
|
||||
: tree[part] = i < lastIndex ? {} : value;
|
||||
});
|
||||
}
|
||||
|
||||
// Given 'symbolMap' like {Foo: 's1', 'Bar.Baz': 's2', 'Bar.Quux.A': 's3', 'Bar.Quux.B': 's4'}
|
||||
// return something like
|
||||
// {Foo: 's1', Bar: {Baz: 's2', Quux: {A: 's3', B: 's4'}}}
|
||||
@@ -424,20 +515,16 @@ var File = function (inputFile, module) {
|
||||
self.servePath = inputFile.servePath;
|
||||
|
||||
// Module identifiers imported or required by this module, if any.
|
||||
if (Array.isArray(inputFile.deps)) {
|
||||
self.deps = inputFile.deps;
|
||||
} else if (inputFile.deps && typeof inputFile.deps === "object") {
|
||||
self.deps = Object.keys(inputFile.deps);
|
||||
} else {
|
||||
self.deps = [];
|
||||
}
|
||||
// Excludes dynamically imported dependencies, and may exclude
|
||||
// dependencies already included in the non-dynamic initial bundle.
|
||||
self.deps = getNonDynamicDeps(inputFile.deps);
|
||||
|
||||
// True if the input file should not be evaluated eagerly.
|
||||
self.lazy = inputFile.lazy; // could be `true`, `false` or `undefined` <sigh>
|
||||
|
||||
// True if the file is an eagerly evaluated entry point, or if some
|
||||
// other file imports or requires it.
|
||||
self.imported = !!inputFile.imported;
|
||||
// True if the file is eagerly imported, "dynamic" if the file is
|
||||
// dynamically imported.
|
||||
self.imported = inputFile.imported;
|
||||
|
||||
// Boolean indicating whether this file is the main entry point module
|
||||
// for its package.
|
||||
@@ -450,10 +537,28 @@ var File = function (inputFile, module) {
|
||||
// Is an Object, not a string.
|
||||
self.sourceMap = inputFile.sourceMap;
|
||||
|
||||
// If inputFile is a JSON file, its parsed data will be exposed via the
|
||||
// .jsonData property.
|
||||
self.jsonData = inputFile.jsonData || null;
|
||||
|
||||
// The Module containing this file.
|
||||
self.module = module;
|
||||
};
|
||||
|
||||
function getNonDynamicDeps(inputFileDeps) {
|
||||
const nonDynamicDeps = Object.create(null);
|
||||
|
||||
if (! _.isEmpty(inputFileDeps)) {
|
||||
_.each(inputFileDeps, (info, id) => {
|
||||
if (! info.dynamic) {
|
||||
nonDynamicDeps[id] = info;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return Object.keys(nonDynamicDeps);
|
||||
}
|
||||
|
||||
_.extend(File.prototype, {
|
||||
// Return the globals in this file as an array of symbol names. For
|
||||
// example: if the code references 'Foo.bar.baz' and 'Quux', and
|
||||
@@ -511,21 +616,13 @@ _.extend(File.prototype, {
|
||||
return this.module.meteorInstallOptions;
|
||||
},
|
||||
|
||||
isDynamic() {
|
||||
return this.lazy && this.imported === "dynamic";
|
||||
},
|
||||
|
||||
_getClosureHeader() {
|
||||
if (this._useMeteorInstall()) {
|
||||
var header = "";
|
||||
|
||||
if (this.deps.length > 0) {
|
||||
header += "[";
|
||||
_.each(this.deps, dep => {
|
||||
header += JSON.stringify(dep) + ",";
|
||||
});
|
||||
}
|
||||
|
||||
const headerParts = [
|
||||
header,
|
||||
"function("
|
||||
];
|
||||
const headerParts = ["function("];
|
||||
|
||||
if (this.source.match(/\b__dirname\b/)) {
|
||||
headerParts.push("require,exports,module,__filename,__dirname");
|
||||
@@ -548,14 +645,9 @@ _.extend(File.prototype, {
|
||||
},
|
||||
|
||||
_getClosureFooter() {
|
||||
if (this._useMeteorInstall()) {
|
||||
var footer = "}";
|
||||
if (this.deps.length > 0) {
|
||||
footer += "]";
|
||||
}
|
||||
return footer;
|
||||
}
|
||||
return "}).call(this);\n";
|
||||
return this._useMeteorInstall()
|
||||
? "}"
|
||||
: "}).call(this);\n";
|
||||
},
|
||||
|
||||
// Options:
|
||||
@@ -1057,6 +1149,10 @@ export var fullLink = Profile("linker.fullLink", function (inputFiles, {
|
||||
var headerContent = (new Array(headerLines + 1).join(';'));
|
||||
|
||||
return _.map(prelinkedFiles, function (file) {
|
||||
if (file.dynamic) {
|
||||
return file;
|
||||
}
|
||||
|
||||
if (file.sourceMap) {
|
||||
var sourceMap = file.sourceMap;
|
||||
sourceMap.mappings = headerContent + sourceMap.mappings;
|
||||
|
||||
@@ -60,13 +60,9 @@ export class JsFile extends InputFile {
|
||||
// - sourceMap
|
||||
// - path
|
||||
// - hash?
|
||||
// - stats?
|
||||
addJavaScript(options) {
|
||||
const self = this;
|
||||
self._minifiedFiles.push({
|
||||
data: options.data,
|
||||
sourceMap: options.sourceMap,
|
||||
path: options.path
|
||||
});
|
||||
this._minifiedFiles.push({ ...options });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,12 +71,9 @@ export class CssFile extends InputFile {
|
||||
// - sourceMap
|
||||
// - path
|
||||
// - hash?
|
||||
// - stats?
|
||||
addStylesheet(options) {
|
||||
this._minifiedFiles.push({
|
||||
data: options.data,
|
||||
sourceMap: options.sourceMap,
|
||||
path: options.path
|
||||
});
|
||||
this._minifiedFiles.push({ ...options });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -297,17 +297,21 @@ export default class Resolver {
|
||||
pkgSubset.version = pkg.version;
|
||||
}
|
||||
|
||||
let main = pkg.main;
|
||||
if (has(pkg, "main")) {
|
||||
pkgSubset.main = pkg.main;
|
||||
let main;
|
||||
function tryMain(name) {
|
||||
const value = pkg[name];
|
||||
if (isString(value)) {
|
||||
main = main || value;
|
||||
pkgSubset[name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
if (archMatches(this.targetArch, "web") &&
|
||||
isString(pkg.browser)) {
|
||||
main = pkg.browser;
|
||||
pkgSubset.browser = pkg.browser;
|
||||
if (archMatches(this.targetArch, "web")) {
|
||||
tryMain("browser");
|
||||
}
|
||||
|
||||
tryMain("main");
|
||||
|
||||
if (isString(main)) {
|
||||
// The "main" field of package.json does not have to begin with ./
|
||||
// to be considered relative, so first we try simply appending it to
|
||||
|
||||
@@ -13,6 +13,8 @@ var Profile = require('./profile.js').Profile;
|
||||
// This code is duplicated in tools/main.js.
|
||||
var MIN_NODE_VERSION = 'v0.10.41';
|
||||
|
||||
var hasOwn = Object.prototype.hasOwnProperty;
|
||||
|
||||
if (require('semver').lt(process.version, MIN_NODE_VERSION)) {
|
||||
process.stderr.write(
|
||||
'Meteor requires Node ' + MIN_NODE_VERSION + ' or later.\n');
|
||||
@@ -124,6 +126,34 @@ var startCheckForLiveParent = function (parentPid) {
|
||||
}
|
||||
};
|
||||
|
||||
var specialArgPaths = {
|
||||
"packages/modules-runtime.js": function () {
|
||||
return {
|
||||
npmRequire: npmRequire,
|
||||
Profile: Profile
|
||||
};
|
||||
},
|
||||
|
||||
"packages/dynamic-import.js": function (file) {
|
||||
var dynamicImportInfo = {};
|
||||
|
||||
Object.keys(configJson.clientPaths).map(function (key) {
|
||||
var programJsonPath = path.resolve(configJson.clientPaths[key]);
|
||||
var programJson = require(programJsonPath);
|
||||
|
||||
dynamicImportInfo[key] = {
|
||||
dynamicRoot: path.join(path.dirname(programJsonPath), "dynamic")
|
||||
};
|
||||
});
|
||||
|
||||
dynamicImportInfo.server = {
|
||||
dynamicRoot: path.join(serverDir, "dynamic")
|
||||
};
|
||||
|
||||
return { dynamicImportInfo: dynamicImportInfo };
|
||||
}
|
||||
};
|
||||
|
||||
var loadServerBundles = Profile("Load server bundles", function () {
|
||||
_.each(serverJson.load, function (fileInfo) {
|
||||
var code = fs.readFileSync(path.resolve(serverDir, fileInfo.path));
|
||||
@@ -269,13 +299,17 @@ var loadServerBundles = Profile("Load server bundles", function () {
|
||||
},
|
||||
};
|
||||
|
||||
var isModulesRuntime =
|
||||
fileInfo.path === "packages/modules-runtime.js";
|
||||
|
||||
var wrapParts = ["(function(Npm,Assets"];
|
||||
if (isModulesRuntime) {
|
||||
wrapParts.push(",npmRequire,Profile");
|
||||
}
|
||||
|
||||
var specialArgs =
|
||||
hasOwn.call(specialArgPaths, fileInfo.path) &&
|
||||
specialArgPaths[fileInfo.path](fileInfo);
|
||||
|
||||
var specialKeys = Object.keys(specialArgs || {});
|
||||
specialKeys.forEach(function (key) {
|
||||
wrapParts.push("," + key);
|
||||
});
|
||||
|
||||
// \n is necessary in case final line is a //-comment
|
||||
wrapParts.push("){", code, "\n})");
|
||||
var wrapped = wrapParts.join("");
|
||||
@@ -296,9 +330,10 @@ var loadServerBundles = Profile("Load server bundles", function () {
|
||||
// what require() uses to generate its errors.
|
||||
var func = require('vm').runInThisContext(wrapped, scriptPath, true);
|
||||
var args = [Npm, Assets];
|
||||
if (isModulesRuntime) {
|
||||
args.push(npmRequire, Profile);
|
||||
}
|
||||
|
||||
specialKeys.forEach(function (key) {
|
||||
args.push(specialArgs[key]);
|
||||
});
|
||||
|
||||
Profile(fileInfo.path, func).apply(global, args);
|
||||
});
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
meteor-base # Packages every Meteor app needs to have
|
||||
mobile-experience # Packages for a great mobile UX
|
||||
mongo # The database Meteor supports right now
|
||||
blaze-html-templates # Compile .html files into Meteor Blaze views
|
||||
static-html # Define static page content in .html files
|
||||
reactive-var # Reactive variable for tracker
|
||||
tracker # Meteor's client-side reactive programming library
|
||||
|
||||
standard-minifier-css # CSS minifier run for production mode
|
||||
standard-minifier-js # JS minifier run for production mode
|
||||
es5-shim # ECMAScript 5 compatibility for older browsers.
|
||||
es5-shim # ECMAScript 5 compatibility for older browsers
|
||||
ecmascript # Enable ECMAScript2015+ syntax in app code
|
||||
shell-server # Server-side component of the `meteor shell` command
|
||||
|
||||
@@ -13,7 +13,7 @@ tracker # Meteor's client-side reactive programming library
|
||||
|
||||
standard-minifier-css # CSS minifier run for production mode
|
||||
standard-minifier-js # JS minifier run for production mode
|
||||
es5-shim # ECMAScript 5 compatibility for older browsers.
|
||||
es5-shim # ECMAScript 5 compatibility for older browsers
|
||||
ecmascript # Enable ECMAScript2015+ syntax in app code
|
||||
|
||||
kadira:flow-router # FlowRouter is a very simple router for Meteor
|
||||
|
||||
@@ -13,7 +13,7 @@ tracker # Meteor's client-side reactive programming library
|
||||
|
||||
standard-minifier-css # CSS minifier run for production mode
|
||||
standard-minifier-js # JS minifier run for production mode
|
||||
es5-shim # ECMAScript 5 compatibility for older browsers.
|
||||
es5-shim # ECMAScript 5 compatibility for older browsers
|
||||
ecmascript # Enable ECMAScript2015+ syntax in app code
|
||||
shell-server # Server-side component of the `meteor shell` command
|
||||
|
||||
|
||||
1
tools/tests/apps/dynamic-import/.gitignore
vendored
Normal file
1
tools/tests/apps/dynamic-import/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
node_modules
|
||||
15
tools/tests/apps/dynamic-import/.meteor/.finished-upgraders
Normal file
15
tools/tests/apps/dynamic-import/.meteor/.finished-upgraders
Normal file
@@ -0,0 +1,15 @@
|
||||
# This file contains information which helps Meteor properly upgrade your
|
||||
# app when you run 'meteor update'. You should check it into version control
|
||||
# with your project.
|
||||
|
||||
notices-for-0.9.0
|
||||
notices-for-0.9.1
|
||||
0.9.4-platform-file
|
||||
notices-for-facebook-graph-api-2
|
||||
1.2.0-standard-minifiers-package
|
||||
1.2.0-meteor-platform-split
|
||||
1.2.0-cordova-changes
|
||||
1.2.0-breaking-changes
|
||||
1.3.0-split-minifiers-package
|
||||
1.4.0-remove-old-dev-bundle-link
|
||||
1.4.1-add-shell-server-package
|
||||
1
tools/tests/apps/dynamic-import/.meteor/.gitignore
vendored
Normal file
1
tools/tests/apps/dynamic-import/.meteor/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
local
|
||||
7
tools/tests/apps/dynamic-import/.meteor/.id
Normal file
7
tools/tests/apps/dynamic-import/.meteor/.id
Normal file
@@ -0,0 +1,7 @@
|
||||
# This file contains a token that is unique to your project.
|
||||
# Check it into your repository along with the rest of this directory.
|
||||
# It can be used for purposes such as:
|
||||
# - ensuring you don't accidentally deploy one app on top of another
|
||||
# - providing package authors with aggregated statistics
|
||||
|
||||
1ue5kcr1q6a4v2o7ro4
|
||||
27
tools/tests/apps/dynamic-import/.meteor/packages
Normal file
27
tools/tests/apps/dynamic-import/.meteor/packages
Normal file
@@ -0,0 +1,27 @@
|
||||
# Meteor packages used by this project, one per line.
|
||||
# Check this file (and the other files in this directory) into your repository.
|
||||
#
|
||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||
# but you can also edit it by hand.
|
||||
|
||||
meteor-base # Packages every Meteor app needs to have
|
||||
mobile-experience # Packages for a great mobile UX
|
||||
mongo # The database Meteor supports right now
|
||||
blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views
|
||||
reactive-var # Reactive variable for tracker
|
||||
jquery # Helpful client-side library
|
||||
tracker # Meteor's client-side reactive programming library
|
||||
|
||||
standard-minifier-css # CSS minifier run for production mode
|
||||
standard-minifier-js # JS minifier run for production mode
|
||||
es5-shim # ECMAScript 5 compatibility for older browsers.
|
||||
ecmascript # Enable ECMAScript2015+ syntax in app code
|
||||
shell-server # Server-side component of the `meteor shell` command
|
||||
|
||||
autopublish # Publish all data to the clients (for prototyping)
|
||||
insecure # Allow all DB writes from clients (for prototyping)
|
||||
dynamic-import
|
||||
dispatch:mocha-phantomjs
|
||||
dispatch:mocha-browser
|
||||
lazy-test-package
|
||||
helper-package
|
||||
2
tools/tests/apps/dynamic-import/.meteor/platforms
Normal file
2
tools/tests/apps/dynamic-import/.meteor/platforms
Normal file
@@ -0,0 +1,2 @@
|
||||
server
|
||||
browser
|
||||
1
tools/tests/apps/dynamic-import/.meteor/release
Normal file
1
tools/tests/apps/dynamic-import/.meteor/release
Normal file
@@ -0,0 +1 @@
|
||||
none
|
||||
2
tools/tests/apps/dynamic-import/imports/date.js
Normal file
2
tools/tests/apps/dynamic-import/imports/date.js
Normal file
@@ -0,0 +1,2 @@
|
||||
import moment from "moment";
|
||||
export { moment };
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = { __esModule: true };
|
||||
6
tools/tests/apps/dynamic-import/imports/mutual-a.js
Normal file
6
tools/tests/apps/dynamic-import/imports/mutual-a.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import { strictEqual } from "assert";
|
||||
export const name = module.id;
|
||||
export const promise = import("./mutual-b").then(b => {
|
||||
strictEqual(b.name, "/imports/mutual-b.js");
|
||||
return b;
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user