Projekt

Obecné

Profil

Stáhnout (14 KB) Statistiky
| Větev: | Revize:
1
#!/usr/bin/env node
2
/*********************************************************************
3
 * NAN - Native Abstractions for Node.js
4
 *
5
 * Copyright (c) 2018 NAN contributors
6
 *
7
 * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
8
 ********************************************************************/
9

    
10
var commander = require('commander'),
11
    fs = require('fs'),
12
    glob = require('glob'),
13
    groups = [],
14
    total = 0,
15
    warning1 = '/* ERROR: Rewrite using Buffer */\n',
16
    warning2 = '\\/\\* ERROR\\: Rewrite using Buffer \\*\\/\\n',
17
    length,
18
    i;
19

    
20
fs.readFile(__dirname + '/package.json', 'utf8', function (err, data) {
21
  if (err) {
22
    throw err;
23
  }
24

    
25
  commander
26
      .version(JSON.parse(data).version)
27
      .usage('[options] <file ...>')
28
      .parse(process.argv);
29

    
30
  if (!process.argv.slice(2).length) {
31
    commander.outputHelp();
32
  }
33
});
34

    
35
/* construct strings representing regular expressions
36
   each expression contains a unique group allowing for identification of the match
37
   the index of this key group, relative to the regular expression in question,
38
    is indicated by the first array member */
39

    
40
/* simple substistutions, key group is the entire match, 0 */
41
groups.push([0, [
42
  '_NAN_',
43
  'NODE_SET_METHOD',
44
  'NODE_SET_PROTOTYPE_METHOD',
45
  'NanAsciiString',
46
  'NanEscapeScope',
47
  'NanReturnValue',
48
  'NanUcs2String'].join('|')]);
49

    
50
/* substitutions of parameterless macros, key group is 1 */
51
groups.push([1, ['(', [
52
  'NanEscapableScope',
53
  'NanReturnNull',
54
  'NanReturnUndefined',
55
  'NanScope'].join('|'), ')\\(\\)'].join('')]);
56

    
57
/* replace TryCatch with NanTryCatch once, gobbling possible namespace, key group 2 */
58
groups.push([2, '(?:(?:v8\\:\\:)?|(Nan)?)(TryCatch)']);
59

    
60
/* NanNew("string") will likely not fail a ToLocalChecked(), key group 1 */ 
61
groups.push([1, ['(NanNew)', '(\\("[^\\"]*"[^\\)]*\\))(?!\\.ToLocalChecked\\(\\))'].join('')]);
62

    
63
/* Removed v8 APIs, warn that the code needs rewriting using node::Buffer, key group 2 */
64
groups.push([2, ['(', warning2, ')?', '^.*?(', [
65
      'GetIndexedPropertiesExternalArrayDataLength',
66
      'GetIndexedPropertiesExternalArrayData',
67
      'GetIndexedPropertiesExternalArrayDataType',
68
      'GetIndexedPropertiesPixelData',
69
      'GetIndexedPropertiesPixelDataLength',
70
      'HasIndexedPropertiesInExternalArrayData',
71
      'HasIndexedPropertiesInPixelData',
72
      'SetIndexedPropertiesToExternalArrayData',
73
      'SetIndexedPropertiesToPixelData'].join('|'), ')'].join('')]);
74

    
75
/* No need for NanScope in V8-exposed methods, key group 2 */
76
groups.push([2, ['((', [
77
      'NAN_METHOD',
78
      'NAN_GETTER',
79
      'NAN_SETTER',
80
      'NAN_PROPERTY_GETTER',
81
      'NAN_PROPERTY_SETTER',
82
      'NAN_PROPERTY_ENUMERATOR',
83
      'NAN_PROPERTY_DELETER',
84
      'NAN_PROPERTY_QUERY',
85
      'NAN_INDEX_GETTER',
86
      'NAN_INDEX_SETTER',
87
      'NAN_INDEX_ENUMERATOR',
88
      'NAN_INDEX_DELETER',
89
      'NAN_INDEX_QUERY'].join('|'), ')\\([^\\)]*\\)\\s*\\{)\\s*NanScope\\(\\)\\s*;'].join('')]);
90

    
91
/* v8::Value::ToXXXXXXX returns v8::MaybeLocal<T>, key group 3 */
92
groups.push([3, ['([\\s\\(\\)])([^\\s\\(\\)]+)->(', [
93
      'Boolean',
94
      'Number',
95
      'String',
96
      'Object',
97
      'Integer',
98
      'Uint32',
99
      'Int32'].join('|'), ')\\('].join('')]);
100

    
101
/* v8::Value::XXXXXXXValue returns v8::Maybe<T>, key group 3 */
102
groups.push([3, ['([\\s\\(\\)])([^\\s\\(\\)]+)->((?:', [
103
      'Boolean',
104
      'Number',
105
      'Integer',
106
      'Uint32',
107
      'Int32'].join('|'), ')Value)\\('].join('')]);
