Skip to content
Merged

cx #2

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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ Use imports from `angular2/compiler` instead.
<my-cmp (myEvent)="action()">
<my-cmp [(myProp)]="prop">
<input #myInput>`,
<template ngFor="#myItem" [ngForOf]=items #myIndex="index">
<template ngFor "#myItem" [ngForOf]=items #myIndex="index">
```

The full migration instruction can be found at [angular2/docs/migration/kebab-case.md](https://github.com/angular/angular/blob/master/modules/angular2/docs/migration/kebab-case.md).
Expand Down
9 changes: 6 additions & 3 deletions COMMITTER.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ Someone with committer access will do the rest.
We have automated the process for merging pull requests into master. Our goal is to minimize the disruption for
Angular committers and also prevent breakages on master.

When a PR is ready to merge, a project member in the CoreTeamMember list (see below) can add the special label,
`PR: merge`.
When a PR has `pr_state: LGTM` and is ready to merge, you should add the `pr_action: merge` label.
Currently (late 2015), we need to ensure that each PR will cleanly merge into the Google-internal version control,
so the caretaker reviews the changes manually.

After this review, the caretaker adds `zomg_admin: do_merge` which is restricted to admins only.
A robot running as [mary-poppins](https://github.com/mary-poppins)
is notified that the label was added by an authorized person,
and will create a new branch in the angular project, using the convention `presubmit-{username}-pr-{number}`.
Expand All @@ -26,6 +29,6 @@ Finally, after merge `mary-poppins` removes the presubmit branch.

## Administration

The list of users who can trigger a merge by adding the label is stored in our appengine app datastore.
The list of users who can trigger a merge by adding the `zomg_admin: do_merge` label is stored in our appengine app datastore.
Edit the contents of the [CoreTeamMember Table](
https://console.developers.google.com/project/angular2-automation/datastore/query?queryType=KindQuery&namespace=&kind=CoreTeamMember)
10 changes: 10 additions & 0 deletions clone.git
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
$ git clone --bare https://github.com/angular/angular.git
# Make a bare clone of the repository

$ cd old-repository.git
$ git push --mirror https://github.com/usernamealreadyis/commands.git
# Mirror-push to the new repository

$ cd ..
$ rm -rf old-repository.git
# Remove our temporary local repository
4 changes: 2 additions & 2 deletions modules/angular2/docs/cheatsheet/template-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ Creates a local variable `movieplayer` that provides access to the `video` eleme

@cheatsheetItem
syntax:
`<p *my-unless="myExpression">...</p>`|`*my-unless`
`<p *myUnless="myExpression">...</p>`|`*myUnless`
description:
The `*` symbol means that the current element will be turned into an embedded template. Equivalent to:
`<template [myless]="myExpression"><p>...</p></template>`
`<template [myUnless]="myExpression"><p>...</p></template>`

@cheatsheetItem
syntax:
Expand Down
2 changes: 1 addition & 1 deletion modules/angular2/src/compiler/template_parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,13 @@ class TemplateParseVisitor implements HtmlAstVisitor {
var attrs = [];

element.attrs.forEach(attr => {
matchableAttrs.push([attr.name, attr.value]);
var hasBinding = this._parseAttr(attr, matchableAttrs, elementOrDirectiveProps, events, vars);
var hasTemplateBinding = this._parseInlineTemplateBinding(
attr, templateMatchableAttrs, templateElementOrDirectiveProps, templateVars);
if (!hasBinding && !hasTemplateBinding) {
// don't include the bindings as attributes as well in the AST
attrs.push(this.visitAttr(attr, null));
matchableAttrs.push([attr.name, attr.value]);
}
if (hasTemplateBinding) {
hasInlineTemplates = true;
Expand Down
1 change: 1 addition & 0 deletions modules/angular2/src/facade/lang.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Math {
static final _random = new math.Random();
static int floor(num n) => n.floor();
static double random() => _random.nextDouble();
static num min(num a, num b) => math.min(a, b);
}

class CONST {
Expand Down
6 changes: 3 additions & 3 deletions modules/angular2/src/router/instruction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ export abstract class Instruction {

get urlParams(): string[] { return isPresent(this.component) ? this.component.urlParams : []; }

get specificity(): number {
var total = 0;
get specificity(): string {
var total = '';
if (isPresent(this.component)) {
total += this.component.specificity;
}
Expand Down Expand Up @@ -305,7 +305,7 @@ export class ComponentInstruction {
public routeData: RouteData;

constructor(public urlPath: string, public urlParams: string[], data: RouteData,
public componentType, public terminal: boolean, public specificity: number,
public componentType, public terminal: boolean, public specificity: string,
public params: {[key: string]: any} = null) {
this.routeData = isPresent(data) ? data : BLANK_ROUTE_DATA;
}
Expand Down
38 changes: 19 additions & 19 deletions modules/angular2/src/router/path_recognizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,45 +96,45 @@ function parsePathString(route: string): {[key: string]: any} {

var segments = splitBySlash(route);
var results = [];
var specificity = 0;

var specificity = '';

// a single slash (or "empty segment" is as specific as a static segment
if (segments.length == 0) {
specificity += '2';
}

// The "specificity" of a path is used to determine which route is used when multiple routes match
// a URL.
// Static segments (like "/foo") are the most specific, followed by dynamic segments (like
// "/:id"). Star segments
// add no specificity. Segments at the start of the path are more specific than proceeding ones.
// a URL. Static segments (like "/foo") are the most specific, followed by dynamic segments (like
// "/:id"). Star segments add no specificity. Segments at the start of the path are more specific
// than proceeding ones.
//
// The code below uses place values to combine the different types of segments into a single
// integer that we can
// sort later. Each static segment is worth hundreds of points of specificity (10000, 9900, ...,
// 200), and each
// dynamic segment is worth single points of specificity (100, 99, ... 2).
if (segments.length > 98) {
throw new BaseException(`'${route}' has more than the maximum supported number of segments.`);
}
// string that we can sort later. Each static segment is marked as a specificity of "2," each
// dynamic segment is worth "1" specificity, and stars are worth "0" specificity.

var limit = segments.length - 1;
for (var i = 0; i <= limit; i++) {
var segment = segments[i], match;

if (isPresent(match = RegExpWrapper.firstMatch(paramMatcher, segment))) {
results.push(new DynamicSegment(match[1]));
specificity += (100 - i);
specificity += '1';
} else if (isPresent(match = RegExpWrapper.firstMatch(wildcardMatcher, segment))) {
results.push(new StarSegment(match[1]));
specificity += '0';
} else if (segment == '...') {
if (i < limit) {
throw new BaseException(`Unexpected "..." before the end of the path for "${route}".`);
}
results.push(new ContinuationSegment());
} else {
results.push(new StaticSegment(segment));
specificity += 100 * (100 - i);
specificity += '2';
}
}
var result = StringMapWrapper.create();
StringMapWrapper.set(result, 'segments', results);
StringMapWrapper.set(result, 'specificity', specificity);
return result;

return {'segments': results, 'specificity': specificity};
}

// this function is used to determine whether a route config path like `/foo/:id` collides with
Expand Down Expand Up @@ -177,7 +177,7 @@ function assertPath(path: string) {
*/
export class PathRecognizer {
private _segments: Segment[];
specificity: number;
specificity: string;
terminal: boolean = true;
hash: string;

Expand Down
2 changes: 1 addition & 1 deletion modules/angular2/src/router/route_recognizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class RedirectRecognizer implements AbstractRecognizer {

// represents something like '/foo/:bar'
export class RouteRecognizer implements AbstractRecognizer {
specificity: number;
specificity: string;
terminal: boolean = true;
hash: string;

Expand Down
36 changes: 35 additions & 1 deletion modules/angular2/src/router/route_registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
isString,
isStringMap,
Type,
StringWrapper,
Math,
getTypeNameForDebugging,
CONST_EXPR
} from 'angular2/src/facade/lang';
Expand Down Expand Up @@ -492,7 +494,39 @@ function splitAndFlattenLinkParams(linkParams: any[]): any[] {
* Given a list of instructions, returns the most specific instruction
*/
function mostSpecific(instructions: Instruction[]): Instruction {
return ListWrapper.maximum(instructions, (instruction: Instruction) => instruction.specificity);
instructions = instructions.filter((instruction) => isPresent(instruction));
if (instructions.length == 0) {
return null;
}
if (instructions.length == 1) {
return instructions[0];
}
var first = instructions[0];
var rest = instructions.slice(1);
return rest.reduce((instruction: Instruction, contender: Instruction) => {
if (compareSpecificityStrings(contender.specificity, instruction.specificity) == -1) {
return contender;
}
return instruction;
}, first);
}

/*
* Expects strings to be in the form of "[0-2]+"
* Returns -1 if string A should be sorted above string B, 1 if it should be sorted after,
* or 0 if they are the same.
*/
function compareSpecificityStrings(a: string, b: string): number {
var l = Math.min(a.length, b.length);
for (var i = 0; i < l; i += 1) {
var ai = StringWrapper.charCodeAt(a, i);
var bi = StringWrapper.charCodeAt(b, i);
var difference = bi - ai;
if (difference != 0) {
return difference;
}
}
return a.length - b.length;
}

function assertTerminalComponent(component, path) {
Expand Down
19 changes: 19 additions & 0 deletions modules/angular2/test/router/route_registry_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,21 @@ export function main() {
});
}));

it('should prefer routes with high specificity over routes with children with lower specificity',
inject([AsyncTestCompleter], (async) => {
registry.config(RootHostCmp, new Route({path: '/first', component: DummyCmpA}));

// terminates to DummyCmpB
registry.config(RootHostCmp,
new Route({path: '/:second/...', component: SingleSlashChildCmp}));

registry.recognize('/first', [])
.then((instruction) => {
expect(instruction.component.componentType).toBe(DummyCmpA);
async.done();
});
}));

it('should match the full URL using child components', inject([AsyncTestCompleter], (async) => {
registry.config(RootHostCmp, new Route({path: '/first/...', component: DummyParentCmp}));

Expand Down Expand Up @@ -322,6 +337,10 @@ class DummyCmpB {}
class DefaultRouteCmp {
}

@RouteConfig([new Route({path: '/', component: DummyCmpB, name: 'ThirdCmp'})])
class SingleSlashChildCmp {
}


@RouteConfig([
new Route(
Expand Down
4 changes: 2 additions & 2 deletions modules/angular2/test/router/router_link_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ import {
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
import {ResolvedInstruction} from 'angular2/src/router/instruction';

let dummyInstruction =
new ResolvedInstruction(new ComponentInstruction('detail', [], null, null, true, 0), null, {});
let dummyInstruction = new ResolvedInstruction(
new ComponentInstruction('detail', [], null, null, true, '0'), null, {});

export function main() {
describe('routerLink directive', function() {
Expand Down
5 changes: 4 additions & 1 deletion tools/broccoli/broccoli-typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,10 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {

if (fs.existsSync(absoluteJsFilePath)) {
fs.unlinkSync(absoluteJsFilePath);
fs.unlinkSync(absoluteMapFilePath);
if (fs.existsSync(absoluteMapFilePath)) {
// source map could be inline or not generated
fs.unlinkSync(absoluteMapFilePath);
}
fs.unlinkSync(absoluteDtsFilePath);
}
}
Expand Down