Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions karma-dart-evalcache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// This module provides a customFileHandler for karma
// that serves files with urls like /packages_<timestamp>/...
// with maximum cache.
// We are using these urls when we spawn isolates
// so that the isolates don't reload files every time.

var common = require('karma/lib/middleware/common');
var fs = require('fs');

var DART_EVAL_PATH_RE = /.*\/packages_\d+\/(.*)$/;

module.exports = createFactory;

function createFactory(proxyPaths) {
return {
'framework:dart-evalcache': ['factory', dartEvalCacheFactory]
};

function dartEvalCacheFactory(emitter, logger, customFileHandlers) {
var filesPromise = new common.PromiseContainer();
emitter.on('file_list_modified', function(files) {
filesPromise.set(files);
});

var serveFile = common.createServeFile(fs);
var log = logger.create('dart-evalcache');

customFileHandlers.push({
urlRegex: DART_EVAL_PATH_RE,
handler: handler
});

// See source_files handler
function handler(request, response, fa, fb, basePath) {
return filesPromise.then(function(files) {
try {
var requestedFilePath = mapUrlToFile(request.url, proxyPaths, basePath, log);
// TODO(vojta): change served to be a map rather then an array
var file = findByPath(files.served, requestedFilePath);
if (file) {
serveFile(file.contentPath || file.path, response, function() {
common.setHeavyCacheHeaders(response);
}, file.content);
} else {
response.writeHead(404);
response.end('Not found');
}
} catch (e) {
log.error(e.stack);
response.writeHead(500);
response.end('Error', e.stack);
}
});
}
};
}

function mapUrlToFile(url, proxyPaths, basePath, log) {
var originalUrl = url;
url = url.indexOf('?') > -1 ? url.substring(0, url.indexOf('?')) : url;
var match = DART_EVAL_PATH_RE.exec(url);
var packagePath = match[1];
var result = null;
var lastProxyFromLength = 0;
Object.keys(proxyPaths).forEach(function(proxyFrom) {
if (startsWith(packagePath, proxyFrom) && proxyFrom.length > lastProxyFromLength) {
lastProxyFromLength = proxyFrom.length;
result = proxyPaths[proxyFrom] + packagePath.substring(proxyFrom.length);
}
});
return basePath + '/' + result;
}

function startsWith(string, subString) {
return string.length >= subString.length && string.slice(0, subString.length) === subString;
}

function findByPath(files, path) {
for (var i = 0; i < files.length; i++) {
if (files[i].path === path) {
return files[i];
}
}

return null;
}
59 changes: 40 additions & 19 deletions karma-dart.conf.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,41 @@
var sauceConf = require('./sauce.conf');

var packageSources = {
// Dependencies installed with `pub install`.
'unittest': 'packages/unittest',
'guinness': 'packages/guinness',
'matcher': 'packages/matcher',
'stack_trace': 'packages/stack_trace',
'collection': 'packages/collection',
'path': 'packages/path',
'observe': 'packages/observe',
'quiver': 'packages/quiver',
'intl': 'packages/intl',
'smoke': 'packages/smoke',
'logging': 'packages/logging',
'utf': 'packages/utf',

// Local dependencies, transpiled from the source.
'angular2/test/': 'dist/dart/angular2/test/',
'angular2': 'dist/dart/angular2/lib',
'http': 'dist/dart/http/lib',
'angular2_material': 'dist/dart/angular2_material/lib',
'benchpress': 'dist/dart/benchpress/lib',
'examples': 'dist/dart/examples/lib'
};

var proxyPaths = {};
Object.keys(packageSources).map(function(packageName) {
var filePath = packageSources[packageName];
proxyPaths['/packages/'+packageName] = '/base/'+filePath;
});