108

    
109
/* NAN_WEAK_CALLBACK macro was removed, write out callback definition, key group 1 */
110
groups.push([1, '(NAN_WEAK_CALLBACK)\\(([^\\s\\)]+)\\)']);
111

    
112
/* node::ObjectWrap and v8::Persistent have been replaced with Nan implementations, key group 1 */
113
groups.push([1, ['(', [
114
  'NanDisposePersistent',
115
  'NanObjectWrapHandle'].join('|'), ')\\s*\\(\\s*([^\\s\\)]+)'].join('')]);
116

    
117
/* Since NanPersistent there is no need for NanMakeWeakPersistent, key group 1 */
118
groups.push([1, '(NanMakeWeakPersistent)\\s*\\(\\s*([^\\s,]+)\\s*,\\s*']);
119

    
120
/* Many methods of v8::Object and others now return v8::MaybeLocal<T>, key group 3 */
121
groups.push([3, ['([\\s])([^\\s]+)->(', [
122
  'GetEndColumn',
123
  'GetFunction',
124
  'GetLineNumber',
125
  'NewInstance',
126
  'GetPropertyNames',
127
  'GetOwnPropertyNames',
128
  'GetSourceLine',
129
  'GetStartColumn',
130
  'ObjectProtoToString',
131
  'ToArrayIndex',
132
  'ToDetailString',
133
  'CallAsConstructor',
134
  'CallAsFunction',
135
  'CloneElementAt',
136
  'Delete',
137
  'ForceSet',
138
  'Get',
139
  'GetPropertyAttributes',
140
  'GetRealNamedProperty',
141
  'GetRealNamedPropertyInPrototypeChain',
142
  'Has',
143
  'HasOwnProperty',
144
  'HasRealIndexedProperty',
145
  'HasRealNamedCallbackProperty',
146
  'HasRealNamedProperty',
147
  'Set',
148
  'SetAccessor',
149
  'SetIndexedPropertyHandler',
150
  'SetNamedPropertyHandler',
151
  'SetPrototype'].join('|'), ')\\('].join('')]);
152

    
153
/* You should get an error if any of these fail anyways,
154
   or handle the error better, it is indicated either way, key group 2 */
155
groups.push([2, ['NanNew(<(?:v8\\:\\:)?(', ['Date', 'String', 'RegExp'].join('|'), ')>)(\\([^\\)]*\\))(?!\\.ToLocalChecked\\(\\))'].join('')]);
156

    
157
/* v8::Value::Equals now returns a v8::Maybe, key group 3 */
158
groups.push([3, '([\\s\\(\\)])([^\\s\\(\\)]+)->(Equals)\\(([^\\s\\)]+)']);
159

    
160
/* NanPersistent makes this unnecessary, key group 1 */
161
groups.push([1, '(NanAssignPersistent)(?:<v8\\:\\:[^>]+>)?\\(([^,]+),\\s*']);
162

    
163
/* args has been renamed to info, key group 2 */
164
groups.push([2, '(\\W)(args)(\\W)'])
165

    
166
/* node::ObjectWrap was replaced with NanObjectWrap, key group 2 */
167
groups.push([2, '(\\W)(?:node\\:\\:)?(ObjectWrap)(\\W)']);
168

    
169
/* v8::Persistent was replaced with NanPersistent, key group 2 */
170
groups.push([2, '(\\W)(?:v8\\:\\:)?(Persistent)(\\W)']);
171

    
172
/* counts the number of capturing groups in a well-formed regular expression,
173
   ignoring non-capturing groups and escaped parentheses */
