mirror of https://github.com/sveltejs/svelte
				
				
				
			
						commit
						0ebe5355e1
					
				@ -0,0 +1,102 @@
 | 
				
			|||||||
 | 
					import { Node, Warning } from './interfaces';
 | 
				
			||||||
 | 
					import Generator from './generators/Generator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const now = (typeof process !== 'undefined' && process.hrtime)
 | 
				
			||||||
 | 
						? () => {
 | 
				
			||||||
 | 
							const t = process.hrtime();
 | 
				
			||||||
 | 
							return t[0] * 1e3 + t[1] / 1e6;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						: () => window.performance.now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Timing = {
 | 
				
			||||||
 | 
						label: string;
 | 
				
			||||||
 | 
						start: number;
 | 
				
			||||||
 | 
						end: number;
 | 
				
			||||||
 | 
						children: Timing[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function collapseTimings(timings) {
 | 
				
			||||||
 | 
						const result = {};
 | 
				
			||||||
 | 
						timings.forEach(timing => {
 | 
				
			||||||
 | 
							result[timing.label] = Object.assign({
 | 
				
			||||||
 | 
								total: timing.end - timing.start
 | 
				
			||||||
 | 
							}, timing.children && collapseTimings(timing.children));
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class Stats {
 | 
				
			||||||
 | 
						startTime: number;
 | 
				
			||||||
 | 
						currentTiming: Timing;
 | 
				
			||||||
 | 
						currentChildren: Timing[];
 | 
				
			||||||
 | 
						timings: Timing[];
 | 
				
			||||||
 | 
						stack: Timing[];
 | 
				
			||||||
 | 
						warnings: Warning[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						constructor() {
 | 
				
			||||||
 | 
							this.startTime = now();
 | 
				
			||||||
 | 
							this.stack = [];
 | 
				
			||||||
 | 
							this.currentChildren = this.timings = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.warnings = [];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						start(label) {
 | 
				
			||||||
 | 
							const timing = {
 | 
				
			||||||
 | 
								label,
 | 
				
			||||||
 | 
								start: now(),
 | 
				
			||||||
 | 
								end: null,
 | 
				
			||||||
 | 
								children: []
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.currentChildren.push(timing);
 | 
				
			||||||
 | 
							this.stack.push(timing);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.currentTiming = timing;
 | 
				
			||||||
 | 
							this.currentChildren = timing.children;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stop(label) {
 | 
				
			||||||
 | 
							if (label !== this.currentTiming.label) {
 | 
				
			||||||
 | 
								throw new Error(`Mismatched timing labels`);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.currentTiming.end = now();
 | 
				
			||||||
 | 
							this.stack.pop();
 | 
				
			||||||
 | 
							this.currentTiming = this.stack[this.stack.length - 1];
 | 
				
			||||||
 | 
							this.currentChildren = this.currentTiming ? this.currentTiming.children : this.timings;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						render(generator: Generator) {
 | 
				
			||||||
 | 
							const timings = Object.assign({
 | 
				
			||||||
 | 
								total: now() - this.startTime
 | 
				
			||||||
 | 
							}, collapseTimings(this.timings));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const imports = generator.imports.map(node => {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									source: node.source.value,
 | 
				
			||||||
 | 
									specifiers: node.specifiers.map(specifier => {
 | 
				
			||||||
 | 
										return {
 | 
				
			||||||
 | 
											name: (
 | 
				
			||||||
 | 
												specifier.type === 'ImportDefaultSpecifier' ? 'default' :
 | 
				
			||||||
 | 
												specifier.type === 'ImportNamespaceSpecifier' ? '*' :
 | 
				
			||||||
 | 
												specifier.imported.name
 | 
				
			||||||
 | 
											),
 | 
				
			||||||
 | 
											as: specifier.local.name
 | 
				
			||||||
 | 
										};
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const hooks: Record<string, boolean> = {};
 | 
				
			||||||
 | 
							if (generator.templateProperties.oncreate) hooks.oncreate = true;
 | 
				
			||||||
 | 
							if (generator.templateProperties.ondestroy) hooks.ondestroy = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								timings,
 | 
				
			||||||
 | 
								warnings: this.warnings,
 | 
				
			||||||
 | 
								imports,
 | 
				
			||||||
 | 
								hooks
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					import * as fs from 'fs';
 | 
				
			||||||
 | 
					import assert from 'assert';
 | 
				
			||||||
 | 
					import { svelte, loadConfig, tryToLoadJson } from '../helpers.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('stats', () => {
 | 
				
			||||||
 | 
						fs.readdirSync('test/stats/samples').forEach(dir => {
 | 
				
			||||||
 | 
							if (dir[0] === '.') return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// add .solo to a sample directory name to only run that test
 | 
				
			||||||
 | 
							const solo = /\.solo/.test(dir);
 | 
				
			||||||
 | 
							const skip = /\.skip/.test(dir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (solo && process.env.CI) {
 | 
				
			||||||
 | 
								throw new Error('Forgot to remove `solo: true` from test');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							(solo ? it.only : skip ? it.skip : it)(dir, () => {
 | 
				
			||||||
 | 
								const config = loadConfig(`./stats/samples/${dir}/_config.js`);
 | 
				
			||||||
 | 
								const filename = `test/stats/samples/${dir}/input.html`;
 | 
				
			||||||
 | 
								const input = fs.readFileSync(filename, 'utf-8').replace(/\s+$/, '');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const expectedWarnings =
 | 
				
			||||||
 | 
									tryToLoadJson(`test/stats/samples/${dir}/warnings.json`) || [];
 | 
				
			||||||
 | 
								const expectedError = tryToLoadJson(
 | 
				
			||||||
 | 
									`test/stats/samples/${dir}/error.json`
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								let result;
 | 
				
			||||||
 | 
								let error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									result = svelte.compile(input, config.options);
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									error = e;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								config.test(assert, result.stats);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (result.stats.warnings.length || expectedWarnings.length) {
 | 
				
			||||||
 | 
									// TODO check warnings are added to stats.warnings
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (error || expectedError) {
 | 
				
			||||||
 | 
									if (error && !expectedError) {
 | 
				
			||||||
 | 
										throw error;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (expectedError && !error) {
 | 
				
			||||||
 | 
										throw new Error(`Expected an error: ${expectedError.message}`);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									assert.equal(error.message, expectedError.message);
 | 
				
			||||||
 | 
									assert.deepEqual(error.loc, expectedError.loc);
 | 
				
			||||||
 | 
									assert.deepEqual(error.end, expectedError.end);
 | 
				
			||||||
 | 
									assert.equal(error.pos, expectedError.pos);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					export default {
 | 
				
			||||||
 | 
						test(assert, stats) {
 | 
				
			||||||
 | 
							assert.equal(typeof stats.timings, 'object');
 | 
				
			||||||
 | 
							assert.equal(typeof stats.timings.total, 'number');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					export default {
 | 
				
			||||||
 | 
						test(assert, stats) {
 | 
				
			||||||
 | 
							assert.deepEqual(stats.hooks, {
 | 
				
			||||||
 | 
								oncreate: true
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						export default {
 | 
				
			||||||
 | 
							oncreate() {
 | 
				
			||||||
 | 
								console.log('creating');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					export default {
 | 
				
			||||||
 | 
						test(assert, stats) {
 | 
				
			||||||
 | 
							assert.deepEqual(stats.imports, [
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									source: 'x',
 | 
				
			||||||
 | 
									specifiers: [{ name: 'default', as: 'x' }]
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									source: 'y',
 | 
				
			||||||
 | 
									specifiers: [{ name: 'y', as: 'y' }]
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									source: 'z',
 | 
				
			||||||
 | 
									specifiers: [{ name: '*', as: 'z' }]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import x from 'x';
 | 
				
			||||||
 | 
						import { y } from 'y';
 | 
				
			||||||
 | 
						import * as z from 'z';
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue