diff --git a/modules/di/src/exceptions.js b/modules/di/src/exceptions.js index 866356e710..15a971dc6d 100644 --- a/modules/di/src/exceptions.js +++ b/modules/di/src/exceptions.js @@ -12,6 +12,8 @@ function constructResolvingPath(keys:List) { } } +export class KeyMetadataError extends Error {} + export class ProviderError extends Error { constructor(key:Key, constructResolvingMessage:Function) { this.keys = [key]; diff --git a/modules/di/src/injector.js b/modules/di/src/injector.js index e99b797e79..a20a184189 100644 --- a/modules/di/src/injector.js +++ b/modules/di/src/injector.js @@ -44,13 +44,13 @@ export class Injector { _createListOfBindings(flattenBindings):List { - var bindings = ListWrapper.createFixedSize(Key.numberOfKeys() + 1); + var bindings = ListWrapper.createFixedSize(Key.numberOfKeys + 1); MapWrapper.forEach(flattenBindings, (v, keyId) => bindings[keyId] = v); return bindings; } _createInstances():List { - return ListWrapper.createFixedSize(Key.numberOfKeys() + 1); + return ListWrapper.createFixedSize(Key.numberOfKeys + 1); } _getByKey(key:Key, returnPromise:boolean, returnLazy:boolean) { diff --git a/modules/di/src/key.js b/modules/di/src/key.js index a69087a73a..057c7be54d 100644 --- a/modules/di/src/key.js +++ b/modules/di/src/key.js @@ -1,30 +1,44 @@ +import {KeyMetadataError} from './exceptions'; import {MapWrapper, Map} from 'facade/collection'; import {FIELD, int, isPresent} from 'facade/lang'; var _allKeys = MapWrapper.create(); -var _id:int = 0; export class Key { @FIELD('final token') @FIELD('final id:int') + @FIELD('metadata:Object') constructor(token, id:int) { this.token = token; this.id = id; + this.metadata = null; } - static get(token) { + static get(token):Key { if (token instanceof Key) return token; if (MapWrapper.contains(_allKeys, token)) { return MapWrapper.get(_allKeys, token); } - var newKey = new Key(token, ++_id); + var newKey = new Key(token, Key.numberOfKeys); MapWrapper.set(_allKeys, token, newKey); return newKey; } - static numberOfKeys() { - return _id; + static setMetadata(key:Key, metadata):Key { + if (isPresent(key.metadata) && key.metadata !== metadata) { + throw new KeyMetadataError(); + } + key.metadata = metadata; + return key; + } + + static clear() { + _allKeys = MapWrapper.create(); + } + + static get numberOfKeys():int { + return MapWrapper.size(_allKeys); } } diff --git a/modules/di/test/di/key_spec.js b/modules/di/test/di/key_spec.js index cebf492131..34eed487f4 100644 --- a/modules/di/test/di/key_spec.js +++ b/modules/di/test/di/key_spec.js @@ -1,8 +1,12 @@ -import {describe, it, expect} from 'test_lib/test_lib'; +import {describe, it, expect, beforeEach} from 'test_lib/test_lib'; import {Key} from 'di/di'; export function main() { describe("key", function () { + beforeEach(function () { + Key.clear(); + }); + it('should be equal to another key if type is the same', function () { expect(Key.get('car')).toBe(Key.get('car')); }); @@ -14,5 +18,32 @@ export function main() { it('should return the passed in key', function () { expect(Key.get(Key.get('car'))).toBe(Key.get('car')); }); + + describe("metadata", function () { + it("should assign metadata to a key", function () { + var key = Key.get('car'); + + Key.setMetadata(key, "meta"); + + expect(key.metadata).toEqual("meta"); + }); + + it("should allow assigning the same metadata twice", function () { + var key = Key.get('car'); + + Key.setMetadata(key, "meta"); + Key.setMetadata(key, "meta"); + + expect(key.metadata).toEqual("meta"); + }); + + it("should throw when assigning different metadata", function () { + var key = Key.get('car'); + + Key.setMetadata(key, "meta1"); + + expect(() => Key.setMetadata(key, "meta2")).toThrowError(); + }); + }); }); } \ No newline at end of file diff --git a/modules/facade/src/collection.dart b/modules/facade/src/collection.dart index 46f9e31b90..8844b25d2b 100644 --- a/modules/facade/src/collection.dart +++ b/modules/facade/src/collection.dart @@ -11,6 +11,7 @@ class MapWrapper { static forEach(m, fn) { m.forEach((k,v) => fn(v,k)); } + static int size(m) {return m.length;} } class ListWrapper { diff --git a/modules/facade/src/collection.es6 b/modules/facade/src/collection.es6 index 647caa1c05..2195127f10 100644 --- a/modules/facade/src/collection.es6 +++ b/modules/facade/src/collection.es6 @@ -10,6 +10,7 @@ export class MapWrapper { static forEach(m, fn) { m.forEach(fn); } + static size(m) {return m.size;} } diff --git a/modules/test_lib/src/test_lib.dart b/modules/test_lib/src/test_lib.dart index 507e27c89d..2b7d465f66 100644 --- a/modules/test_lib/src/test_lib.dart +++ b/modules/test_lib/src/test_lib.dart @@ -15,7 +15,7 @@ Expect expect(actual, [matcher]) { class Expect extends gns.Expect { Expect(actual) : super(actual); - void toThrowError(message) => this.toThrowWith(message: message); + void toThrowError([message=""]) => this.toThrowWith(message: message); void toBePromise() => _expect(actual is Future, equals(true)); Function get _expect => gns.guinness.matchers.expect; }