174
function groupcount(s) {
175
  var positive = s.match(/\((?!\?)/g),
176
      negative = s.match(/\\\(/g);
177
  return (positive ? positive.length : 0) - (negative ? negative.length : 0);
178
}
179

    
180
/* compute the absolute position of each key group in the joined master RegExp */
181
for (i = 1, length = groups.length; i < length; i++) {
182
	total += groupcount(groups[i - 1][1]);
183
	groups[i][0] += total;
184
}
185

    
186
/* create the master RegExp, whis is the union of all the groups' expressions */
187
master = new RegExp(groups.map(function (a) { return a[1]; }).join('|'), 'gm');
188

    
189
/* replacement function for String.replace, receives 21 arguments */
190
function replace() {
191
	/* simple expressions */
192
      switch (arguments[groups[0][0]]) {
193
        case '_NAN_':
194
          return 'NAN_';
195
        case 'NODE_SET_METHOD':
196
          return 'NanSetMethod';
197
        case 'NODE_SET_PROTOTYPE_METHOD':
198
          return 'NanSetPrototypeMethod';
199
        case 'NanAsciiString':
200
          return 'NanUtf8String';
201
        case 'NanEscapeScope':
202
          return 'scope.Escape';
203
        case 'NanReturnNull':
204
          return 'info.GetReturnValue().SetNull';
205
        case 'NanReturnValue':
206
          return 'info.GetReturnValue().Set';
207
        case 'NanUcs2String':
208
          return 'v8::String::Value';
209
        default:
210
      }
211

    
212
      /* macros without arguments */
213
      switch (arguments[groups[1][0]]) {
214
        case 'NanEscapableScope':
215
          return 'NanEscapableScope scope'
216
        case 'NanReturnUndefined':
217
          return 'return';
218
        case 'NanScope':
219
          return 'NanScope scope';
220
        default:
221
      }
222

    
223
      /* TryCatch, emulate negative backref */
224
      if (arguments[groups[2][0]] === 'TryCatch') {
225
        return arguments[groups[2][0] - 1] ? arguments[0] : 'NanTryCatch';
226
      }
227

    
228
      /* NanNew("foo") --> NanNew("foo").ToLocalChecked() */
229
      if (arguments[groups[3][0]] === 'NanNew') {
230
        return [arguments[0], '.ToLocalChecked()'].join('');
231
      }
232

    
233
      /* insert warning for removed functions as comment on new line above */
234
      switch (arguments[groups[4][0]]) {
235
        case 'GetIndexedPropertiesExternalArrayData':
236
        case 'GetIndexedPropertiesExternalArrayDataLength':
237
        case 'GetIndexedPropertiesExternalArrayDataType':
238
        case 'GetIndexedPropertiesPixelData':
239
        case 'GetIndexedPropertiesPixelDataLength':
240
        case 'HasIndexedPropertiesInExternalArrayData':
241
        case 'HasIndexedPropertiesInPixelData':
242
        case 'SetIndexedPropertiesToExternalArrayData':
243
        case 'SetIndexedPropertiesToPixelData':
244
          return arguments[groups[4][0] - 1] ? arguments[0] : [warning1, arguments[0]].join('');
245
        default:
246
      }
247

    
248
     /* remove unnecessary NanScope() */
249
      switch (arguments[groups[5][0]]) {
250
        case 'NAN_GETTER':
251
        case 'NAN_METHOD':
252
        case 'NAN_SETTER':
253
        case 'NAN_INDEX_DELETER':
254
        case 'NAN_INDEX_ENUMERATOR':
255
        case 'NAN_INDEX_GETTER':
256
        case 'NAN_INDEX_QUERY':
257
        case 'NAN_INDEX_SETTER':
258
        case 'NAN_PROPERTY_DELETER':
259
        case 'NAN_PROPERTY_ENUMERATOR':
260
        case 'NAN_PROPERTY_GETTER':
261
        case 'NAN_PROPERTY_QUERY':
262
        case 'NAN_PROPERTY_SETTER':
263
          return arguments[groups[5][0] - 1];
264
        default:
265
      }
266

    
267
      /* Value converstion */
268
      switch (arguments[groups[6][0]]) {
269
        case 'Boolean':
270
        case 'Int32':
271
        case 'Integer':
272
        case 'Number':
273
        case 'Object':
274
        case 'String':
275
        case 'Uint32':
276
          return [arguments[groups[6][0] - 2], 'NanTo<v8::', arguments[groups[6][0]], '>(',  arguments[groups[6][0] - 1]].join('');
277
        default:
278
      }
279

    
280
      /* other value conversion */
281
      switch (arguments[groups[7][0]]) {
282
        case 'BooleanValue':
283
          return [arguments[groups[7][0] - 2], 'NanTo<bool>(', arguments[groups[7][0] - 1]].join('');
284
        case 'Int32Value':
285
          return [arguments[groups[7][0] - 2], 'NanTo<int32_t>(', arguments[groups[7][0] - 1]].join('');
286
        case 'IntegerValue':
287
          return [arguments[groups[7][0] - 2], 'NanTo<int64_t>(', arguments[groups[7][0] - 1]].join('');
288
        case 'Uint32Value':
289
          return [arguments[groups[7][0] - 2], 'NanTo<uint32_t>(', arguments[groups[7][0] - 1]].join('');
290
        default:
291
      }
292

    
293
      /* NAN_WEAK_CALLBACK */
294
      if (arguments[groups[8][0]] === 'NAN_WEAK_CALLBACK') {
295
        return ['template<typename T>\nvoid ',
296
          arguments[groups[8][0] + 1], '(const NanWeakCallbackInfo<T> &data)'].join('');
297
      }
298

    
299
      /* use methods on NAN classes instead */
300
      switch (arguments[groups[9][0]]) {
301
        case 'NanDisposePersistent':
302
          return [arguments[groups[9][0] + 1], '.Reset('].join('');
303
        case 'NanObjectWrapHandle':
304
          return [arguments[groups[9][0] + 1], '->handle('].join('');
305
        default:
306
      }
307

    
308
      /* use method on NanPersistent instead */
309
      if (arguments[groups[10][0]] === 'NanMakeWeakPersistent') {
310
        return arguments[groups[10][0] + 1] + '.SetWeak(';
311
      }
312

    
313
      /* These return Maybes, the upper ones take no arguments */
314
      switch (arguments[groups[11][0]]) {
315
        case 'GetEndColumn':
316
        case 'GetFunction':
317
        case 'GetLineNumber':
318
        case 'GetOwnPropertyNames':
319
        case 'GetPropertyNames':
320
        case 'GetSourceLine':
321
        case 'GetStartColumn':
322
        case 'NewInstance':
323
        case 'ObjectProtoToString':
324
        case 'ToArrayIndex':
325
        case 'ToDetailString':
326
          return [arguments[groups[11][0] - 2], 'Nan', arguments[groups[11][0]], '(', arguments[groups[11][0] - 1]].join('');
327
        case 'CallAsConstructor':
328
        case 'CallAsFunction':
329
        case 'CloneElementAt':
330
        case 'Delete':
331
        case 'ForceSet':
332
        case 'Get':
333
        case 'GetPropertyAttributes':
334
        case 'GetRealNamedProperty':
335
        case 'GetRealNamedPropertyInPrototypeChain':
336
        case 'Has':
337
        case 'HasOwnProperty':
338
        case 'HasRealIndexedProperty':
339
        case 'HasRealNamedCallbackProperty':
340
        case 'HasRealNamedProperty':
341
        case 'Set':
342
        case 'SetAccessor':
343
        case 'SetIndexedPropertyHandler':
344
        case 'SetNamedPropertyHandler':
345
        case 'SetPrototype':
346
          return [arguments[groups[11][0] - 2], 'Nan', arguments[groups[11][0]], '(', arguments[groups[11][0] - 1], ', '].join('');
347
        default:
348
      }
349

    
350
      /* Automatic ToLocalChecked(), take it or leave it */
351
      switch (arguments[groups[12][0]]) {
352
        case 'Date':
353
        case 'String':
354
        case 'RegExp':
355
          return ['NanNew', arguments[groups[12][0] - 1], arguments[groups[12][0] + 1], '.ToLocalChecked()'].join('');
356
        default:
357
      }
358

    
359
      /* NanEquals is now required for uniformity */
360
      if (arguments[groups[13][0]] === 'Equals') {
361
        return [arguments[groups[13][0] - 1], 'NanEquals(', arguments[groups[13][0] - 1], ', ', arguments[groups[13][0] + 1]].join('');
362
      }
363

    
364
      /* use method on replacement class instead */
365
      if (arguments[groups[14][0]] === 'NanAssignPersistent') {
366
        return [arguments[groups[14][0] + 1], '.Reset('].join('');
367
      }
368

    
369
      /* args --> info */
370
      if (arguments[groups[15][0]] === 'args') {
371
        return [arguments[groups[15][0] - 1], 'info', arguments[groups[15][0] + 1]].join('');
372
      }
373

    
374
      /* ObjectWrap --> NanObjectWrap */
375
      if (arguments[groups[16][0]] === 'ObjectWrap') {
376
        return [arguments[groups[16][0] - 1], 'NanObjectWrap', arguments[groups[16][0] + 1]].join('');
377
      }
378

    
379
      /* Persistent --> NanPersistent */
380
      if (arguments[groups[17][0]] === 'Persistent') {
381
        return [arguments[groups[17][0] - 1], 'NanPersistent', arguments[groups[17][0] + 1]].join('');
382
      }
383

    
384
      /* This should not happen. A switch is probably missing a case if it does. */
385
      throw 'Unhandled match: ' + arguments[0];
386
}
387

    
388
/* reads a file, runs replacement and writes it back */
389
function processFile(file) {
390
  fs.readFile(file, {encoding: 'utf8'}, function (err, data) {
391
    if (err) {
392
      throw err;
393
    }
394

    
395
    /* run replacement twice, might need more runs */
396
    fs.writeFile(file, data.replace(master, replace).replace(master, replace), function (err) {
397
      if (err) {
398
        throw err;
399
      }
400
    });
401
  });
402
}
403

    
404
/* process file names from command line and process the identified files */
405
for (i = 2, length = process.argv.length; i < length; i++) {
406
  glob(process.argv[i], function (err, matches) {
407
    if (err) {
408
      throw err;
409
    }
410
    matches.forEach(processFile);
411
  });
412
}
(1-1/3)