Commit 218dd59e9632521763daa53b40550901c8c2dcf0
Merge pull request #118 from primea/unboundPorts
adds more port binding functionalitywanderer authored on 5/29/2017, 5:04:31 PM
GitHub committed on 5/29/2017, 5:04:31 PM
Parent: 1df41b95ebf09568a8c125df38f2bcedfb9ad8b5
Parent: c8d99be502a496e485cae703eed1e18dc149870b
Files changed
exoInterface.js | changed |
portManager.js | changed |
tests/index.js | changed |
exoInterface.js | ||
---|---|---|
@@ -146,10 +146,16 @@ | ||
146 | 146 | /** |
147 | 147 | * creates a new message |
148 | 148 | * @param {*} data |
149 | 149 | */ |
150 | - createMessage (data) { | |
151 | - return new Message(data) | |
150 | + createMessage (opts) { | |
151 | + const message = new Message(opts) | |
152 | + for (const port of message.ports) { | |
153 | + if (this.ports.isBound(port)) { | |
154 | + throw new Error('message must not contain bound ports') | |
155 | + } | |
156 | + } | |
157 | + return message | |
152 | 158 | } |
153 | 159 | |
154 | 160 | /** |
155 | 161 | * sends a message to a given port |
portManager.js | ||
---|---|---|
@@ -40,8 +40,9 @@ | ||
40 | 40 | */ |
41 | 41 | constructor (opts) { |
42 | 42 | Object.assign(this, opts) |
43 | 43 | this._portMap = new Map() |
44 | + this._unboundPort = new WeakSet() | |
44 | 45 | } |
45 | 46 | |
46 | 47 | /** |
47 | 48 | * starts the port manager. This fetchs the ports from the state and maps |
@@ -72,39 +73,34 @@ | ||
72 | 73 | * @param {Object} port - the port to bind |
73 | 74 | * @param {String} name - the name of the port |
74 | 75 | */ |
75 | 76 | bind (port, name) { |
77 | + if (this.isBound(port)) { | |
78 | + throw new Error('cannot bind a port that is already bound') | |
79 | + } | |
76 | 80 | // save the port instance |
77 | 81 | this.ports[name] = port |
78 | 82 | this._bindRef(port, name) |
79 | 83 | } |
80 | 84 | |
81 | 85 | /** |
82 | - * queues a message on a port | |
83 | - * @param {Message} message | |
84 | - */ | |
85 | - queue (message) { | |
86 | - this._portMap.get(message.fromPort).queue(message) | |
87 | - } | |
88 | - | |
89 | - /** | |
90 | - * gets a port given it's name | |
86 | + * unbinds a port given its name | |
91 | 87 | * @param {String} name |
92 | - * @return {Object} | |
88 | + * @returns {boolean} whether or not the port was deleted | |
93 | 89 | */ |
94 | - get (name) { | |
95 | - return this.ports[name] | |
90 | + unbind (name) { | |
91 | + const port = this.ports[name] | |
92 | + delete this.ports[name] | |
93 | + this._portMap.delete(port) | |
94 | + return port | |
96 | 95 | } |
97 | 96 | |
98 | 97 | /** |
99 | - * deletes a port given its name | |
100 | - * @param {String} name | |
101 | - * @returns {boolean} whether or not the port was deleted | |
98 | + * get the port name given its referance | |
99 | + * @return {string} | |
102 | 100 | */ |
103 | - delete (name) { | |
104 | - const port = this.ports[name] | |
105 | - delete this.ports[name] | |
106 | - return this._portMap.delete(port) | |
101 | + getBoundName (portRef) { | |
102 | + return this._portMap.get(portRef).name | |
107 | 103 | } |
108 | 104 | |
109 | 105 | /** |
110 | 106 | * check if a port object is still valid |
@@ -114,8 +110,25 @@ | ||
114 | 110 | isBound (port) { |
115 | 111 | return this._portMap.has(port) |
116 | 112 | } |
117 | 113 | |
114 | + /** | |
115 | + * queues a message on a port | |
116 | + * @param {Message} message | |
117 | + */ | |
118 | + queue (message) { | |
119 | + this._portMap.get(message.fromPort).queue(message) | |
120 | + } | |
121 | + | |
122 | + /** | |
123 | + * gets a port given it's name | |
124 | + * @param {String} name | |
125 | + * @return {Object} | |
126 | + */ | |
127 | + get (name) { | |
128 | + return this.ports[name] | |
129 | + } | |
130 | + | |
118 | 131 | _createPortObject (type, link) { |
119 | 132 | const parentId = this.entryPort ? this.entryPort.id : null |
120 | 133 | let nonce = this.state['/'].nonce |
121 | 134 | |
@@ -134,8 +147,9 @@ | ||
134 | 147 | // incerment the nonce |
135 | 148 | nonce = new BN(nonce) |
136 | 149 | nonce.iaddn(1) |
137 | 150 | this.state['/'].nonce = nonce.toArray() |
151 | + this._unboundPort.add(portRef) | |
138 | 152 | return portRef |
139 | 153 | } |
140 | 154 | |
141 | 155 | /** |
tests/index.js | ||
---|---|---|
@@ -234,9 +234,9 @@ | ||
234 | 234 | class Root extends BaseContainer { |
235 | 235 | async run (m) { |
236 | 236 | const port = this.kernel.ports.create('root') |
237 | 237 | this.kernel.ports.bind(port, 'three') |
238 | - this.kernel.ports.delete('three') | |
238 | + this.kernel.ports.unbind('three') | |
239 | 239 | try { |
240 | 240 | await this.kernel.send(port, this.kernel.createMessage()) |
241 | 241 | } catch (e) { |
242 | 242 | t.pass() |
@@ -679,5 +679,35 @@ | ||
679 | 679 | let port2 = root.ports.copy(port) |
680 | 680 | |
681 | 681 | t.equals(port2.type, port.type, 'should copy port type') |
682 | 682 | }) |
683 | + | |
684 | + tape('checking ports', async t => { | |
685 | + t.plan(4) | |
686 | + const hypervisor = new Hypervisor(node.dag) | |
687 | + hypervisor.registerContainer('base', BaseContainer) | |
688 | + | |
689 | + const root = await hypervisor.createInstance('base') | |
690 | + let port = root.ports.create('base') | |
691 | + root.ports.bind(port, 'test') | |
692 | + | |
693 | + t.equals(root.ports.getBoundName(port), 'test', 'should get the ports name') | |
694 | + | |
695 | + try { | |
696 | + root.createMessage({ | |
697 | + ports: [port] | |
698 | + }) | |
699 | + } catch (e) { | |
700 | + t.pass('should thow if sending a port that is bound') | |
701 | + } | |
702 | + | |
703 | + try { | |
704 | + root.ports.bind(port, 'test') | |
705 | + } catch (e) { | |
706 | + t.pass('should thow if binding an already bound port') | |
707 | + } | |
708 | + | |
709 | + root.ports.unbind('test') | |
710 | + const message = root.createMessage({ports: [port]}) | |
711 | + t.equals(message.ports[0], port, 'should create a message if the port is unbound') | |
712 | + }) | |
683 | 713 | }) |
Built with git-ssb-web