1 | 'use strict'
|
2 |
|
3 | var mod$0 = require('./signals');var ACQUIRE = mod$0.ACQUIRE;var RELEASE = mod$0.RELEASE;var DISPOSE = mod$0.DISPOSE;
|
4 | var mod$1 = require('./constants');var CONTAINER_ALIAS = mod$1.CONTAINER_ALIAS;var CONTEXT_ALIAS = mod$1.CONTEXT_ALIAS;var CHILD_ALIAS = mod$1.CHILD_ALIAS;
|
5 | var VALUE = require('./options').VALUE;
|
6 | var mod$2 = require('./utils');var generateMask = mod$2.generateMask;var noop = mod$2.noop;var isEagerSingleton = mod$2.isEagerSingleton;
|
7 | var resolvers = require('./resolvers');
|
8 | var createContext = require('./createContext');
|
9 |
|
10 |
|
11 |
|
12 | function Container(conf, logger, mappings, signalRelease) {
|
13 | var context
|
14 |
|
15 | if (typeof conf !== 'function') {
|
16 | throw new Error('Invalid container creation, missing contribution function')
|
17 | }
|
18 |
|
19 | this.$Container_mappings = mappings || {}
|
20 | this.$Container_resolvers = resolvers
|
21 | this.$Container_logger = logger
|
22 | this.$Container_resolving = {}
|
23 | this.$Container_pending = []
|
24 | this.$Container_children = {}
|
25 | this.$Container_signalRelease = signalRelease || noop
|
26 |
|
27 | this.$Container_bind(CONTAINER_ALIAS, this, VALUE, [])
|
28 | context = this.$Container_context = createContext(this.$Container_bind.bind(this))
|
29 | this.$Container_bind(CONTEXT_ALIAS, context, VALUE, [])
|
30 | conf(context)
|
31 | context.flush()
|
32 | this.$Container_unbind(CONTEXT_ALIAS)
|
33 | }
|
34 |
|
35 | Container.prototype.get=function(alias, transients) {
|
36 | return this.$Container_logger.log(("resolving '" + alias + "'"), function() {
|
37 | if (this.$Container_resolving[alias]) { throw new Error(("Circular dependency detected while resolving '" + alias + "'")) }
|
38 | if (!(alias in this.$Container_mappings)) { throw new Error(("'" + alias + "' is not available. Has it ever been registered?.")) }
|
39 |
|
40 | this.$Container_resolving[alias] = true
|
41 | try {
|
42 | return this.$Container_mappings[alias](ACQUIRE)
|
43 | } catch(err) {
|
44 | err.message = ("Failed while resolving '" + alias + "' due to:\n\t" + err.message)
|
45 | throw err
|
46 | } finally {
|
47 | this.$Container_resolving[alias] = false
|
48 | }
|
49 | }.bind(this))
|
50 | };
|
51 |
|
52 | Container.prototype.using=function(transientsDeps) {
|
53 | return {
|
54 | get: function(alias) {
|
55 | var context = this.$Container_context
|
56 | var dep
|
57 |
|
58 | for (dep in transientsDeps) {
|
59 | context.map(dep).to(transientsDeps[dep]).as(VALUE)
|
60 | }
|
61 | context.flush()
|
62 | this.get(alias)
|
63 | for (dep in transientsDeps) {
|
64 | this.$Container_unbind(dep)
|
65 | }
|
66 | }.bind(this)
|
67 | }
|
68 | };
|
69 |
|
70 | Container.prototype.release=function(alias) {
|
71 | try {
|
72 | this.$Container_mappings[alias](RELEASE)
|
73 | } catch(err) {
|
74 | err.message = ("Failed while releasing '" + alias + "' due to:\n\t" + err.message)
|
75 | throw err
|
76 | }
|
77 | };
|
78 |
|
79 | Container.prototype.createChild=function(conf) {
|
80 | var id = Object.keys(this.$Container_children).length + 1
|
81 | var child = new Container(conf, this.$Container_logger, Object.create(this.$Container_mappings), this.$Container_releaseChild.bind(this, id))
|
82 |
|
83 | this.$Container_children[id] = child
|
84 | return child
|
85 | };
|
86 |
|
87 | Container.prototype.dispose=function() {
|
88 | this.$Container_disposeChildren()
|
89 | this.$Container_disposeInstances()
|
90 | this.$Container_signalRelease()
|
91 | this.$Container_signalRelease = noop
|
92 | };
|
93 |
|
94 | Container.prototype.$Container_disposeChildren=function() {
|
95 | var children = this.$Container_children
|
96 | var id
|
97 |
|
98 | for (id in children) {
|
99 |
|
100 | if (children.hasOwnProperty(id)) {
|
101 | children[id].dispose()
|
102 | this.$Container_releaseChild(id)
|
103 | }
|
104 | }
|
105 | };
|
106 |
|
107 | Container.prototype.$Container_releaseChild=function(id) {
|
108 | delete this.$Container_children[id]
|
109 | };
|
110 |
|
111 | Container.prototype.$Container_disposeInstances=function() {
|
112 | var mappings = this.$Container_mappings
|
113 | var alias
|
114 |
|
115 | for (alias in mappings) {
|
116 |
|
117 | if (mappings.hasOwnProperty(alias)) {
|
118 | try {
|
119 | mappings[alias](DISPOSE)
|
120 | } catch(err) {
|
121 | err.message = ("Failed while disposing '" + alias + "' due to:\n\t" + err.message)
|
122 | throw err
|
123 | }
|
124 | delete mappings[alias]
|
125 | }
|
126 | }
|
127 | };
|
128 |
|
129 | Container.prototype.$Container_bind=function(alias, value, type, deps) {
|
130 | if ( !(type in this.$Container_resolvers) ) {
|
131 | throw new Error('Invalid flags combination. See documentation for valid flags combinations.')
|
132 | }
|
133 | this.$Container_mappings[alias] = this.$Container_resolvers[type].call(null, value, this.$Container_resolve.bind(this, deps), this.$Container_release.bind(this, deps))
|
134 | if (isEagerSingleton(type)) {
|
135 | this.get(alias)
|
136 | }
|
137 | };
|
138 |
|
139 | Container.prototype.$Container_unbind=function(alias) {
|
140 | this.$Container_mappings[alias](DISPOSE)
|
141 | delete this.$Container_mappings[alias]
|
142 | };
|
143 |
|
144 | Container.prototype.$Container_release=function(deps) {
|
145 | return deps.forEach(function(dep) {
|
146 | this.release(dep)
|
147 | }.bind(this))
|
148 | };
|
149 |
|
150 | Container.prototype.$Container_resolve=function(deps) {
|
151 | return deps.map(function(dep) {
|
152 | return this.get(dep)
|
153 | }.bind(this))
|
154 | };
|
155 |
|
156 |
|
157 | module.exports = Container |
\ | No newline at end of file |