Skip to content

Commit d26f8b4

Browse files
committed
Expose Socket from deno polyfill as class
1 parent 4265251 commit d26f8b4

File tree

1 file changed

+135
-127
lines changed

1 file changed

+135
-127
lines changed

deno/polyfills.js

Lines changed: 135 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,140 @@ import { isIP } from 'https://deno.land/std@0.132.0/node/net.ts'
55

66
const events = () => ({ data: [], error: [], drain: [], connect: [], secureConnect: [], close: [] })
77

8+
class Socket {
9+
constructor() {
10+
return createSocket()
11+
}
12+
}
13+
14+
function createSocket() {
15+
let paused
16+
, resume
17+
, keepAlive
18+
19+
const socket = {
20+
error,
21+
success,
22+
readyState: 'open',
23+
setKeepAlive: x => {
24+
keepAlive = x
25+
socket.raw && socket.raw.setKeepAlive && socket.raw.setKeepAlive(x)
26+
},
27+
connect: (port, hostname) => {
28+
socket.raw = null
29+
socket.readyState = 'connecting'
30+
typeof port === 'string'
31+
? Deno.connect({ transport: 'unix', path: socket.path = port }).then(success, error)
32+
: Deno.connect({ transport: 'tcp', port: socket.port = port, hostname: socket.hostname = hostname || 'localhost' }).then(success, error) // eslint-disable-line
33+
return socket
34+
},
35+
pause: () => {
36+
paused = new Promise(r => resume = r)
37+
},
38+
resume: () => {
39+
resume && resume()
40+
paused = null
41+
},
42+
isPaused: () => !!paused,
43+
removeAllListeners: () => socket.events = events(),
44+
events: events(),
45+
raw: null,
46+
on: (x, fn) => socket.events[x].push(fn),
47+
once: (x, fn) => {
48+
if (x === 'data')
49+
socket.break = true
50+
const e = socket.events[x]
51+
e.push(once)
52+
once.once = fn
53+
function once(...args) {
54+
fn(...args)
55+
e.indexOf(once) > -1 && e.splice(e.indexOf(once), 1)
56+
}
57+
},
58+
removeListener: (x, fn) => {
59+
socket.events[x] = socket.events[x].filter(x => x !== fn && x.once !== fn)
60+
},
61+
write: (x, cb) => {
62+
socket.raw.write(x).then(l => {
63+
l < x.length
64+
? socket.write(x.slice(l), cb)
65+
: (cb && cb(null))
66+
}).catch(err => {
67+
cb && cb()
68+
call(socket.events.error, err)
69+
})
70+
return false
71+
},
72+
destroy: () => close(),
73+
end: (x) => {
74+
x && socket.write(x)
75+
close()
76+
}
77+
}
78+
79+
return socket
80+
81+
async function success(raw) {
82+
if (socket.readyState !== 'connecting')
83+
return raw.close()
84+
85+
const encrypted = socket.encrypted
86+
socket.raw = raw
87+
keepAlive != null && raw.setKeepAlive && raw.setKeepAlive(keepAlive)
88+
socket.readyState = 'open'
89+
socket.encrypted
90+
? call(socket.events.secureConnect)
91+
: call(socket.events.connect)
92+
93+
const b = new Uint8Array(1024)
94+
let result
95+
96+
try {
97+
while ((result = socket.readyState === 'open' && await raw.read(b))) {
98+
call(socket.events.data, Buffer.from(b.subarray(0, result)))
99+
if (!encrypted && socket.break && (socket.break = false, b[0] === 83))
100+
return socket.break = false
101+
paused && await paused
102+
}
103+
} catch (e) {
104+
if (e instanceof Deno.errors.BadResource === false)
105+
error(e)
106+
}
107+
108+
if (!socket.encrypted || encrypted)
109+
closed()
110+
}
111+
112+
function close() {
113+
try {
114+
socket.raw && socket.raw.close()
115+
} catch (e) {
116+
if (e instanceof Deno.errors.BadResource === false)
117+
call(socket.events.error, e)
118+
}
119+
}
120+
121+
function closed() {
122+
if (socket.readyState === 'closed')
123+
return
124+
125+
socket.break = socket.encrypted = false
126+
socket.readyState = 'closed'
127+
call(socket.events.close)
128+
}
129+
130+
function error(err) {
131+
call(socket.events.error, err)
132+
socket.raw
133+
? close()
134+
: closed()
135+
}
136+
137+
function call(xs, x) {
138+
xs.slice().forEach(fn => fn(x))
139+
}
140+
}
141+
8142
export const net = {
9143
isIP,
10144
createServer() {
@@ -23,133 +157,7 @@ export const net = {
23157
}
24158
return server
25159
},
26-
Socket() {
27-
let paused
28-
, resume
29-
, keepAlive
30-
31-
const socket = {
32-
error,
33-
success,
34-
readyState: 'open',
35-
setKeepAlive: x => {
36-
keepAlive = x
37-
socket.raw && socket.raw.setKeepAlive && socket.raw.setKeepAlive(x)
38-
},
39-
connect: (port, hostname) => {
40-
socket.raw = null
41-
socket.readyState = 'connecting'
42-
typeof port === 'string'
43-
? Deno.connect({ transport: 'unix', path: socket.path = port }).then(success, error)
44-
: Deno.connect({ transport: 'tcp', port: socket.port = port, hostname: socket.hostname = hostname || 'localhost' }).then(success, error) // eslint-disable-line
45-
return socket
46-
},
47-
pause: () => {
48-
paused = new Promise(r => resume = r)
49-
},
50-
resume: () => {
51-
resume && resume()
52-
paused = null
53-
},
54-
isPaused: () => !!paused,
55-
removeAllListeners: () => socket.events = events(),
56-
events: events(),
57-
raw: null,
58-
on: (x, fn) => socket.events[x].push(fn),
59-
once: (x, fn) => {
60-
if (x === 'data')
61-
socket.break = true
62-
const e = socket.events[x]
63-
e.push(once)
64-
once.once = fn
65-
function once(...args) {
66-
fn(...args)
67-
e.indexOf(once) > -1 && e.splice(e.indexOf(once), 1)
68-
}
69-
},
70-
removeListener: (x, fn) => {
71-
socket.events[x] = socket.events[x].filter(x => x !== fn && x.once !== fn)
72-
},
73-
write: (x, cb) => {
74-
socket.raw.write(x).then(l => {
75-
l < x.length
76-
? socket.write(x.slice(l), cb)
77-
: (cb && cb(null))
78-
}).catch(err => {
79-
cb && cb()
80-
call(socket.events.error, err)
81-
})
82-
return false
83-
},
84-
destroy: () => close(),
85-
end: (x) => {
86-
x && socket.write(x)
87-
close()
88-
}
89-
}
90-
91-
return socket
92-
93-
async function success(raw) {
94-
if (socket.readyState !== 'connecting')
95-
return raw.close()
96-
97-
const encrypted = socket.encrypted
98-
socket.raw = raw
99-
keepAlive != null && raw.setKeepAlive && raw.setKeepAlive(keepAlive)
100-
socket.readyState = 'open'
101-
socket.encrypted
102-
? call(socket.events.secureConnect)
103-
: call(socket.events.connect)
104-
105-
const b = new Uint8Array(1024)
106-
let result
107-
108-
try {
109-
while ((result = socket.readyState === 'open' && await raw.read(b))) {
110-
call(socket.events.data, Buffer.from(b.subarray(0, result)))
111-
if (!encrypted && socket.break && (socket.break = false, b[0] === 83))
112-
return socket.break = false
113-
paused && await paused
114-
}
115-
} catch (e) {
116-
if (e instanceof Deno.errors.BadResource === false)
117-
error(e)
118-
}
119-
120-
if (!socket.encrypted || encrypted)
121-
closed()
122-
}
123-
124-
function close() {
125-
try {
126-
socket.raw && socket.raw.close()
127-
} catch (e) {
128-
if (e instanceof Deno.errors.BadResource === false)
129-
call(socket.events.error, e)
130-
}
131-
}
132-
133-
function closed() {
134-
if (socket.readyState === 'closed')
135-
return
136-
137-
socket.break = socket.encrypted = false
138-
socket.readyState = 'closed'
139-
call(socket.events.close)
140-
}
141-
142-
function error(err) {
143-
call(socket.events.error, err)
144-
socket.raw
145-
? close()
146-
: closed()
147-
}
148-
149-
function call(xs, x) {
150-
xs.slice().forEach(fn => fn(x))
151-
}
152-
}
160+
Socket
153161
}
154162

155163
export const tls = {

0 commit comments

Comments
 (0)