Initial commit
[yaffs-website] / node_modules / nan / tools / 1to2.js
1 #!/usr/bin/env node
2 /*********************************************************************
3  * NAN - Native Abstractions for Node.js
4  *
5  * Copyright (c) 2017 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 }