Skip to content

Commit

Permalink
Merge pull request #1 from sgtcoolguy/es6
Browse files Browse the repository at this point in the history
[TIMOB-24609] ES 6 Support
  • Loading branch information
sgtcoolguy committed Apr 24, 2017
2 parents 6222f4b + 196118f commit d57d09d
Show file tree
Hide file tree
Showing 3 changed files with 497 additions and 68 deletions.
108 changes: 57 additions & 51 deletions lib/jsanalyze.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* @module lib/jsanalyze
*
* @copyright
* Copyright (c) 2009-2013 by Appcelerator, Inc. All Rights Reserved.
* Copyright (c) 2009-2017 by Appcelerator, Inc. All Rights Reserved.
*
* @license
* Licensed under the terms of the Apache Public License
Expand All @@ -15,13 +15,13 @@
var appc = require('node-appc'),
fs = require('fs'),
DOMParser = require('xmldom').DOMParser,
UglifyJS = require('uglify-js'),
babel = require('babel-core'),
babylon = require('babylon'),
types = require('babel-types'),
traverse = require('babel-traverse').default,
__ = appc.i18n(__dirname).__,
apiUsage = {};

// silence uglify's default warn mechanism
UglifyJS.AST_Node.warn_function = function () {};

/**
* Returns an object with the Titanium API usage statistics.
*
Expand All @@ -47,6 +47,44 @@ exports.analyzeJsFile = function analyzeJsFile(file, opts) {
return exports.analyzeJs(fs.readFileSync(file).toString(), opts);
};

// Need to look for MemberExpressions, expand them out to full name

function getMemberValue(node) {
if (types.isIdentifier(node)) {
return node.name;
} else if (types.isStringLiteral(node)) {
return node.value;
} else if (types.isMemberExpression(node)) {
if (node.computed && !types.isStringLiteral(node.property)) {
return null;
}
var objVal = getMemberValue(node.object);
if (objVal == null) {
return null;
}
var propVal = getMemberValue(node.property);
if (propVal == null) {
return null;
}
return objVal + '.' + propVal;
}
return null;
}

function getTitaniumExpression(member) {
var value = getMemberValue(member),
tiNodeRegExp = /^Ti(tanium)?/;
if (value == null) return null;
if (tiNodeRegExp.test(value)) {
// if value.startsWith('Ti.'), replace with 'Titanium.'
if (value.indexOf('Ti.') === 0) {
return 'Titanium.' + value.substring(3);
}
return value;
}
return null;
}

/**
* Analyzes a string containing JavaScript for all Titanium API symbols.
*
Expand All @@ -71,7 +109,7 @@ exports.analyzeJs = function analyzeJs(contents, opts) {

// parse the js file
try {
ast = UglifyJS.parse(contents, { filename: opts.filename });
ast = babylon.parse(contents, { sourceFilename: opts.filename });
} catch (ex) {
var errmsg = [ __('Failed to parse %s', opts.filename) ];
if (ex.line) {
Expand Down Expand Up @@ -100,63 +138,31 @@ exports.analyzeJs = function analyzeJs(contents, opts) {
}

// find all of the titanium symbols
var walker = new UglifyJS.TreeWalker(function (node, descend) {
if (node instanceof UglifyJS.AST_SymbolRef && tiNodeRegExp.test(node.name)) {
var p = walker.stack,
buffer = [],
symbol,
i = p.length - 1; // we already know the top of the stack is Ti

// loop until 2nd from bottom of stack since the bottom is the toplevel node which we don't care about
while (--i) {
if (p[i] instanceof UglifyJS.AST_Dot) {
buffer.push(p[i].property);
} else if (p[i] instanceof UglifyJS.AST_Symbol || p[i] instanceof UglifyJS.AST_SymbolRef) {
buffer.push(p[i].name);
} else {
break;
}
}

if (buffer.length) {
// the build is only interested in finding Titanium.* symbols
symbols[buffer.join('.')] = 1;

traverse(ast, {
MemberExpression: {
enter: function(path) {
var memberExpr = getTitaniumExpression(path.node);
if (memberExpr) {
symbols[memberExpr.substring(9)] = 1; // Drop leading 'Titanium.'
if (!opts.skipStats) {
// analytics wants all symbols
if (node.name == 'Ti') {
buffer.unshift('Titanium');
} else {
buffer.unshift(node.name);
}

var api = buffer.join('.');
if (apiUsage[api] === void 0) {
apiUsage[api] = 1;
if (apiUsage[memberExpr] === void 0) {
apiUsage[memberExpr] = 1;
} else {
apiUsage[api]++;
apiUsage[memberExpr]++;
}
}
}

}
}.bind(this));

ast.walk(walker);
}
});

// convert the object of symbol names to an array of symbol names
results.symbols = Object.keys(symbols);

// minify
if (opts.minify) {
ast.figure_out_scope();
ast = ast.transform(UglifyJS.Compressor());
ast.figure_out_scope();
ast.compute_char_frequency();
ast.mangle_names();
var stream = UglifyJS.OutputStream();
ast.print(stream);
results.contents = stream.toString();
var minified = babel.transformFromAst(ast, contents, {minified: true, compact: true, comments: false, presets: ['babili']});
results.contents = minified.code;
}

return results;
Expand Down
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"titanium",
"mobile"
],
"version": "0.1.0",
"version": "0.2.0",
"author": {
"name": "Appcelerator, Inc.",
"email": "info@appcelerator.com"
Expand All @@ -22,9 +22,13 @@
},
"dependencies": {
"async": "^2.3.0",
"babylon": "^6.16.1",
"babel-core": "^6.24.1",
"babel-preset-babili": "^0.0.12",
"babel-traverse": "^6.23.1",
"babel-types": "^6.23.0",
"node-appc": "^0.2.43",
"stream-splitter": "~0.3.2",
"uglify-js": "^2.8.21",
"unorm": "^1.4.1",
"wrench": "^1.5.9",
"xmldom": "0.1.22"
Expand Down

0 comments on commit d57d09d

Please sign in to comment.