123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- #!/usr/bin/env node
- /*********************************************************************
- * NAN - Native Abstractions for Node.js
- *
- * Copyright (c) 2018 NAN contributors
- *
- * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
- ********************************************************************/
-
- var commander = require('commander'),
- fs = require('fs'),
- glob = require('glob'),
- groups = [],
- total = 0,
- warning1 = '/* ERROR: Rewrite using Buffer */\n',
- warning2 = '\\/\\* ERROR\\: Rewrite using Buffer \\*\\/\\n',
- length,
- i;
-
- fs.readFile(__dirname + '/package.json', 'utf8', function (err, data) {
- if (err) {
- throw err;
- }
-
- commander
- .version(JSON.parse(data).version)
- .usage('[options] <file ...>')
- .parse(process.argv);
-
- if (!process.argv.slice(2).length) {
- commander.outputHelp();
- }
- });
-
- /* construct strings representing regular expressions
- each expression contains a unique group allowing for identification of the match
- the index of this key group, relative to the regular expression in question,
- is indicated by the first array member */
-
- /* simple substistutions, key group is the entire match, 0 */
- groups.push([0, [
- '_NAN_',
- 'NODE_SET_METHOD',
- 'NODE_SET_PROTOTYPE_METHOD',
- 'NanAsciiString',
- 'NanEscapeScope',
- 'NanReturnValue',
- 'NanUcs2String'].join('|')]);
-
- /* substitutions of parameterless macros, key group is 1 */
- groups.push([1, ['(', [
- 'NanEscapableScope',
- 'NanReturnNull',
- 'NanReturnUndefined',
- 'NanScope'].join('|'), ')\\(\\)'].join('')]);
-
- /* replace TryCatch with NanTryCatch once, gobbling possible namespace, key group 2 */
- groups.push([2, '(?:(?:v8\\:\\:)?|(Nan)?)(TryCatch)']);
-
- /* NanNew("string") will likely not fail a ToLocalChecked(), key group 1 */
- groups.push([1, ['(NanNew)', '(\\("[^\\"]*"[^\\)]*\\))(?!\\.ToLocalChecked\\(\\))'].join('')]);
-
- /* Removed v8 APIs, warn that the code needs rewriting using node::Buffer, key group 2 */
- groups.push([2, ['(', warning2, ')?', '^.*?(', [
- 'GetIndexedPropertiesExternalArrayDataLength',
- 'GetIndexedPropertiesExternalArrayData',
- 'GetIndexedPropertiesExternalArrayDataType',
- 'GetIndexedPropertiesPixelData',
- 'GetIndexedPropertiesPixelDataLength',
- 'HasIndexedPropertiesInExternalArrayData',
- 'HasIndexedPropertiesInPixelData',
- 'SetIndexedPropertiesToExternalArrayData',
- 'SetIndexedPropertiesToPixelData'].join('|'), ')'].join('')]);
-
- /* No need for NanScope in V8-exposed methods, key group 2 */
- groups.push([2, ['((', [
- 'NAN_METHOD',
- 'NAN_GETTER',
- 'NAN_SETTER',
- 'NAN_PROPERTY_GETTER',
- 'NAN_PROPERTY_SETTER',
- 'NAN_PROPERTY_ENUMERATOR',
- 'NAN_PROPERTY_DELETER',
- 'NAN_PROPERTY_QUERY',
- 'NAN_INDEX_GETTER',
- 'NAN_INDEX_SETTER',
- 'NAN_INDEX_ENUMERATOR',
- 'NAN_INDEX_DELETER',
- 'NAN_INDEX_QUERY'].join('|'), ')\\([^\\)]*\\)\\s*\\{)\\s*NanScope\\(\\)\\s*;'].join('')]);
-
- /* v8::Value::ToXXXXXXX returns v8::MaybeLocal<T>, key group 3 */
- groups.push([3, ['([\\s\\(\\)])([^\\s\\(\\)]+)->(', [
- 'Boolean',
- 'Number',
- 'String',
- 'Object',
- 'Integer',
- 'Uint32',
- 'Int32'].join('|'), ')\\('].join('')]);
-
- /* v8::Value::XXXXXXXValue returns v8::Maybe<T>, key group 3 */
- groups.push([3, ['([\\s\\(\\)])([^\\s\\(\\)]+)->((?:', [
- 'Boolean',
- 'Number',
- 'Integer',
- 'Uint32',
- 'Int32'].join('|'), ')Value)\\('].join('')]);
-
- /* NAN_WEAK_CALLBACK macro was removed, write out callback definition, key group 1 */
- groups.push([1, '(NAN_WEAK_CALLBACK)\\(([^\\s\\)]+)\\)']);
-
- /* node::ObjectWrap and v8::Persistent have been replaced with Nan implementations, key group 1 */
- groups.push([1, ['(', [
- 'NanDisposePersistent',
- 'NanObjectWrapHandle'].join('|'), ')\\s*\\(\\s*([^\\s\\)]+)'].join('')]);
-
- /* Since NanPersistent there is no need for NanMakeWeakPersistent, key group 1 */
- groups.push([1, '(NanMakeWeakPersistent)\\s*\\(\\s*([^\\s,]+)\\s*,\\s*']);
-
- /* Many methods of v8::Object and others now return v8::MaybeLocal<T>, key group 3 */
- groups.push([3, ['([\\s])([^\\s]+)->(', [
- 'GetEndColumn',
- 'GetFunction',
- 'GetLineNumber',
- 'NewInstance',
- 'GetPropertyNames',
- 'GetOwnPropertyNames',
- 'GetSourceLine',
- 'GetStartColumn',
- 'ObjectProtoToString',
- 'ToArrayIndex',
- 'ToDetailString',
- 'CallAsConstructor',
- 'CallAsFunction',
- 'CloneElementAt',
- 'Delete',
- 'ForceSet',
- 'Get',
- 'GetPropertyAttributes',
- 'GetRealNamedProperty',
- 'GetRealNamedPropertyInPrototypeChain',
- 'Has',
- 'HasOwnProperty',
- 'HasRealIndexedProperty',
- 'HasRealNamedCallbackProperty',
- 'HasRealNamedProperty',
- 'Set',
- 'SetAccessor',
- 'SetIndexedPropertyHandler',
- 'SetNamedPropertyHandler',
- 'SetPrototype'].join('|'), ')\\('].join('')]);
-
- /* You should get an error if any of these fail anyways,
- or handle the error better, it is indicated either way, key group 2 */
- groups.push([2, ['NanNew(<(?:v8\\:\\:)?(', ['Date', 'String', 'RegExp'].join('|'), ')>)(\\([^\\)]*\\))(?!\\.ToLocalChecked\\(\\))'].join('')]);
-
- /* v8::Value::Equals now returns a v8::Maybe, key group 3 */
- groups.push([3, '([\\s\\(\\)])([^\\s\\(\\)]+)->(Equals)\\(([^\\s\\)]+)']);
-
- /* NanPersistent makes this unnecessary, key group 1 */
- groups.push([1, '(NanAssignPersistent)(?:<v8\\:\\:[^>]+>)?\\(([^,]+),\\s*']);
-
- /* args has been renamed to info, key group 2 */
- groups.push([2, '(\\W)(args)(\\W)'])
-
- /* node::ObjectWrap was replaced with NanObjectWrap, key group 2 */
- groups.push([2, '(\\W)(?:node\\:\\:)?(ObjectWrap)(\\W)']);
-
- /* v8::Persistent was replaced with NanPersistent, key group 2 */
- groups.push([2, '(\\W)(?:v8\\:\\:)?(Persistent)(\\W)']);
-
- /* counts the number of capturing groups in a well-formed regular expression,
- ignoring non-capturing groups and escaped parentheses */
- function groupcount(s) {
- var positive = s.match(/\((?!\?)/g),
- negative = s.match(/\\\(/g);
- return (positive ? positive.length : 0) - (negative ? negative.length : 0);
- }
-
- /* compute the absolute position of each key group in the joined master RegExp */
- for (i = 1, length = groups.length; i < length; i++) {
- total += groupcount(groups[i - 1][1]);
- groups[i][0] += total;
- }
-
- /* create the master RegExp, whis is the union of all the groups' expressions */
- master = new RegExp(groups.map(function (a) { return a[1]; }).join('|'), 'gm');
-
- /* replacement function for String.replace, receives 21 arguments */
- function replace() {
- /* simple expressions */
- switch (arguments[groups[0][0]]) {
- case '_NAN_':
- return 'NAN_';
- case 'NODE_SET_METHOD':
- return 'NanSetMethod';
- case 'NODE_SET_PROTOTYPE_METHOD':
- return 'NanSetPrototypeMethod';
- case 'NanAsciiString':
- return 'NanUtf8String';
- case 'NanEscapeScope':
- return 'scope.Escape';
- case 'NanReturnNull':
- return 'info.GetReturnValue().SetNull';
- case 'NanReturnValue':
- return 'info.GetReturnValue().Set';
- case 'NanUcs2String':
- return 'v8::String::Value';
- default:
- }
-
- /* macros without arguments */
- switch (arguments[groups[1][0]]) {
- case 'NanEscapableScope':
- return 'NanEscapableScope scope'
- case 'NanReturnUndefined':
- return 'return';
- case 'NanScope':
- return 'NanScope scope';
- default:
- }
-
- /* TryCatch, emulate negative backref */
- if (arguments[groups[2][0]] === 'TryCatch') {
- return arguments[groups[2][0] - 1] ? arguments[0] : 'NanTryCatch';
- }
-
- /* NanNew("foo") --> NanNew("foo").ToLocalChecked() */
- if (arguments[groups[3][0]] === 'NanNew') {
- return [arguments[0], '.ToLocalChecked()'].join('');
- }
-
- /* insert warning for removed functions as comment on new line above */
- switch (arguments[groups[4][0]]) {
- case 'GetIndexedPropertiesExternalArrayData':
- case 'GetIndexedPropertiesExternalArrayDataLength':
- case 'GetIndexedPropertiesExternalArrayDataType':
- case 'GetIndexedPropertiesPixelData':
- case 'GetIndexedPropertiesPixelDataLength':
- case 'HasIndexedPropertiesInExternalArrayData':
- case 'HasIndexedPropertiesInPixelData':
- case 'SetIndexedPropertiesToExternalArrayData':
- case 'SetIndexedPropertiesToPixelData':
- return arguments[groups[4][0] - 1] ? arguments[0] : [warning1, arguments[0]].join('');
- default:
- }
-
- /* remove unnecessary NanScope() */
- switch (arguments[groups[5][0]]) {
- case 'NAN_GETTER':
- case 'NAN_METHOD':
- case 'NAN_SETTER':
- case 'NAN_INDEX_DELETER':
- case 'NAN_INDEX_ENUMERATOR':
- case 'NAN_INDEX_GETTER':
- case 'NAN_INDEX_QUERY':
- case 'NAN_INDEX_SETTER':
- case 'NAN_PROPERTY_DELETER':
- case 'NAN_PROPERTY_ENUMERATOR':
- case 'NAN_PROPERTY_GETTER':
- case 'NAN_PROPERTY_QUERY':
- case 'NAN_PROPERTY_SETTER':
- return arguments[groups[5][0] - 1];
- default:
- }
-
- /* Value conversion */
- switch (arguments[groups[6][0]]) {
- case 'Boolean':
- case 'Int32':
- case 'Integer':
- case 'Number':
- case 'Object':
- case 'String':
- case 'Uint32':
- return [arguments[groups[6][0] - 2], 'NanTo<v8::', arguments[groups[6][0]], '>(', arguments[groups[6][0] - 1]].join('');
- default:
- }
-
- /* other value conversion */
- switch (arguments[groups[7][0]]) {
- case 'BooleanValue':
- return [arguments[groups[7][0] - 2], 'NanTo<bool>(', arguments[groups[7][0] - 1]].join('');
- case 'Int32Value':
- return [arguments[groups[7][0] - 2], 'NanTo<int32_t>(', arguments[groups[7][0] - 1]].join('');
- case 'IntegerValue':
- return [arguments[groups[7][0] - 2], 'NanTo<int64_t>(', arguments[groups[7][0] - 1]].join('');
- case 'Uint32Value':
- return [arguments[groups[7][0] - 2], 'NanTo<uint32_t>(', arguments[groups[7][0] - 1]].join('');
- default:
- }
-
- /* NAN_WEAK_CALLBACK */
- if (arguments[groups[8][0]] === 'NAN_WEAK_CALLBACK') {
- return ['template<typename T>\nvoid ',
- arguments[groups[8][0] + 1], '(const NanWeakCallbackInfo<T> &data)'].join('');
- }
-
- /* use methods on NAN classes instead */
- switch (arguments[groups[9][0]]) {
- case 'NanDisposePersistent':
- return [arguments[groups[9][0] + 1], '.Reset('].join('');
- case 'NanObjectWrapHandle':
- return [arguments[groups[9][0] + 1], '->handle('].join('');
- default:
- }
-
- /* use method on NanPersistent instead */
- if (arguments[groups[10][0]] === 'NanMakeWeakPersistent') {
- return arguments[groups[10][0] + 1] + '.SetWeak(';
- }
-
- /* These return Maybes, the upper ones take no arguments */
- switch (arguments[groups[11][0]]) {
- case 'GetEndColumn':
- case 'GetFunction':
- case 'GetLineNumber':
- case 'GetOwnPropertyNames':
- case 'GetPropertyNames':
- case 'GetSourceLine':
- case 'GetStartColumn':
- case 'NewInstance':
- case 'ObjectProtoToString':
- case 'ToArrayIndex':
- case 'ToDetailString':
- return [arguments[groups[11][0] - 2], 'Nan', arguments[groups[11][0]], '(', arguments[groups[11][0] - 1]].join('');
- case 'CallAsConstructor':
- case 'CallAsFunction':
- case 'CloneElementAt':
- case 'Delete':
- case 'ForceSet':
- case 'Get':
- case 'GetPropertyAttributes':
- case 'GetRealNamedProperty':
- case 'GetRealNamedPropertyInPrototypeChain':
- case 'Has':
- case 'HasOwnProperty':
- case 'HasRealIndexedProperty':
- case 'HasRealNamedCallbackProperty':
- case 'HasRealNamedProperty':
- case 'Set':
- case 'SetAccessor':
- case 'SetIndexedPropertyHandler':
- case 'SetNamedPropertyHandler':
- case 'SetPrototype':
- return [arguments[groups[11][0] - 2], 'Nan', arguments[groups[11][0]], '(', arguments[groups[11][0] - 1], ', '].join('');
- default:
- }
-
- /* Automatic ToLocalChecked(), take it or leave it */
- switch (arguments[groups[12][0]]) {
- case 'Date':
- case 'String':
- case 'RegExp':
- return ['NanNew', arguments[groups[12][0] - 1], arguments[groups[12][0] + 1], '.ToLocalChecked()'].join('');
- default:
- }
-
- /* NanEquals is now required for uniformity */
- if (arguments[groups[13][0]] === 'Equals') {
- return [arguments[groups[13][0] - 1], 'NanEquals(', arguments[groups[13][0] - 1], ', ', arguments[groups[13][0] + 1]].join('');
- }
-
- /* use method on replacement class instead */
- if (arguments[groups[14][0]] === 'NanAssignPersistent') {
- return [arguments[groups[14][0] + 1], '.Reset('].join('');
- }
-
- /* args --> info */
- if (arguments[groups[15][0]] === 'args') {
- return [arguments[groups[15][0] - 1], 'info', arguments[groups[15][0] + 1]].join('');
- }
-
- /* ObjectWrap --> NanObjectWrap */
- if (arguments[groups[16][0]] === 'ObjectWrap') {
- return [arguments[groups[16][0] - 1], 'NanObjectWrap', arguments[groups[16][0] + 1]].join('');
- }
-
- /* Persistent --> NanPersistent */
- if (arguments[groups[17][0]] === 'Persistent') {
- return [arguments[groups[17][0] - 1], 'NanPersistent', arguments[groups[17][0] + 1]].join('');
- }
-
- /* This should not happen. A switch is probably missing a case if it does. */
- throw 'Unhandled match: ' + arguments[0];
- }
-
- /* reads a file, runs replacement and writes it back */
- function processFile(file) {
- fs.readFile(file, {encoding: 'utf8'}, function (err, data) {
- if (err) {
- throw err;
- }
-
- /* run replacement twice, might need more runs */
- fs.writeFile(file, data.replace(master, replace).replace(master, replace), function (err) {
- if (err) {
- throw err;
- }
- });
- });
- }
-
- /* process file names from command line and process the identified files */
- for (i = 2, length = process.argv.length; i < length; i++) {
- glob(process.argv[i], function (err, matches) {
- if (err) {
- throw err;
- }
- matches.forEach(processFile);
- });
- }
|