From ec14c88ecc2807c4a4e3b7c506098ddf9eda9ead Mon Sep 17 00:00:00 2001 From: sis0k0 Date: Tue, 16 May 2017 19:56:32 +0300 Subject: [PATCH] fix(renderer): stop performing value conversions These conversions are now handled by core modules. The conversions performed in the renderer and value accessors are no longer needed. fixes #799 --- nativescript-angular/common/utils.ts | 16 -------- nativescript-angular/directives/tab-view.ts | 3 +- nativescript-angular/lang-facade.ts | 4 -- .../value-accessors/checked-value-accessor.ts | 11 +---- .../value-accessors/date-value-accessor.ts | 15 +------ .../value-accessors/number-value-accessor.ts | 14 +------ .../selectedIndex-value-accessor.ts | 9 ++--- .../value-accessors/text-value-accessor.ts | 4 +- .../value-accessors/time-value-accessor.ts | 14 +------ nativescript-angular/view-util.ts | 40 ++++++++----------- tests/app/tests/property-sets.ts | 14 ++++--- tests/app/tests/value-accessor-tests.ts | 32 +++++---------- tests/package.json | 3 +- tests/references.d.ts | 1 - 14 files changed, 48 insertions(+), 132 deletions(-) delete mode 100644 nativescript-angular/common/utils.ts delete mode 100644 tests/references.d.ts diff --git a/nativescript-angular/common/utils.ts b/nativescript-angular/common/utils.ts deleted file mode 100644 index 9e905b5f7..000000000 --- a/nativescript-angular/common/utils.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { isBlank, isNumber } from "../lang-facade"; - -export function convertToInt(value): number { - let normalizedValue; - if (isBlank(value)) { - normalizedValue = 0; - } else { - if (isNumber(value)) { - normalizedValue = value; - } else { - let parsedValue = parseInt(value.toString(), 10); - normalizedValue = isNaN(parsedValue) ? 0 : parsedValue; - } - } - return Math.round(normalizedValue); -} diff --git a/nativescript-angular/directives/tab-view.ts b/nativescript-angular/directives/tab-view.ts index 984dc0076..4a630a716 100644 --- a/nativescript-angular/directives/tab-view.ts +++ b/nativescript-angular/directives/tab-view.ts @@ -10,7 +10,6 @@ import { import { TabView, TabViewItem } from "tns-core-modules/ui/tab-view"; import { CommentNode } from "../element-types"; -import { convertToInt } from "../common/utils"; import { rendererLog } from "../trace"; import { isBlank } from "../lang-facade"; @@ -28,7 +27,7 @@ export class TabViewDirective implements AfterViewInit { } set selectedIndex(value) { - this._selectedIndex = convertToInt(value); + this._selectedIndex = value; if (this.viewInitialized) { this.tabView.selectedIndex = this._selectedIndex; } diff --git a/nativescript-angular/lang-facade.ts b/nativescript-angular/lang-facade.ts index 89fa86a90..424b1c64a 100644 --- a/nativescript-angular/lang-facade.ts +++ b/nativescript-angular/lang-facade.ts @@ -11,10 +11,6 @@ export function isBlank(obj: any): boolean { return obj === undefined || obj === null; } -export function isNumber(obj: any): boolean { - return typeof obj === 'number'; -} - export function isDate(obj: any): obj is Date { return obj instanceof Date && !isNaN(obj.valueOf()); } diff --git a/nativescript-angular/value-accessors/checked-value-accessor.ts b/nativescript-angular/value-accessors/checked-value-accessor.ts index 584e5f6b3..9b4237bcd 100644 --- a/nativescript-angular/value-accessors/checked-value-accessor.ts +++ b/nativescript-angular/value-accessors/checked-value-accessor.ts @@ -1,6 +1,5 @@ import { Directive, ElementRef, forwardRef, HostListener } from "@angular/core"; import { NG_VALUE_ACCESSOR } from "@angular/forms"; -import { isBlank } from "../lang-facade"; import { BaseValueAccessor } from "./base-value-accessor"; import { Switch } from "tns-core-modules/ui/switch"; @@ -34,15 +33,7 @@ export class CheckedValueAccessor extends BaseValueAccessor { // tslint: } writeValue(value: any): void { - let normalizedValue = false; - if (!isBlank(value)) { - if (typeof value === "string") { - normalizedValue = value.toLowerCase() === "true" ? true : false; - } else { - normalizedValue = !!value; - } - } - this.view.checked = normalizedValue; + this.view.checked = value; } registerOnTouched(fn: () => void): void { this.onTouched = fn; } diff --git a/nativescript-angular/value-accessors/date-value-accessor.ts b/nativescript-angular/value-accessors/date-value-accessor.ts index 659549ca8..66e312d68 100644 --- a/nativescript-angular/value-accessors/date-value-accessor.ts +++ b/nativescript-angular/value-accessors/date-value-accessor.ts @@ -1,6 +1,5 @@ import { Directive, ElementRef, forwardRef, HostListener } from "@angular/core"; import { NG_VALUE_ACCESSOR } from "@angular/forms"; -import { isBlank, isDate } from "../lang-facade"; import { BaseValueAccessor } from "./base-value-accessor"; import { DatePicker } from "tns-core-modules/ui/date-picker"; @@ -34,19 +33,7 @@ export class DateValueAccessor extends BaseValueAccessor { // tslint } writeValue(value: any): void { - let normalizedValue = isBlank(value) ? new Date() : value; - if (!isDate(normalizedValue)) { - if (typeof normalizedValue === "string") { - normalizedValue = new Date(normalizedValue); - } else if (typeof normalizedValue === "number") { - normalizedValue = new Date(normalizedValue); - } - - if (!isDate(normalizedValue)) { - normalizedValue = new Date(); - } - } - this.view.date = normalizedValue; + this.view.date = value; } registerOnTouched(fn: () => void): void { this.onTouched = fn; } diff --git a/nativescript-angular/value-accessors/number-value-accessor.ts b/nativescript-angular/value-accessors/number-value-accessor.ts index b34ec8646..28a528585 100644 --- a/nativescript-angular/value-accessors/number-value-accessor.ts +++ b/nativescript-angular/value-accessors/number-value-accessor.ts @@ -1,6 +1,5 @@ import { Directive, ElementRef, forwardRef, HostListener } from "@angular/core"; import { NG_VALUE_ACCESSOR } from "@angular/forms"; -import { isBlank, isNumber } from "../lang-facade"; import { BaseValueAccessor } from "./base-value-accessor"; import { Slider } from "tns-core-modules/ui/slider"; @@ -34,18 +33,7 @@ export class NumberValueAccessor extends BaseValueAccessor { // tslint:d } writeValue(value: any): void { - let normalizedValue; - if (isBlank(value)) { - normalizedValue = 0; - } else { - if (isNumber(value)) { - normalizedValue = value; - } else { - let parsedValue = Number(value); - normalizedValue = isNaN(parsedValue) ? 0 : parsedValue; - } - } - this.view.value = normalizedValue; + this.view.value = value; } registerOnTouched(fn: () => void): void { this.onTouched = fn; } diff --git a/nativescript-angular/value-accessors/selectedIndex-value-accessor.ts b/nativescript-angular/value-accessors/selectedIndex-value-accessor.ts index 2466ea3c5..521ecbc83 100644 --- a/nativescript-angular/value-accessors/selectedIndex-value-accessor.ts +++ b/nativescript-angular/value-accessors/selectedIndex-value-accessor.ts @@ -2,7 +2,6 @@ import { Directive, ElementRef, forwardRef, AfterViewInit, HostListener } from " import { NG_VALUE_ACCESSOR } from "@angular/forms"; import { BaseValueAccessor } from "./base-value-accessor"; import { View } from "tns-core-modules/ui/core/view"; -import { convertToInt } from "../common/utils"; const SELECTED_INDEX_VALUE_ACCESSOR = {provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SelectedIndexValueAccessor), multi: true}; @@ -35,19 +34,19 @@ export class SelectedIndexValueAccessor extends BaseValueAccessor void): void { this.onTouched = fn; } diff --git a/nativescript-angular/value-accessors/text-value-accessor.ts b/nativescript-angular/value-accessors/text-value-accessor.ts index ecbb97be9..17fb0e845 100644 --- a/nativescript-angular/value-accessors/text-value-accessor.ts +++ b/nativescript-angular/value-accessors/text-value-accessor.ts @@ -1,6 +1,5 @@ import { Directive, ElementRef, forwardRef, HostListener } from "@angular/core"; import { NG_VALUE_ACCESSOR } from "@angular/forms"; -import { isBlank } from "../lang-facade"; import { BaseValueAccessor } from "./base-value-accessor"; import { View } from "tns-core-modules/ui/core/view"; @@ -36,8 +35,7 @@ export class TextValueAccessor extends BaseValueAccessor { // tslint:d } writeValue(value: any): void { - let normalizedValue = isBlank(value) ? "" : value.toString(); - this.view.text = normalizedValue; + this.view.text = value; } registerOnTouched(fn: () => void): void { this.onTouched = fn; } diff --git a/nativescript-angular/value-accessors/time-value-accessor.ts b/nativescript-angular/value-accessors/time-value-accessor.ts index 7563c3ba6..1e6cde347 100644 --- a/nativescript-angular/value-accessors/time-value-accessor.ts +++ b/nativescript-angular/value-accessors/time-value-accessor.ts @@ -1,6 +1,5 @@ import { Directive, ElementRef, forwardRef, HostListener } from "@angular/core"; import { NG_VALUE_ACCESSOR } from "@angular/forms"; -import { isBlank, isDate } from "../lang-facade"; import { BaseValueAccessor } from "./base-value-accessor"; import { TimePicker } from "tns-core-modules/ui/time-picker"; @@ -34,18 +33,7 @@ export class TimeValueAccessor extends BaseValueAccessor { // tslint } writeValue(value: any): void { - let normalizedValue = isBlank(value) ? new Date() : value; - if (!isDate(normalizedValue)) { - if (typeof normalizedValue === "string") { - normalizedValue = new Date(normalizedValue); - } else if (typeof normalizedValue === "number") { - normalizedValue = new Date(normalizedValue); - } - if (!isDate(normalizedValue)) { - normalizedValue = new Date(); - } - } - this.view.time = normalizedValue; + this.view.time = value; } registerOnTouched(fn: () => void): void { this.onTouched = fn; } diff --git a/nativescript-angular/view-util.ts b/nativescript-angular/view-util.ts index f0b9cc73a..c57b390ca 100644 --- a/nativescript-angular/view-util.ts +++ b/nativescript-angular/view-util.ts @@ -207,41 +207,32 @@ export class ViewUtil { private setPropertyInternal(view: NgView, attributeName: string, value: any): void { - traceLog("Setting attribute: " + attributeName); - - let propMap = this.getProperties(view); + traceLog(`Setting attribute: ${attributeName}=${value} to ${view}`); if (attributeName === "class") { this.setClasses(view, value); - } else if (XML_ATTRIBUTES.indexOf(attributeName) !== -1) { - view._applyXmlAttribute(attributeName, value); - } else if (propMap.has(attributeName)) { - // We have a lower-upper case mapped property. - let propertyName = propMap.get(attributeName); - view[propertyName] = this.convertValue(value); - } else { - // Unknown attribute value -- just set it to our object as is. - view[attributeName] = this.convertValue(value); + return; } - } - private convertValue(value: any): any { - if (typeof (value) !== "string" || value === "") { - return value; + if (XML_ATTRIBUTES.indexOf(attributeName) !== -1) { + view._applyXmlAttribute(attributeName, value); + return; } - let valueAsNumber = +value; - if (!isNaN(valueAsNumber)) { - return valueAsNumber; - } else if (value && (value.toLowerCase() === "true" || value.toLowerCase() === "false")) { - return value.toLowerCase() === "true" ? true : false; - } else { - return value; + const propMap = this.getProperties(view); + const propertyName = propMap.get(attributeName); + if (propertyName) { + // We have a lower-upper case mapped property. + view[propertyName] = value; + return; } + + // Unknown attribute value -- just set it to our object as is. + view[attributeName] = value; } private getProperties(instance: any): Map { - let type = instance && instance.constructor; + const type = instance && instance.constructor; if (!type) { return new Map(); } @@ -253,6 +244,7 @@ export class ViewUtil { } propertyMaps.set(type, propMap); } + return propertyMaps.get(type); } diff --git a/tests/app/tests/property-sets.ts b/tests/app/tests/property-sets.ts index 3cb2ca29d..547dd9962 100644 --- a/tests/app/tests/property-sets.ts +++ b/tests/app/tests/property-sets.ts @@ -36,20 +36,24 @@ describe("setting View properties", () => { assert.equal("blah", view.stringValue); }); - it("converts number values", () => { + it("doesn\'t convert number values", () => { let view = new TestView(); viewUtil.setProperty(view, "numValue", "42"); - assert.strictEqual(42, view.numValue); + assert.strictEqual("42", view.numValue); + + viewUtil.setProperty(view, "numValue", "42."); + assert.strictEqual("42.", view.numValue); + viewUtil.setProperty(view, "numValue", 0); assert.strictEqual(0, view.numValue); }); - it("converts boolean values", () => { + it("doesn\'t convert boolean values", () => { let view = new TestView(); viewUtil.setProperty(view, "boolValue", "true"); - assert.strictEqual(true, view.boolValue); + assert.strictEqual("true", view.boolValue); viewUtil.setProperty(view, "boolValue", "false"); - assert.strictEqual(false, view.boolValue); + assert.strictEqual("false", view.boolValue); }); it("sets style values", () => { diff --git a/tests/app/tests/value-accessor-tests.ts b/tests/app/tests/value-accessor-tests.ts index 0f55fcba2..c1d6c53fc 100644 --- a/tests/app/tests/value-accessor-tests.ts +++ b/tests/app/tests/value-accessor-tests.ts @@ -78,20 +78,19 @@ describe("two-way binding via ng-model", () => { assert.strictEqual(42, accessor.view.value); accessor.writeValue("blah"); - assert.strictEqual(0, accessor.view.value, "default to 0 on parse errors"); + assert.notEqual(accessor.view.value, accessor.view.value, "defaults to NaN on parse errors"); }); it("converts strings to bools", () => { const accessor = new TestCheckedValueAccessor(); accessor.writeValue(null); - assert.strictEqual(false, accessor.view.checked, "default to false on empty"); + assert.strictEqual(null, accessor.view.checked, "default to null on empty"); accessor.writeValue("true"); assert.strictEqual(true, accessor.view.checked); - accessor.writeValue("blah"); - assert.strictEqual(false, accessor.view.checked, "default to false on parse errors"); + assert.throws(() => accessor.writeValue("blah")); }); it("converts strings to dates", () => { @@ -99,13 +98,10 @@ describe("two-way binding via ng-model", () => { const accessor = new TestDateValueAccessor(); accessor.writeValue(null); - assert.equal(formatDate(now), formatDate(accessor.view.date), "default to now on empty"); + assert.equal(null, accessor.view.date, "default to null on empty"); accessor.writeValue("2010-03-17"); assert.equal(formatDate(new Date(2010, 2, 17)), formatDate(accessor.view.date)); - - accessor.writeValue("a fortnight ago"); - assert.equal(formatDate(now), formatDate(accessor.view.date), "default to now on parse error"); }); it("converts strings to int selection", () => { @@ -113,7 +109,7 @@ describe("two-way binding via ng-model", () => { accessor.writeValue(null); accessor.ngAfterViewInit(); - assert.strictEqual(0, accessor.view.selectedIndex, "default to 0 on empty"); + assert.strictEqual(null, accessor.view.selectedIndex, "default to null on empty"); accessor.writeValue("3"); accessor.ngAfterViewInit(); @@ -121,29 +117,23 @@ describe("two-way binding via ng-model", () => { accessor.writeValue("blah"); accessor.ngAfterViewInit(); - assert.strictEqual(0, accessor.view.selectedIndex, "default to 0 on parse errors"); + assert.notEqual(accessor.view.selectedIndex, accessor.view.selectedIndex, + "default to NaN on parse errors"); }); it("converts strings to times", () => { - const now = new Date(); const accessor = new TestTimeValueAccessor(); - accessor.writeValue(null); - assert.equal(formatTime(now), formatTime(accessor.view.time), "default to now on empty"); - - accessor.writeValue("2010/03/17 12:54"); - assert.equal(formatTime(new Date(2010, 2, 17, 12, 54)), formatTime(accessor.view.time)); - - accessor.writeValue("three hours from now"); - assert.equal(formatTime(now), formatTime(accessor.view.time), "default to now on parse error"); + assert.throws(() => accessor.writeValue(null)); + assert.throws(() => accessor.writeValue("2010/03/17 12:54")); + assert.throws(() => accessor.writeValue("three hours from now")); }); it("converts values to text", () => { - const now = new Date(); const accessor = new TestTextValueAccessor(); accessor.writeValue(null); - assert.equal("", accessor.view.text); + assert.equal(null, accessor.view.text, "defaults to null on empty"); accessor.writeValue("blah"); assert.equal("blah", accessor.view.text); diff --git a/tests/package.json b/tests/package.json index a17e12135..1f6aa354c 100644 --- a/tests/package.json +++ b/tests/package.json @@ -69,6 +69,7 @@ "appium-android": "tns build android && npm run run-appium-android", "run-appium-android": "nativescript-dev-appium android", "appium-ios-simulator": "tns build ios && nativescript-dev-appium ios-simulator", - "tslint": "tslint --project tsconfig.json --config tslint.json" + "tslint": "tslint --project tsconfig.json --config tslint.json", + "appium": "nativescript-dev-appium" } } diff --git a/tests/references.d.ts b/tests/references.d.ts deleted file mode 100644 index b14f3837d..000000000 --- a/tests/references.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// Needed for autocompletion and compilation. \ No newline at end of file