diff --git a/lib/global-this.js b/lib/global-this.js
new file mode 100644
index 00000000..2040039d
--- /dev/null
+++ b/lib/global-this.js
@@ -0,0 +1,24 @@
+'use strict';
+
+const THIS_BREAK_KEYS = [ 'FunctionExpression', 'FunctionDeclaration', 'ClassProperty',
+ 'ClassMethod', 'ObjectMethod' ];
+
+// Walk the AST looking for 'this' references intended to be references to global
+// Replace them with an explicit 'global' reference
+module.exports = function (_ref) {
+ const t = _ref.types;
+ return {
+ visitor: {
+ ThisExpression(path, state) {
+ if (
+ state.opts.allowTopLevelThis !== true
+ && !path.findParent((path) => !path.is('shadow')
+ && THIS_BREAK_KEYS.indexOf(path.type) >= 0)
+ ) {
+ // TODO: Spit out a warning/deprecation notice?
+ path.replaceWith(t.identifier('global'));
+ }
+ }
+ }
+ };
+};
diff --git a/lib/jsanalyze.js b/lib/jsanalyze.js
index c81064cf..80742bda 100644
--- a/lib/jsanalyze.js
+++ b/lib/jsanalyze.js
@@ -76,7 +76,7 @@ function getMemberValue(node) {
function getTitaniumExpression(member) {
var value = getMemberValue(member),
tiNodeRegExp = /^Ti(tanium)?/;
- if (value == null) return null;
+ if (value == null) { return null; }
if (tiNodeRegExp.test(value)) {
// if value.startsWith('Ti.'), replace with 'Titanium.'
if (value.indexOf('Ti.') === 0) {
@@ -123,7 +123,7 @@ exports.analyzeJs = function analyzeJs(contents, opts) {
contents = contents.split('\n');
if (ex.line && ex.line <= contents.length) {
errmsg.push('');
- errmsg.push(' ' + contents[ex.line-1].replace(/\t/g, ' '));
+ errmsg.push(' ' + contents[ex.line - 1].replace(/\t/g, ' '));
if (ex.col) {
var i = 0,
len = ex.col,
@@ -142,7 +142,7 @@ exports.analyzeJs = function analyzeJs(contents, opts) {
// find all of the titanium symbols
traverse(ast, {
MemberExpression: {
- enter: function(path) {
+ enter: function (path) {
var memberExpr = getTitaniumExpression(path.node);
if (memberExpr) {
symbols[memberExpr.substring(9)] = 1; // Drop leading 'Titanium.'
@@ -170,6 +170,7 @@ exports.analyzeJs = function analyzeJs(contents, opts) {
// transpile
if (opts.transpile) {
+ options.plugins.push(require.resolve('./global-this'));
options.presets.push([ env, { targets: opts.targets } ]);
}
@@ -246,7 +247,7 @@ exports.analyzeHtml = function analyzeHtml(contents, relPath) {
}
try {
- var dom = new DOMParser({ errorHandler: function(){} }).parseFromString('\n' + contents + '\n', 'text/html'),
+ var dom = new DOMParser({ errorHandler: function () {} }).parseFromString('\n' + contents + '\n', 'text/html'),
doc = dom && dom.documentElement,
scripts = doc && doc.getElementsByTagName('script'),
i, len, src, m, p, q, r;
diff --git a/package-lock.json b/package-lock.json
index b2883b39..5a860954 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "node-titanium-sdk",
- "version": "0.4.8",
+ "version": "0.4.9",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 50dc3ad9..9a2c356c 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,7 @@
"titanium",
"mobile"
],
- "version": "0.4.8",
+ "version": "0.4.9",
"author": {
"name": "Appcelerator, Inc.",
"email": "info@appcelerator.com"
@@ -53,6 +53,6 @@
"node": ">=0.6.6"
},
"scripts": {
- "test": "JUNIT_REPORT_PATH=junit_report.xml mocha --require tests/init --reporter mocha-jenkins-reporter --check-leaks tests/test-tiappxml.js"
+ "test": "JUNIT_REPORT_PATH=junit_report.xml mocha --require tests/init --reporter mocha-jenkins-reporter --check-leaks tests/*_test.js"
}
}
diff --git a/tests/init.js b/tests/init.js
index ed0eeed9..fcaaf2d1 100644
--- a/tests/init.js
+++ b/tests/init.js
@@ -1,9 +1,10 @@
-global.should = null;
-global.should = require('should');
-
-var util = require('util');
-global.dump = function () {
- for (var i = 0; i < arguments.length; i++) {
- console.error(util.inspect(arguments[i], false, null, true));
- }
-};
\ No newline at end of file
+'use strict';
+global.should = null;
+global.should = require('should');
+
+var util = require('util');
+global.dump = function () {
+ for (var i = 0; i < arguments.length; i++) {
+ console.error(util.inspect(arguments[i], false, null, true));
+ }
+};
diff --git a/tests/jsanalyze_test.js b/tests/jsanalyze_test.js
new file mode 100644
index 00000000..4654a602
--- /dev/null
+++ b/tests/jsanalyze_test.js
@@ -0,0 +1,10 @@
+'use strict';
+
+const jsanalyze = require('../lib/jsanalyze');
+
+describe('jsanalyze', function () {
+ it('#analyzeJs() converts global "this" references into "global" references when transpiling', function () {
+ const results = jsanalyze.analyzeJs('this.myGlobalMethod = function() {};', { transpile: true });
+ results.contents.should.eql('"use strict";global.myGlobalMethod = function () {};');
+ });
+});
diff --git a/tests/run.js b/tests/run.js
index c3e194e3..9b4dfa04 100644
--- a/tests/run.js
+++ b/tests/run.js
@@ -1,17 +1,21 @@
-var spawn = require('child_process').spawn,
- exitCode = 0,
+'use strict';
+
+const spawn = require('child_process').spawn, // eslint-disable-line security/detect-child-process
tests = [
- 'test-tiappxml.js'
+ 'jsanalyze_test.js',
+ 'tiappxml_test.js'
];
+let exitCode = 0;
+
(function next() {
if (tests.length === 0) {
process.exit(exitCode);
}
-
+
var file = tests.shift();
console.log(file);
-
+
var proc = spawn('node', [ 'tests/' + file ]);
proc.stdout.pipe(process.stdout);
proc.stderr.pipe(process.stderr);
diff --git a/tests/test-tiappxml.js b/tests/tiappxml_test.js
similarity index 100%
rename from tests/test-tiappxml.js
rename to tests/tiappxml_test.js