@@ -10,6 +10,7 @@ const {
10
10
RegExpPrototypeExec,
11
11
RegExpPrototypeSymbolReplace,
12
12
ObjectCreate,
13
+ Symbol,
13
14
} = primordials ;
14
15
15
16
const errors = require ( 'internal/errors' ) ;
@@ -35,6 +36,12 @@ const {
35
36
ERR_INVALID_IP_ADDRESS ,
36
37
} = errors . codes ;
37
38
39
+ const {
40
+ addSerializeCallback,
41
+ addDeserializeCallback,
42
+ isBuildingSnapshot,
43
+ } = require ( 'v8' ) . startupSnapshot ;
44
+
38
45
function validateTimeout ( options ) {
39
46
const { timeout = - 1 } = { ...options } ;
40
47
validateInt32 ( timeout , 'options.timeout' , - 1 ) ;
@@ -47,12 +54,27 @@ function validateTries(options) {
47
54
return tries ;
48
55
}
49
56
57
+ const kSerializeResolver = Symbol ( 'dns:resolver:serialize' ) ;
58
+ const kDeserializeResolver = Symbol ( 'dns:resolver:deserialize' ) ;
59
+ const kSnapshotStates = Symbol ( 'dns:resolver:config' ) ;
60
+ const kInitializeHandle = Symbol ( 'dns:resolver:initializeHandle' ) ;
61
+ const kSetServersInteral = Symbol ( 'dns:resolver:setServers' ) ;
62
+
50
63
// Resolver instances correspond 1:1 to c-ares channels.
51
64
52
65
class ResolverBase {
53
66
constructor ( options = undefined ) {
54
67
const timeout = validateTimeout ( options ) ;
55
68
const tries = validateTries ( options ) ;
69
+ // If we are building snapshot, save the states of the resolver along
70
+ // the way.
71
+ if ( isBuildingSnapshot ( ) ) {
72
+ this [ kSnapshotStates ] = { timeout, tries } ;
73
+ }
74
+ this [ kInitializeHandle ] ( timeout , tries ) ;
75
+ }
76
+
77
+ [ kInitializeHandle ] ( timeout , tries ) {
56
78
const { ChannelWrap } = lazyBinding ( ) ;
57
79
this . _handle = new ChannelWrap ( timeout , tries ) ;
58
80
}
@@ -77,9 +99,7 @@ class ResolverBase {
77
99
// Cache the original servers because in the event of an error while
78
100
// setting the servers, c-ares won't have any servers available for
79
101
// resolution.
80
- const orig = this . _handle . getServers ( ) || [ ] ;
81
102
const newSet = [ ] ;
82
-
83
103
ArrayPrototypeForEach ( servers , ( serv , index ) => {
84
104
validateString ( serv , `servers[${ index } ]` ) ;
85
105
let ipVersion = isIP ( serv ) ;
@@ -118,6 +138,11 @@ class ResolverBase {
118
138
throw new ERR_INVALID_IP_ADDRESS ( serv ) ;
119
139
} ) ;
120
140
141
+ this [ kSetServersInteral ] ( newSet , servers ) ;
142
+ }
143
+
144
+ [ kSetServersInteral ] ( newSet , servers ) {
145
+ const orig = this . _handle . getServers ( ) || [ ] ;
121
146
const errorNumber = this . _handle . setServers ( newSet ) ;
122
147
123
148
if ( errorNumber !== 0 ) {
@@ -127,8 +152,13 @@ class ResolverBase {
127
152
const err = strerror ( errorNumber ) ;
128
153
throw new ERR_DNS_SET_SERVERS_FAILED ( err , servers ) ;
129
154
}
155
+
156
+ if ( isBuildingSnapshot ( ) ) {
157
+ this [ kSnapshotStates ] . servers = newSet ;
158
+ }
130
159
}
131
160
161
+
132
162
setLocalAddress ( ipv4 , ipv6 ) {
133
163
validateString ( ipv4 , 'ipv4' ) ;
134
164
@@ -137,6 +167,31 @@ class ResolverBase {
137
167
}
138
168
139
169
this . _handle . setLocalAddress ( ipv4 , ipv6 ) ;
170
+
171
+ if ( isBuildingSnapshot ( ) ) {
172
+ this [ kSnapshotStates ] . localAddress = { ipv4, ipv6 } ;
173
+ }
174
+ }
175
+
176
+ // TODO(joyeecheung): consider exposing this if custom DNS resolvers
177
+ // end up being useful for snapshot users.
178
+ [ kSerializeResolver ] ( ) {
179
+ this . _handle = null ; // We'll restore it during deserialization.
180
+ addDeserializeCallback ( function deserializeResolver ( resolver ) {
181
+ resolver [ kDeserializeResolver ] ( ) ;
182
+ } , this ) ;
183
+ }
184
+
185
+ [ kDeserializeResolver ] ( ) {
186
+ const { timeout, tries, localAddress, servers } = this [ kSnapshotStates ] ;
187
+ this [ kInitializeHandle ] ( timeout , tries ) ;
188
+ if ( localAddress ) {
189
+ const { ipv4, ipv6 } = localAddress ;
190
+ this . _handle . setLocalAddress ( ipv4 , ipv6 ) ;
191
+ }
192
+ if ( servers ) {
193
+ this [ kSetServersInteral ] ( servers , servers ) ;
194
+ }
140
195
}
141
196
}
142
197
@@ -151,6 +206,14 @@ function initializeDns() {
151
206
// Allow the deserialized application to override order from CLI.
152
207
dnsOrder = orderFromCLI ;
153
208
}
209
+
210
+ if ( ! isBuildingSnapshot ( ) ) {
211
+ return ;
212
+ }
213
+
214
+ addSerializeCallback ( ( ) => {
215
+ defaultResolver ?. [ kSerializeResolver ] ( ) ;
216
+ } ) ;
154
217
}
155
218
156
219
const resolverKeys = [
0 commit comments