forked from MetaMask/post-message-stream
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
75 lines (62 loc) · 1.69 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
const DuplexStream = require('readable-stream').Duplex
const inherits = require('util').inherits
module.exports = PostMessageStream
inherits(PostMessageStream, DuplexStream)
function PostMessageStream (opts) {
DuplexStream.call(this, {
objectMode: true,
})
this._name = opts.name
this._target = opts.target
this._targetWindow = opts.targetWindow || window
this._origin = (opts.targetWindow ? '*' : location.origin)
// initialization flags
this._init = false
this._haveSyn = false
window.addEventListener('message', this._onMessage.bind(this), false)
// send syncorization message
this._write('SYN', null, noop)
this.cork()
}
// private
PostMessageStream.prototype._onMessage = function (event) {
var msg = event.data
// validate message
if (this._origin !== '*' && event.origin !== this._origin) return
if (event.source !== this._targetWindow) return
if (typeof msg !== 'object') return
if (msg.target !== this._name) return
if (!msg.data) return
if (!this._init) {
// listen for handshake
if (msg.data === 'SYN') {
this._haveSyn = true
this._write('ACK', null, noop)
} else if (msg.data === 'ACK') {
this._init = true
if (!this._haveSyn) {
this._write('ACK', null, noop)
}
this.uncork()
}
} else {
// forward message
try {
this.push(msg.data)
} catch (err) {
this.emit('error', err)
}
}
}
// stream plumbing
PostMessageStream.prototype._read = noop
PostMessageStream.prototype._write = function (data, encoding, cb) {
var message = {
target: this._target,
data: data,
}
this._targetWindow.postMessage(message, this._origin)
cb()
}
// util
function noop () {}