// Karma configuration
// Generated on Thu Sep 25 2014 11:52:02 GMT-0700 (PDT)
module.exports = function(config) {
config.set({

frameworks: ['dart-unittest'],
frameworks: ['dart-unittest', 'dart-evalcache'],

files: [
// Init and configure guiness.
Expand Down Expand Up @@ -35,27 +65,18 @@ module.exports = function(config) {
},

// Map packages to the correct urls where Karma serves them.
proxies: {
// Dependencies installed with `pub install`.
'/packages/unittest': '/base/packages/unittest',
'/packages/guinness': '/base/packages/guinness',
'/packages/matcher': '/base/packages/matcher',
'/packages/stack_trace': '/base/packages/stack_trace',
'/packages/collection': '/base/packages/collection',
'/packages/path': '/base/packages/path',

// Local dependencies, transpiled from the source.
'/packages/angular2/test/': '/base/dist/dart/angular2/test/',
'/packages/angular2': '/base/dist/dart/angular2/lib',
'/packages/http': '/base/dist/dart/http/lib',
'/packages/angular2_material': '/base/dist/dart/angular2_material/lib',
'/packages/benchpress': '/base/dist/dart/benchpress/lib',
'/packages/examples': '/base/dist/dart/examples/lib'
},
proxies: proxyPaths,

customLaunchers: sauceConf.customLaunchers,
browsers: ['DartiumWithWebPlatform'],

port: 9877
port: 9877,

plugins: [
require('karma-dart'),
require('karma-chrome-launcher'),
require('karma-sauce-launcher'),
require('./karma-dart-evalcache')(packageSources)
]
});
};
147 changes: 116 additions & 31 deletions modules/angular2/src/compiler/api.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
import {isPresent, normalizeBool} from 'angular2/src/core/facade/lang';
import {HtmlAst} from './html_ast';
import {ChangeDetectionStrategy} from 'angular2/src/core/change_detection/change_detection';
import {isPresent, normalizeBool, serializeEnum, Type} from 'angular2/src/core/facade/lang';
import {
ChangeDetectionStrategy,
changeDetectionStrategyFromJson
} from 'angular2/src/core/change_detection/change_detection';
import {ViewEncapsulation, viewEncapsulationFromJson} from 'angular2/src/core/render/api';

export class TypeMetadata {
id: number;
type: any;
type: Type;
typeName: string;
typeUrl: string;
constructor({id, type, typeName, typeUrl}:
{id?: number, type?: string, typeName?: string, typeUrl?: string} = {}) {
{id?: number, type?: Type, typeName?: string, typeUrl?: string} = {}) {
this.id = id;
this.type = type;
this.typeName = typeName;
this.typeUrl = typeUrl;
}

static fromJson(data: StringMap<string, any>): TypeMetadata {
return new TypeMetadata(
{id: data['id'], type: data['type'], typeName: data['typeName'], typeUrl: data['typeUrl']});
}

toJson(): StringMap<string, any> {
return {
// Note: Runtime type can't be serialized...
'id': this.id,
'typeName': this.typeName,
'typeUrl': this.typeUrl
};
}
}

export class ChangeDetectionMetadata {
Expand Down Expand Up @@ -44,7 +61,7 @@ export class ChangeDetectionMetadata {
callOnChanges?: boolean,
callDoCheck?: boolean,
callOnInit?: boolean
}) {
} = {}) {
this.changeDetection = changeDetection;
this.properties = properties;
this.events = events;
Expand All @@ -58,60 +75,102 @@ export class ChangeDetectionMetadata {
this.callDoCheck = callDoCheck;
this.callOnInit = callOnInit;
}

static fromJson(data: StringMap<string, any>): ChangeDetectionMetadata {
return new ChangeDetectionMetadata({
changeDetection: isPresent(data['changeDetection']) ?
changeDetectionStrategyFromJson(data['changeDetection']) :
data['changeDetection'],
properties: data['properties'],
events: data['events'],
hostListeners: data['hostListeners'],
hostProperties: data['hostProperties'],
callAfterContentInit: data['callAfterContentInit'],
callAfterContentChecked: data['callAfterContentChecked'],
callAfterViewInit: data['callAfterViewInit'],
callAfterViewChecked: data['callAfterViewChecked'],
callOnChanges: data['callOnChanges'],
callDoCheck: data['callDoCheck'],
callOnInit: data['callOnInit']
});
}

toJson(): StringMap<string, any> {
return {
'changeDetection': isPresent(this.changeDetection) ? serializeEnum(this.changeDetection) :
this.changeDetection,
'properties': this.properties,
'events': this.events,
'hostListeners': this.hostListeners,
'hostProperties': this.hostProperties,
'callAfterContentInit': this.callAfterContentInit,
'callAfterContentChecked': this.callAfterContentChecked,
'callAfterViewInit': this.callAfterViewInit,
'callAfterViewChecked': this.callAfterViewChecked,
'callOnChanges': this.callOnChanges,
'callDoCheck': this.callDoCheck,
'callOnInit': this.callOnInit
};
}
}

