diff --git a/modules/@angular/compiler/src/html_parser/tags.ts b/modules/@angular/compiler/src/html_parser/tags.ts index 074974155c..f83c8fd848 100644 --- a/modules/@angular/compiler/src/html_parser/tags.ts +++ b/modules/@angular/compiler/src/html_parser/tags.ts @@ -33,13 +33,13 @@ export function splitNsName(elementName: string): [string, string] { return [null, elementName]; } - const parts = elementName.substring(1).split(':', 2); + const colonIndex = elementName.indexOf(':', 1); - if (parts.length != 2) { + if (colonIndex == -1) { throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`); } - return parts as[string, string]; + return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)]; } export function getNsPrefix(fullName: string): string { @@ -307,4 +307,4 @@ export const NAMED_ENTITIES: {[k: string]: string} = { 'zeta': '\u03B6', 'zwj': '\u200D', 'zwnj': '\u200C', -}; \ No newline at end of file +}; diff --git a/modules/@angular/compiler/src/i18n/extractor.ts b/modules/@angular/compiler/src/i18n/extractor.ts index 8709afcea5..025941d798 100644 --- a/modules/@angular/compiler/src/i18n/extractor.ts +++ b/modules/@angular/compiler/src/i18n/extractor.ts @@ -195,7 +195,8 @@ class _ExtractVisitor implements html.Visitor { // Do not create empty messages return; } - messages.push(new Message(ast, _meaning(meaningAndDesc), _description(meaningAndDesc))); + const [meaning, description] = _splitMeaningAndDesc(meaningAndDesc); + messages.push(new Message(ast, meaning, description)); } /** @@ -285,13 +286,8 @@ function _getI18nAttr(p: html.Element): html.Attribute { return p.attrs.find(attr => attr.name === _I18N_ATTR) || null; } -function _meaning(i18n: string): string { - if (!i18n || i18n == '') return ''; - return i18n.split('|', 2)[0]; +function _splitMeaningAndDesc(i18n: string): [string, string] { + if (!i18n) return ['', '']; + const pipeIndex = i18n.indexOf('|'); + return pipeIndex == -1 ? ['', i18n] : [i18n.slice(0, pipeIndex), i18n.slice(pipeIndex + 1)]; } - -function _description(i18n: string): string { - if (!i18n || i18n == '') return ''; - const parts = i18n.split('|', 2); - return parts.length > 1 ? parts[1] : ''; -} \ No newline at end of file diff --git a/modules/@angular/compiler/src/util.ts b/modules/@angular/compiler/src/util.ts index 4013b3a6c7..7b8715c17a 100644 --- a/modules/@angular/compiler/src/util.ts +++ b/modules/@angular/compiler/src/util.ts @@ -21,8 +21,9 @@ export function camelCaseToDashCase(input: string): string { } export function splitAtColon(input: string, defaultValues: string[]): string[] { - var parts = input.split(':', 2).map((s: string) => s.trim()); - return parts.length > 1 ? parts : defaultValues; + const colonIndex = input.indexOf(':'); + if (colonIndex == -1) return defaultValues; + return [input.slice(0, colonIndex).trim(), input.slice(colonIndex + 1).trim()]; } export function sanitizeIdentifier(name: string): string { diff --git a/modules/@angular/compiler/test/i18n/extractor_spec.ts b/modules/@angular/compiler/test/i18n/extractor_spec.ts index e4a310a00c..881db955dd 100644 --- a/modules/@angular/compiler/test/i18n/extractor_spec.ts +++ b/modules/@angular/compiler/test/i18n/extractor_spec.ts @@ -16,8 +16,8 @@ export function main() { describe('MessageExtractor', () => { describe('elements', () => { it('should extract from elements', () => { - expect(extract('
textnested
')).toEqual([ - [['text', 'nested'], 'm', 'd'], + expect(extract('
textnested
')).toEqual([ + [['text', 'nested'], 'm', 'd|e'], ]); }); @@ -28,11 +28,11 @@ export function main() { describe('blocks', () => { it('should extract from blocks', () => { expect(extract(`message1 - message2 + message2 message3`)) .toEqual([ [['message1'], 'meaning1', 'desc1'], - [['message2'], 'meaning2', ''], + [['message2'], '', 'desc2'], [['message3'], '', ''], ]); }); diff --git a/modules/@angular/compiler/test/i18n/i18n_parser_spec.ts b/modules/@angular/compiler/test/i18n/i18n_parser_spec.ts index 18171c7bd9..43af3b7ff6 100644 --- a/modules/@angular/compiler/test/i18n/i18n_parser_spec.ts +++ b/modules/@angular/compiler/test/i18n/i18n_parser_spec.ts @@ -133,11 +133,11 @@ export function main() { describe('blocks', () => { it('should extract from blocks', () => { expect(_humanizeMessages(`message1 - message2 + message2 message3`)) .toEqual([ [['message1'], 'meaning1', 'desc1'], - [['message2'], 'meaning2', ''], + [['message2'], '', 'desc2'], [['message3'], '', ''], ]); }); diff --git a/modules/@angular/compiler/test/util_spec.ts b/modules/@angular/compiler/test/util_spec.ts index 43ff2fbf8b..9885b4a77e 100644 --- a/modules/@angular/compiler/test/util_spec.ts +++ b/modules/@angular/compiler/test/util_spec.ts @@ -9,7 +9,7 @@ import {fakeAsync} from '@angular/core/testing/fake_async'; import {beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal'; -import {SyncAsyncResult} from '../src/util'; +import {SyncAsyncResult, splitAtColon} from '../src/util'; export function main() { describe('util', () => { @@ -20,5 +20,21 @@ export function main() { sar.asyncResult.then((v: any) => expect(v).toBe(syncValue)); })); }); + + describe('splitAtColon', () => { + it('should split when a single ":" is present', () => { + expect(splitAtColon('a:b', [])).toEqual(['a', 'b']); + }); + + it('should trim parts', () => { expect(splitAtColon(' a : b ', [])).toEqual(['a', 'b']); }); + + it('should support multiple ":"', () => { + expect(splitAtColon('a:b:c', [])).toEqual(['a', 'b:c']); + }); + + it('should use the default value when no ":" is present', () => { + expect(splitAtColon('ab', ['c', 'd'])).toEqual(['c', 'd']); + }); + }); }); } diff --git a/modules/@angular/http/src/url_search_params.ts b/modules/@angular/http/src/url_search_params.ts index 2c09bbb913..5f6ff87085 100644 --- a/modules/@angular/http/src/url_search_params.ts +++ b/modules/@angular/http/src/url_search_params.ts @@ -10,14 +10,14 @@ import {ListWrapper, Map, isListLikeIterable} from '../src/facade/collection'; import {isPresent} from '../src/facade/lang'; function paramParser(rawParams: string = ''): Map { - var map = new Map(); + const map = new Map(); if (rawParams.length > 0) { - var params: string[] = rawParams.split('&'); + const params: string[] = rawParams.split('&'); params.forEach((param: string) => { - var split: string[] = param.split('=', 2); - var key = split[0]; - var val = split[1]; - var list = isPresent(map.get(key)) ? map.get(key) : []; + const eqIdx = param.indexOf('='); + const [key, val]: string[] = + eqIdx == -1 ? [param, ''] : [param.slice(0, eqIdx), param.slice(eqIdx + 1)]; + const list = map.get(key) || []; list.push(val); map.set(key, list); }); diff --git a/modules/@angular/platform-browser/src/browser/browser_adapter.ts b/modules/@angular/platform-browser/src/browser/browser_adapter.ts index ad8a3f46b2..ad25ace62f 100644 --- a/modules/@angular/platform-browser/src/browser/browser_adapter.ts +++ b/modules/@angular/platform-browser/src/browser/browser_adapter.ts @@ -443,13 +443,14 @@ function relativePath(url: any /** TODO #9100 */): string { '/' + urlParsingNode.pathname; } -export function parseCookieValue(cookie: string, name: string): string { +export function parseCookieValue(cookieStr: string, name: string): string { name = encodeURIComponent(name); - let cookies = cookie.split(';'); - for (let cookie of cookies) { - let [key, value] = cookie.split('=', 2); - if (key.trim() === name) { - return decodeURIComponent(value); + for (const cookie of cookieStr.split(';')) { + const eqIndex = cookie.indexOf('='); + const [cookieName, cookieValue]: string[] = + eqIndex == -1 ? [cookie, ''] : [cookie.slice(0, eqIndex), cookie.slice(eqIndex + 1)]; + if (cookieName.trim() === name) { + return decodeURIComponent(cookieValue); } } return null;