333
schangxiang@126.com
2025-09-19 18966e02fb573c7e2bb0c6426ed792b38b910940
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
'use strict';
 
/**
 * Module dependencies.
 */
 
var co = require('co');
var vm = require('vm');
var parse = require('url').parse;
var thunkify = require('thunkify');
var degenerator = require('degenerator');
 
/**
 * Built-in PAC functions.
 */
 
var dateRange = require('./dateRange');
var dnsDomainIs = require('./dnsDomainIs');
var dnsDomainLevels = require('./dnsDomainLevels');
var dnsResolve = require('./dnsResolve');
var isInNet = require('./isInNet');
var isPlainHostName = require('./isPlainHostName');
var isResolvable = require('./isResolvable');
var localHostOrDomainIs = require('./localHostOrDomainIs');
var myIpAddress = require('./myIpAddress');
var shExpMatch = require('./shExpMatch');
var timeRange = require('./timeRange');
var weekdayRange = require('./weekdayRange');
 
/**
 * Module exports.
 */
 
module.exports = generate;
 
/**
 * Returns an asyncronous `FindProxyForURL` function from the
 * given JS string (from a PAC file).
 *
 * @param {String} str JS string
 * @param {Object} opts optional "options" object
 * @return {Function} async resolver function
 */
 
function generate (_str, opts) {
  var i;
  var str = String(_str)
 
  // the sandbox to use for the vm
  var sandbox = {
    dateRange: dateRange,
    dnsDomainIs: dnsDomainIs,
    dnsDomainLevels: dnsDomainLevels,
    dnsResolve: dnsResolve,
    isInNet: isInNet,
    isPlainHostName: isPlainHostName,
    isResolvable: isResolvable,
    localHostOrDomainIs: localHostOrDomainIs,
    myIpAddress: myIpAddress,
    shExpMatch: shExpMatch,
    timeRange: timeRange,
    weekdayRange: weekdayRange
  };
 
  // copy the properties from the user-provided `sandbox` onto ours
  if (opts && opts.sandbox) {
    for (i in opts.sandbox) {
      sandbox[i] = opts.sandbox[i];
    }
  }
 
  // construct the array of async function names to add `yield` calls to.
  // user-provided async functions added to the `sandbox` must have an
  // `async = true` property set on the function instance
  var names = [];
  for (i in sandbox) {
    if (sandbox[i].async) {
      names.push(i);
      sandbox[i] = thunkify(sandbox[i]);
    }
  }
  //console.log(names);
 
  // convert the JS FindProxyForURL function into a generator function
  var js = degenerator(str, names);
 
  // filename of the pac file for the vm
  var filename = (opts && opts.filename) || 'proxy.pac';
 
  // evaluate the JS string and extract the FindProxyForURL generator function
  var fn = vm.runInNewContext(js + ';FindProxyForURL', sandbox, filename);
  if ('function' != typeof fn) {
    throw new TypeError('PAC file JavaScript contents must define a `FindProxyForURL` function');
  }
 
  // return the async resolver function
  var resolver = co.wrap(fn);
 
  return function FindProxyForURL (url, _host, _callback) {
    let host
    let callback
    switch (arguments.length) {
      case 3:
        host = _host
        callback = _callback
        break;
      case 2:
        if (typeof _host === 'function') {
          callback = _host
        } else {
          host = _host
        }
        break;
    }
 
    if (!host) {
      host = parse(url).hostname;
    }
 
    const promise = resolver(url, host, callback);
 
    if (typeof callback === 'function') {
      toCallback(promise, callback)
    } else {
      return promise
    }
  };
}
 
function toCallback (promise, callback) {
  let called = false
  function resolve(rtn) {
    if (called) return
    called = true
    callback(null, rtn)
  }
  function reject(err) {
    if (called) return
    called = true
    callback(err)
  }
  promise.then(resolve, reject)
}