export class TemplateMetadata {
encapsulation: ViewEncapsulation;
nodes: HtmlAst[];
template: string;
styles: string[];
styleAbsUrls: string[];
ngContentSelectors: string[];
constructor({encapsulation, nodes, styles, styleAbsUrls, ngContentSelectors}: {
constructor({encapsulation, template, styles, styleAbsUrls, ngContentSelectors}: {
encapsulation?: ViewEncapsulation,
nodes?: HtmlAst[],
template?: string,
styles?: string[],
styleAbsUrls?: string[],
ngContentSelectors?: string[]
}) {
} = {}) {
this.encapsulation = encapsulation;
this.nodes = nodes;
this.template = template;
this.styles = styles;
this.styleAbsUrls = styleAbsUrls;
this.ngContentSelectors = ngContentSelectors;
}
}

/**
* How the template and styles of a view should be encapsulated.
*/
export enum ViewEncapsulation {
/**
* Emulate scoping of styles by preprocessing the style rules
* and adding additional attributes to elements. This is the default.
*/
Emulated,
/**
* Uses the native mechanism of the renderer. For the DOM this means creating a ShadowRoot.
*/
Native,
/**
* Don't scope the template nor the styles.
*/
None
static fromJson(data: StringMap<string, any>): TemplateMetadata {
return new TemplateMetadata({
encapsulation: isPresent(data['encapsulation']) ?
viewEncapsulationFromJson(data['encapsulation']) :
data['encapsulation'],
template: data['template'],
styles: data['styles'],
styleAbsUrls: data['styleAbsUrls'],
ngContentSelectors: data['ngContentSelectors'],
});
}

toJson(): StringMap<string, any> {
return {
'encapsulation':
isPresent(this.encapsulation) ? serializeEnum(this.encapsulation) : this.encapsulation,
'template': this.template,
'styles': this.styles,
'styleAbsUrls': this.styleAbsUrls,
'ngContentSelectors': this.ngContentSelectors,
};
}
}


export class DirectiveMetadata {
type: TypeMetadata;
isComponent: boolean;
selector: string;
hostAttributes: Map<string, string>;
hostAttributes: StringMap<string, string>;
changeDetection: ChangeDetectionMetadata;
template: TemplateMetadata;
constructor({type, isComponent, selector, hostAttributes, changeDetection, template}: {
type?: TypeMetadata,
isComponent?: boolean,
selector?: string,
hostAttributes?: Map<string, string>,
hostAttributes?: StringMap<string, string>,
changeDetection?: ChangeDetectionMetadata,
template?: TemplateMetadata
} = {}) {
Expand All @@ -122,6 +181,32 @@ export class DirectiveMetadata {
this.changeDetection = changeDetection;
this.template = template;
}

static fromJson(data: StringMap<string, any>): DirectiveMetadata {
return new DirectiveMetadata({
type: isPresent(data['type']) ? TypeMetadata.fromJson(data['type']) : data['type'],
isComponent: data['isComponent'],
selector: data['selector'],
hostAttributes: data['hostAttributes'],
changeDetection: isPresent(data['changeDetection']) ?
ChangeDetectionMetadata.fromJson(data['changeDetection']) :
data['changeDetection'],
template: isPresent(data['template']) ? TemplateMetadata.fromJson(data['template']) :
data['template']
});
}

toJson(): StringMap<string, any> {
return {
'type': isPresent(this.type) ? this.type.toJson() : this.type,
'isComponent': this.isComponent,
'selector': this.selector,
'hostAttributes': this.hostAttributes,
'changeDetection':
isPresent(this.changeDetection) ? this.changeDetection.toJson() : this.changeDetection,
'template': isPresent(this.template) ? this.template.toJson() : this.template
};
}
}

export class SourceModule {
Expand Down
Loading