1 | 'use strict';
|
2 |
|
3 | const MergeTrees = require('broccoli-merge-trees');
|
4 | const Funnel = require('broccoli-funnel');
|
5 | const path = require('path');
|
6 | const resolve = require('resolve');
|
7 | const concatBundle = require('./concat-bundle');
|
8 | const buildDebugMacroPlugin = require('./build-debug-macro-plugin');
|
9 | const buildStripClassCallcheckPlugin = require('./build-strip-class-callcheck-plugin');
|
10 | const injectBabelHelpers = require('./transforms/inject-babel-helpers').injectBabelHelpers;
|
11 | const debugTree = require('broccoli-debug').buildDebugCallback('ember-source:addon');
|
12 |
|
13 | const PRE_BUILT_TARGETS = [
|
14 | 'last 1 Chrome versions',
|
15 | 'last 1 Firefox versions',
|
16 | 'last 1 Safari versions',
|
17 | ];
|
18 |
|
19 | const paths = {};
|
20 | const absolutePaths = {};
|
21 |
|
22 | function add(paths, name, path) {
|
23 | Object.defineProperty(paths, name, {
|
24 | configurable: false,
|
25 | get: function() {
|
26 | return path;
|
27 | },
|
28 | });
|
29 | }
|
30 |
|
31 | add(paths, 'prod', 'vendor/ember/ember.js');
|
32 | add(paths, 'debug', 'vendor/ember/ember.js');
|
33 | add(paths, 'testing', 'vendor/ember/ember-testing.js');
|
34 | add(paths, 'jquery', 'vendor/ember/jquery/jquery.js');
|
35 |
|
36 | add(
|
37 | absolutePaths,
|
38 | 'templateCompiler',
|
39 | path.join(__dirname, '..', 'dist', 'ember-template-compiler.js')
|
40 | );
|
41 |
|
42 | module.exports = {
|
43 | init() {
|
44 | this._super.init && this._super.init.apply(this, arguments);
|
45 |
|
46 | if ('ember' in this.project.bowerDependencies()) {
|
47 |
|
48 | this.ui.writeWarnLine(
|
49 | 'Ember.js is now provided by node_module `ember-source`, please remove it from bower'
|
50 | );
|
51 | }
|
52 |
|
53 |
|
54 |
|
55 |
|
56 | this.root = path.join(__dirname, '..');
|
57 |
|
58 |
|
59 |
|
60 | this.treePaths.vendor = 'dist';
|
61 | },
|
62 |
|
63 | name: 'ember-source',
|
64 | paths,
|
65 | absolutePaths,
|
66 |
|
67 | included() {
|
68 | this._super.included.apply(this, arguments);
|
69 |
|
70 | const { has } = require('@ember/edition-utils');
|
71 |
|
72 | if (has('octane')) {
|
73 | let optionalFeatures = this.project.addons.find(a => a.name === '@ember/optional-features');
|
74 | let optionalFeaturesMissing = optionalFeatures === undefined;
|
75 | let message = [];
|
76 |
|
77 | if (optionalFeaturesMissing) {
|
78 | message.push(
|
79 | `* the @ember/optional-features addon is missing, run \`ember install @ember/optional-features\` to install it`
|
80 | );
|
81 | }
|
82 |
|
83 | if (
|
84 | optionalFeaturesMissing ||
|
85 | typeof optionalFeatures.isFeatureExplicitlySet !== 'function'
|
86 | ) {
|
87 | message.push(
|
88 | '* Unable to detect if jquery-integration is explicitly set to a value, please update `@ember/optional-features` to the latest version'
|
89 | );
|
90 | }
|
91 |
|
92 | if (
|
93 | optionalFeaturesMissing ||
|
94 | (typeof optionalFeatures.isFeatureExplicitlySet === 'function' &&
|
95 | !optionalFeatures.isFeatureExplicitlySet('jquery-integration'))
|
96 | ) {
|
97 | message.push(
|
98 | `* The jquery-integration optional feature should be explicitly set to a value under Octane, run \`ember feature:disable jquery-integration\` to disable it, or \`ember feature:enable jquery-integration\` to explicitly enable it`
|
99 | );
|
100 | }
|
101 |
|
102 | if (
|
103 | optionalFeaturesMissing ||
|
104 | optionalFeatures.isFeatureEnabled('application-template-wrapper')
|
105 | ) {
|
106 | message.push(
|
107 | `* The application-template-wrapper optional feature should be disabled under Octane, run \`ember feature:disable application-template-wrapper\` to disable it`
|
108 | );
|
109 | }
|
110 |
|
111 | if (
|
112 | optionalFeaturesMissing ||
|
113 | !optionalFeatures.isFeatureEnabled('template-only-glimmer-components')
|
114 | ) {
|
115 | message.push(
|
116 | `* The template-only-glimmer-components optional feature should be enabled under Octane, run \`ember feature:enable template-only-glimmer-components\` to enable it`
|
117 | );
|
118 | }
|
119 |
|
120 | if (message.length > 0) {
|
121 | message.unshift(
|
122 | `You have configured your application to indicate that it is using the 'octane' edition (via \`setEdition('octane')\`), but the appropriate Octane features were not enabled:\n`
|
123 | );
|
124 |
|
125 | const SilentError = require('silent-error');
|
126 | throw new SilentError(message.join('\n\t'));
|
127 | }
|
128 | }
|
129 | },
|
130 |
|
131 | transpileTree(tree, isProduction, shouldCompileModules) {
|
132 | let emberCliBabel = this.addons.find(a => a.name === 'ember-cli-babel');
|
133 |
|
134 | let parentOptions = this.parent && this.parent.options;
|
135 | let appOptions = this.app && this.app.options;
|
136 | let babelOptions = (parentOptions || appOptions || {}).babel;
|
137 |
|
138 |
|
139 |
|
140 | let isEmberSource = this.project.name() === 'ember-source';
|
141 | let babelHelperPlugin = injectBabelHelpers(isEmberSource);
|
142 |
|
143 | let options = {
|
144 | 'ember-cli-babel': {
|
145 | disableDebugTooling: true,
|
146 | disableEmberModulesAPIPolyfill: true,
|
147 | },
|
148 | babel: Object.assign({}, babelOptions, {
|
149 | loose: true,
|
150 | plugins: [
|
151 | babelHelperPlugin,
|
152 | buildDebugMacroPlugin(!isProduction),
|
153 | [
|
154 | require.resolve('@babel/plugin-transform-block-scoping'),
|
155 | { throwIfClosureRequired: true },
|
156 | ],
|
157 | [require.resolve('@babel/plugin-transform-object-assign')],
|
158 | ],
|
159 | }),
|
160 | };
|
161 |
|
162 | if (shouldCompileModules !== undefined) {
|
163 |
|
164 |
|
165 |
|
166 | options['ember-cli-babel'].compileModules = shouldCompileModules;
|
167 | }
|
168 |
|
169 | if (isProduction) {
|
170 | options.babel.plugins.push(buildStripClassCallcheckPlugin());
|
171 | }
|
172 |
|
173 | return emberCliBabel.transpileTree(tree, options);
|
174 | },
|
175 |
|
176 | buildEmberBundles(tree, isProduction) {
|
177 | let packages = this.transpileTree(new Funnel(tree, { srcDir: 'packages' }), isProduction);
|
178 |
|
179 | let dependencies = this.transpileTree(
|
180 | new Funnel(tree, { srcDir: 'dependencies' }),
|
181 | isProduction
|
182 | );
|
183 |
|
184 | let headerFiles = this.transpileTree(
|
185 | new Funnel(tree, { srcDir: 'header' }),
|
186 | isProduction,
|
187 | false
|
188 | );
|
189 |
|
190 | let exclude = isProduction ? ['ember-testing/**'] : [];
|
191 |
|
192 | let emberFiles = new MergeTrees([new Funnel(packages, { exclude }), dependencies, headerFiles]);
|
193 |
|
194 | let emberTestingFiles = new MergeTrees([
|
195 | new Funnel(packages, {
|
196 | include: [
|
197 | '@ember/debug/lib/**',
|
198 | '@ember/debug/index.js',
|
199 | 'ember-testing/index.js',
|
200 | 'ember-testing/lib/**',
|
201 | ],
|
202 | }),
|
203 | headerFiles,
|
204 | ]);
|
205 |
|
206 | return new MergeTrees([
|
207 | concatBundle(emberFiles, {
|
208 | outputFile: 'ember.js',
|
209 | footer: "require('ember');",
|
210 | }),
|
211 |
|
212 | concatBundle(emberTestingFiles, {
|
213 | outputFile: 'ember-testing.js',
|
214 | footer: `
|
215 | var testing = require('ember-testing');
|
216 | Ember.Test = testing.Test;
|
217 | Ember.Test.Adapter = testing.Adapter;
|
218 | Ember.Test.QUnitAdapter = testing.QUnitAdapter;
|
219 | Ember.setupForTesting = testing.setupForTesting;
|
220 | `,
|
221 | }),
|
222 | ]);
|
223 | },
|
224 |
|
225 | treeForVendor(tree) {
|
226 | let jqueryPath;
|
227 |
|
228 | try {
|
229 | jqueryPath = path.dirname(
|
230 | resolve.sync('jquery/package.json', { basedir: this.project.root })
|
231 | );
|
232 | } catch (error) {
|
233 | jqueryPath = path.dirname(require.resolve('jquery/package.json'));
|
234 | }
|
235 |
|
236 | let jquery = new Funnel(jqueryPath + '/dist', {
|
237 | destDir: 'ember/jquery',
|
238 | files: ['jquery.js'],
|
239 | });
|
240 |
|
241 | let templateCompiler = new Funnel(tree, {
|
242 | destDir: 'ember',
|
243 | include: ['ember-template-compiler.js', 'ember-template-compiler.map'],
|
244 | });
|
245 |
|
246 | let ember;
|
247 | let targets = (this.project && this.project.targets && this.project.targets.browsers) || [];
|
248 |
|
249 | const isProduction = process.env.EMBER_ENV === 'production';
|
250 |
|
251 | if (
|
252 | !isProduction &&
|
253 | (PRE_BUILT_TARGETS.every(target => targets.includes(target)) &&
|
254 | targets.length === PRE_BUILT_TARGETS.length)
|
255 | ) {
|
256 | ember = new Funnel(tree, {
|
257 | destDir: 'ember',
|
258 | include: ['ember.debug.js', 'ember.debug.map', 'ember-testing.js', 'ember-testing.map'],
|
259 | getDestinationPath(path) {
|
260 | return path.replace('ember.debug.', 'ember.');
|
261 | },
|
262 | });
|
263 | } else {
|
264 | ember = new Funnel(this.buildEmberBundles(tree, isProduction), {
|
265 | destDir: 'ember',
|
266 | });
|
267 | }
|
268 |
|
269 | return debugTree(new MergeTrees([ember, templateCompiler, jquery]), 'vendor:final');
|
270 | },
|
271 | };
|