@qooxdoo/framework 7.0.0-beta.3 → 7.0.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/Manifest.json +1 -1
  3. package/README.md +9 -3
  4. package/lib/compiler/compile-info.json +60 -58
  5. package/lib/compiler/index.js +3242 -1883
  6. package/lib/resource/qx/tool/cli/templates/skeleton/mobile/source/theme/custom/css/custom.css.map +1 -1
  7. package/lib/resource/qx/tool/loadsass.js +6 -4
  8. package/lib/resource/qx/tool/schema/compile-1-0-0.json +6 -11
  9. package/package.json +17 -3
  10. package/source/class/qx/Bootstrap.js +22 -1
  11. package/source/class/qx/bom/Blocker.js +2 -1
  12. package/source/class/qx/core/Environment.js +3 -12
  13. package/source/class/qx/core/MProperty.js +1 -1
  14. package/source/class/qx/dev/unit/Sinon.js +1 -1
  15. package/source/class/qx/io/__init__.js +5 -3
  16. package/source/class/qx/io/exception/Cancel.js +34 -0
  17. package/source/class/qx/io/exception/Exception.js +38 -0
  18. package/source/class/qx/io/exception/Protocol.js +26 -0
  19. package/source/class/qx/io/exception/Transport.js +39 -0
  20. package/source/class/qx/io/exception/__init__.js +4 -0
  21. package/source/class/qx/io/graphql/Client.js +112 -0
  22. package/source/class/qx/io/graphql/__init__.js +9 -0
  23. package/source/class/qx/io/graphql/protocol/Message.js +65 -0
  24. package/source/class/qx/io/graphql/protocol/Request.js +95 -0
  25. package/source/class/qx/io/graphql/protocol/Response.js +61 -0
  26. package/source/class/qx/io/graphql/protocol/__init__.js +6 -0
  27. package/source/class/qx/io/jsonrpc/Client.js +323 -0
  28. package/source/class/qx/io/jsonrpc/__init__.js +15 -0
  29. package/source/class/qx/io/jsonrpc/protocol/Batch.js +97 -0
  30. package/source/class/qx/io/jsonrpc/protocol/Error.js +63 -0
  31. package/source/class/qx/io/jsonrpc/protocol/Message.js +48 -0
  32. package/source/class/qx/io/jsonrpc/protocol/Notification.js +45 -0
  33. package/source/class/qx/io/jsonrpc/protocol/Parser.js +81 -0
  34. package/source/class/qx/io/jsonrpc/protocol/Request.js +93 -0
  35. package/source/class/qx/io/jsonrpc/protocol/Result.js +48 -0
  36. package/source/class/qx/io/jsonrpc/protocol/__init__.js +5 -0
  37. package/source/class/qx/io/request/authentication/Bearer.js +52 -0
  38. package/source/class/qx/io/transport/AbstractClient.js +100 -0
  39. package/source/class/qx/io/transport/AbstractTransport.js +41 -0
  40. package/source/class/qx/io/transport/Fetch.js +95 -0
  41. package/source/class/qx/io/transport/ITransport.js +40 -0
  42. package/source/class/qx/io/transport/PostMessage.js +55 -0
  43. package/source/class/qx/io/transport/Websocket.js +97 -0
  44. package/source/class/qx/io/transport/Xhr.js +139 -0
  45. package/source/class/qx/io/transport/__init__.js +18 -0
  46. package/source/class/qx/test/core/Assert.js +1 -1
  47. package/source/class/qx/test/core/Environment.js +0 -3
  48. package/source/class/qx/test/io/MAssert.js +46 -0
  49. package/source/class/qx/test/io/graphql/Client.js +169 -0
  50. package/source/class/qx/test/io/graphql/ClientFetch.js +34 -0
  51. package/source/class/qx/test/io/graphql/Request.js +42 -0
  52. package/source/class/qx/test/io/jsonrpc/Client.js +267 -0
  53. package/source/class/qx/test/io/jsonrpc/Protocol.js +80 -0
  54. package/source/class/qx/test/io/transport/PostMessage.js +56 -0
  55. package/source/class/qx/test/io/transport/Websocket.js +63 -0
  56. package/source/class/qx/test/ui/embed/Iframe.js +1 -1
  57. package/source/class/qx/test/util/DateFormat.js +45 -6
  58. package/source/class/qx/tool/cli/Cli.js +1 -0
  59. package/source/class/qx/tool/cli/commands/Compile.js +13 -3
  60. package/source/class/qx/tool/cli/commands/Es6ify.js +93 -0
  61. package/source/class/qx/tool/cli/commands/package/Install.js +1 -1
  62. package/source/class/qx/tool/cli/commands/package/Publish.js +14 -0
  63. package/source/class/qx/tool/compiler/ClassFile.js +67 -27
  64. package/source/class/qx/tool/compiler/Es6ify.js +368 -0
  65. package/source/class/qx/tool/compiler/makers/AppMaker.js +2 -1
  66. package/source/class/qx/tool/compiler/targets/Target.js +57 -47
  67. package/source/class/qx/tool/compiler/targets/meta/AbstractJavascriptMeta.js +25 -18
  68. package/source/class/qx/tool/compiler/targets/meta/BootJs.js +16 -16
  69. package/source/class/qx/tool/compiler/targets/meta/PolyfillJs.js +11 -3
  70. package/source/class/qx/tool/compiler/targets/meta/Uglify.js +10 -10
  71. package/source/class/qx/ui/core/Widget.js +70 -0
  72. package/source/class/qx/ui/decoration/MLinearBackgroundGradient.js +2 -1
  73. package/source/class/qx/ui/form/ComboBox.js +8 -3
  74. package/source/class/qx/ui/form/DateField.js +16 -1
  75. package/source/class/qx/ui/form/MenuButton.js +8 -4
  76. package/source/class/qx/ui/form/SelectBox.js +8 -3
  77. package/source/class/qx/ui/menu/AbstractButton.js +12 -8
  78. package/source/class/qx/ui/menu/Menu.js +18 -8
  79. package/source/class/qx/ui/table/pane/Model.js +10 -4
  80. package/source/class/qx/ui/window/Window.js +8 -0
  81. package/source/class/qx/util/format/DateFormat.js +44 -17
  82. package/source/resource/qx/tool/loadsass.js +6 -4
  83. package/source/resource/qx/tool/schema/compile-1-0-0.json +6 -11
  84. package/source/translation/hr.po +297 -0
  85. package/lib/resource/qx/static/blank.gif +0 -0
  86. package/source/class/qx/io/remote/Exchange.js +0 -1063
  87. package/source/class/qx/io/remote/Request.js +0 -1021
  88. package/source/class/qx/io/remote/RequestQueue.js +0 -521
  89. package/source/class/qx/io/remote/Response.js +0 -137
  90. package/source/class/qx/io/remote/Rpc.js +0 -1075
  91. package/source/class/qx/io/remote/RpcError.js +0 -198
  92. package/source/class/qx/io/remote/__init__.js +0 -88
  93. package/source/class/qx/io/remote/transport/Abstract.js +0 -513
  94. package/source/class/qx/io/remote/transport/Iframe.js +0 -652
  95. package/source/class/qx/io/remote/transport/Script.js +0 -475
  96. package/source/class/qx/io/remote/transport/XmlHttp.js +0 -1019
  97. package/source/class/qx/io/remote/transport/__init__.js +0 -3
  98. package/source/class/qx/test/io/remote/AbstractRequest.js +0 -150
  99. package/source/class/qx/test/io/remote/RequestIframe.js +0 -105
  100. package/source/class/qx/test/io/remote/RequestXhr.js +0 -151
  101. package/source/class/qx/test/io/remote/Rpc.js +0 -205
  102. package/source/class/qx/test/io/remote/__init__.js +0 -4
  103. package/source/class/qx/test/io/remote/transport/Iframe.js +0 -67
  104. package/source/class/qx/test/io/remote/transport/XmlHttp.js +0 -133
  105. package/source/class/qx/test/io/remote/transport/__init__.js +0 -4
@@ -64,7 +64,7 @@ qx.Class.define("qx.tool.cli.commands.package.Install", {
64
64
  },
65
65
  "save": {
66
66
  alias: "s",
67
- default: true,
67
+ default: false,
68
68
  describe: "Save the libraries as permanent dependencies"
69
69
  },
70
70
  "from-path": {
@@ -99,6 +99,14 @@ qx.Class.define("qx.tool.cli.commands.package.Publish", {
99
99
  };
100
100
  }
101
101
  },
102
+ events: {
103
+ /**
104
+ * Fired before commit happens. Data is an object with
105
+ * version: new_version,
106
+ * argv: this.argv
107
+ */
108
+ "beforeCommit": "qx.event.type.Data"
109
+ },
102
110
 
103
111
  members: {
104
112
 
@@ -337,6 +345,12 @@ qx.Class.define("qx.tool.cli.commands.package.Publish", {
337
345
  }
338
346
  }
339
347
 
348
+ await this.fireDataEventAsync("beforeCommit", {
349
+ version: new_version,
350
+ argv: this.argv
351
+ });
352
+
353
+
340
354
  if (argv.dryrun) {
341
355
  qx.tool.compiler.Console.info(`Dry run: not creating tag and release '${tag}' of ${repo_name}...`);
342
356
  return;
@@ -43,6 +43,9 @@ function collapseMemberExpression(node) {
43
43
  if (node.type == "ThisExpression") {
44
44
  return "this";
45
45
  }
46
+ if (node.type == "Super") {
47
+ return "super";
48
+ }
46
49
  if (node.type == "Identifier") {
47
50
  return node.name;
48
51
  }
@@ -362,7 +365,10 @@ qx.Class.define("qx.tool.compiler.ClassFile", {
362
365
  [ require.resolve("@babel/preset-typescript") ],
363
366
  [ require.resolve("@babel/preset-react"), qx.tool.compiler.ClassFile.JSX_OPTIONS ]
364
367
  ],
365
- parserOpts: { sourceType: "script" },
368
+ parserOpts: {
369
+ allowSuperOutsideMethod: true,
370
+ sourceType: "script"
371
+ },
366
372
  passPerPreset: true
367
373
  };
368
374
  if (extraPreset[0].plugins.length) {
@@ -780,7 +786,9 @@ qx.Class.define("qx.tool.compiler.ClassFile", {
780
786
  return meta;
781
787
  }
782
788
 
789
+ var es6ClassDeclarations = 0;
783
790
  var needsQxCoreEnvironment = false;
791
+
784
792
  var COLLECT_CLASS_NAMES_VISITOR = {
785
793
  MemberExpression(path) {
786
794
  var self = this;
@@ -794,6 +802,15 @@ qx.Class.define("qx.tool.compiler.ClassFile", {
794
802
  };
795
803
 
796
804
  const CODE_ELIMINATION_VISITOR = {
805
+ ClassBody: {
806
+ enter(path) {
807
+ es6ClassDeclarations++;
808
+ },
809
+ exit(path) {
810
+ es6ClassDeclarations--;
811
+ }
812
+ },
813
+
797
814
  CallExpression(path) {
798
815
  const name = collapseMemberExpression(path.node.callee);
799
816
 
@@ -921,8 +938,12 @@ qx.Class.define("qx.tool.compiler.ClassFile", {
921
938
  let nextJsonPath = jsonPath ? jsonPath + "." : "";
922
939
  node.properties.forEach(function(prop) {
923
940
  var key = prop.key.name;
924
- var value = collectJson(prop.value, isProperties, nextJsonPath + key);
925
- result[key] = value;
941
+ if (prop.type == "ObjectMethod") {
942
+ result[key] = "[[ ObjectMethod Function ]]";
943
+ } else {
944
+ var value = collectJson(prop.value, isProperties, nextJsonPath + key);
945
+ result[key] = value;
946
+ }
926
947
  });
927
948
  } else if (node.type == "Literal" ||
928
949
  node.type == "StringLiteral" ||
@@ -1080,6 +1101,15 @@ qx.Class.define("qx.tool.compiler.ClassFile", {
1080
1101
  }
1081
1102
 
1082
1103
  var CLASS_DEF_VISITOR = {
1104
+ ClassBody: {
1105
+ enter(path) {
1106
+ es6ClassDeclarations++;
1107
+ },
1108
+ exit(path) {
1109
+ es6ClassDeclarations--;
1110
+ }
1111
+ },
1112
+
1083
1113
  ObjectMethod(path) {
1084
1114
  if (path.parentPath.parentPath != this.classDefPath) {
1085
1115
  path.skip();
@@ -1304,6 +1334,16 @@ qx.Class.define("qx.tool.compiler.ClassFile", {
1304
1334
  }
1305
1335
  },
1306
1336
 
1337
+ // Babel seems to be suppressing ClassDeclarations...
1338
+ ClassBody: {
1339
+ enter(path) {
1340
+ es6ClassDeclarations++;
1341
+ },
1342
+ exit(path) {
1343
+ es6ClassDeclarations--;
1344
+ }
1345
+ },
1346
+
1307
1347
  Literal(path) {
1308
1348
  if (typeof path.node.value == "string") {
1309
1349
  path.node.value = t.encodePrivate(path.node.value, false, path.loc);
@@ -1420,7 +1460,7 @@ qx.Class.define("qx.tool.compiler.ClassFile", {
1420
1460
  }
1421
1461
  }
1422
1462
 
1423
- if (types.isMemberExpression(path.node.callee)) {
1463
+ if (types.isMemberExpression(path.node.callee) || (es6ClassDeclarations == 0 && (path.node.callee.object?.type == "Super" || path.node.callee.type == "Super"))) {
1424
1464
  let name = collapseMemberExpression(path.node.callee);
1425
1465
  let thisAlias = null;
1426
1466
 
@@ -1431,7 +1471,7 @@ qx.Class.define("qx.tool.compiler.ClassFile", {
1431
1471
  // var that = this, args = arguments;
1432
1472
  // (function() { that.base(args); })();
1433
1473
  // ```
1434
- if (path.node.callee.object.type == "Identifier") {
1474
+ if (path.node.callee.object?.type == "Identifier") {
1435
1475
  let originalAlias = path.node.callee.object.name;
1436
1476
  let alias = originalAlias;
1437
1477
  let aliasIsThis = false;
@@ -1536,7 +1576,7 @@ qx.Class.define("qx.tool.compiler.ClassFile", {
1536
1576
  path.skip();
1537
1577
  path.traverse(VISITOR);
1538
1578
 
1539
- } else if (name == "this.base") {
1579
+ } else if (name == "this.base" || (es6ClassDeclarations == 0 && (name == "super" || name.startsWith("super.")))) {
1540
1580
  let expr;
1541
1581
 
1542
1582
  // For mixins, there is never a valid time to call this.base() in the constructor; but it is
@@ -1558,10 +1598,11 @@ qx.Class.define("qx.tool.compiler.ClassFile", {
1558
1598
  } else {
1559
1599
  expr = expandMemberExpression(t.__classMeta.superClass + ".prototype." + t.__classMeta.functionName + ".call");
1560
1600
  }
1561
- if (thisAlias) {
1562
- path.node.arguments[0] = types.identifier(thisAlias);
1601
+ let thisArgument = thisAlias ? types.identifier(thisAlias) : types.thisExpression();
1602
+ if (name.startsWith("super")) {
1603
+ path.node.arguments.unshift(thisArgument);
1563
1604
  } else {
1564
- path.node.arguments[0] = types.thisExpression();
1605
+ path.node.arguments[0] = thisArgument;
1565
1606
  }
1566
1607
  let callExpr = types.callExpression(expr, path.node.arguments);
1567
1608
  path.replaceWith(callExpr);
@@ -1727,25 +1768,24 @@ qx.Class.define("qx.tool.compiler.ClassFile", {
1727
1768
  },
1728
1769
 
1729
1770
  ObjectMethod(path) {
1730
- if (t.__classMeta) {
1731
- // Methods within a top level object (ie "members" or "statics"), record the method name and meta data
1732
- if (t.__classMeta._topLevel &&
1733
- t.__classMeta._topLevel.path == path.parentPath.parentPath) {
1734
- t.__classMeta.functionName = getKeyName(path.node.key);
1735
- makeMeta(t.__classMeta._topLevel.keyName, t.__classMeta.functionName, path.node);
1736
- path.skip();
1737
- enterFunction(path);
1738
- path.traverse(VISITOR);
1739
- exitFunction(path);
1740
- t.__classMeta.functionName = null;
1771
+ // Methods within a top level object (ie "members" or "statics"), record the method name and meta data
1772
+ if (t.__classMeta &&
1773
+ t.__classMeta._topLevel &&
1774
+ t.__classMeta._topLevel.path == path.parentPath.parentPath) {
1775
+ t.__classMeta.functionName = getKeyName(path.node.key);
1776
+ makeMeta(t.__classMeta._topLevel.keyName, t.__classMeta.functionName, path.node);
1777
+ path.skip();
1778
+ enterFunction(path);
1779
+ path.traverse(VISITOR);
1780
+ exitFunction(path);
1781
+ t.__classMeta.functionName = null;
1741
1782
 
1742
- // Otherwise traverse method as normal
1743
- } else {
1744
- path.skip();
1745
- enterFunction(path);
1746
- path.traverse(VISITOR);
1747
- exitFunction(path);
1748
- }
1783
+ // Otherwise traverse method as normal
1784
+ } else {
1785
+ path.skip();
1786
+ enterFunction(path);
1787
+ path.traverse(VISITOR);
1788
+ exitFunction(path);
1749
1789
  }
1750
1790
  },
1751
1791
 
@@ -0,0 +1,368 @@
1
+ /* ************************************************************************
2
+
3
+ qooxdoo - the new era of web development
4
+
5
+ http://qooxdoo.org
6
+
7
+ Copyright:
8
+ 2021 Zenesis Ltd
9
+
10
+ License:
11
+ MIT: https://opensource.org/licenses/MIT
12
+ See the LICENSE file in the project's top-level directory for details.
13
+
14
+ Authors:
15
+ * John Spackman (john.spackman@zenesis.com, @johnspackman)
16
+
17
+ ************************************************************************ */
18
+
19
+ const fs = require("fs");
20
+ const path = require("path");
21
+ const babelCore = require("@babel/core");
22
+
23
+ const types = require("@babel/types");
24
+ const babylon = require("@babel/parser");
25
+ const prettier = require("prettier");
26
+
27
+ /**
28
+ * Helper method that collapses the MemberExpression into a string
29
+ * @param node
30
+ * @returns {string}
31
+ */
32
+ function collapseMemberExpression(node) {
33
+ var done = false;
34
+ function doCollapse(node) {
35
+ if (node.type == "ThisExpression") {
36
+ return "this";
37
+ }
38
+ if (node.type == "Identifier") {
39
+ return node.name;
40
+ }
41
+ if (node.type == "ArrayExpression") {
42
+ var result = [];
43
+ node.elements.forEach(element => result.push(doCollapse(element)));
44
+ return result;
45
+ }
46
+ if (node.type != "MemberExpression") {
47
+ return "(" + node.type + ")";
48
+ }
49
+ if (types.isIdentifier(node.object)) {
50
+ let str = node.object.name;
51
+ if (node.property.name) {
52
+ str += "." + node.property.name;
53
+ } else {
54
+ done = true;
55
+ }
56
+ return str;
57
+ }
58
+ var str;
59
+ if (node.object.type == "ArrayExpression") {
60
+ str = "[]";
61
+ } else {
62
+ str = doCollapse(node.object);
63
+ }
64
+ if (done) {
65
+ return str;
66
+ }
67
+ // `computed` is set if the expression is a subscript, eg `abc[def]`
68
+ if (node.computed) {
69
+ done = true;
70
+ } else if (node.property.name) {
71
+ str += "." + node.property.name;
72
+ } else {
73
+ done = true;
74
+ }
75
+ return str;
76
+ }
77
+
78
+ return doCollapse(node);
79
+ }
80
+
81
+ /**
82
+ * Processes a .js source file and tries to upgrade to ES6 syntax
83
+ *
84
+ * This is a reliable but fairly unintrusive upgrade, provided that `arrowFunctions` property is
85
+ * `careful`. The issue is that this code: `setTimeout(function() { something(); })` can be
86
+ * changed to `setTimeout(() => something())` and that is often desirable, but it also means that
87
+ * the `this` will be different because an arrow function always has the `this` from where the
88
+ * code is written.
89
+ *
90
+ * However, if you use an API which changes `this` then the switch to arrow functions will break
91
+ * your code. Mostly, in Qooxdoo, changes to `this` are done via an explicit API (eg
92
+ * `obj.addListener("changeXyx", function() {}, this)`) and so those known APIs can be translated,
93
+ * but there are places which do not work this way (eg the unit tests `qx.dev.unit.TestCase.resume()`).
94
+ * Third party integrations are of course completely unknown.
95
+ *
96
+ * If `arrowFunctions` is set to aggressive, then all functions are switched to arrow functions except
97
+ * where there is a known API that does not support it (eg any call to `.resume` in a test class); this
98
+ * could break your code.
99
+ *
100
+ * If `arrowFunctions is set to `careful` (the default), then functions are only switched to arrow
101
+ * functions where the API is known (eg `.addListener`).
102
+ *
103
+ * The final step is that the ES6ify will use https://prettier.io/ to reformat the code, and will use
104
+ * the nearest `prettierrc.json` for configuration
105
+ */
106
+ qx.Class.define("qx.tool.compiler.Es6ify", {
107
+ extend: qx.core.Object,
108
+
109
+ construct(filename) {
110
+ this.base(arguments);
111
+ this.__filename = filename;
112
+ },
113
+
114
+ properties: {
115
+ /** Whether to convert functions to arrow functions; careful means only on things like addListener callbacks */
116
+ arrowFunctions: {
117
+ init: "careful",
118
+ check: [ "never", "always", "careful", "aggressive" ],
119
+ nullable: true
120
+ },
121
+
122
+ /** Whether to overwrite the original file */
123
+ overwrite: {
124
+ init: false,
125
+ check: "Boolean"
126
+ }
127
+ },
128
+
129
+ members: {
130
+ __filename: null,
131
+
132
+ async transform() {
133
+ let src = await fs.promises.readFile(this.__filename, "utf8");
134
+
135
+ let babelConfig = {};
136
+ let options = qx.lang.Object.clone(babelConfig.options || {}, true);
137
+ options.modules = false;
138
+ let plugins = [
139
+ require("@babel/plugin-syntax-jsx"),
140
+ this.__pluginFunctionExpressions()
141
+ ];
142
+ if (this.getArrowFunctions() != "never") {
143
+ plugins.push(this.__pluginArrowFunctions());
144
+ }
145
+ plugins.push(this.__pluginRemoveUnnecessaryThis());
146
+ plugins.push(this.__pluginSwitchToSuper());
147
+ var config = {
148
+ ast: true,
149
+ babelrc: false,
150
+ sourceFileName: this.__filename,
151
+ filename: this.__filename,
152
+ sourceMaps: false,
153
+ presets: [
154
+ [
155
+ {
156
+ plugins: plugins
157
+ }
158
+ ]
159
+ ],
160
+ parserOpts: {
161
+ allowSuperOutsideMethod: true,
162
+ sourceType: "script"
163
+ },
164
+ generatorOpts: {
165
+ retainLines: true
166
+ },
167
+ passPerPreset: true
168
+ };
169
+ let result = babelCore.transform(src, config);
170
+
171
+ let prettierConfig = await prettier.resolveConfig(this.__filename, { editorConfig: true })||{};
172
+ prettierConfig.parser = "babel";
173
+ let prettyCode = prettier.format(result.code, prettierConfig);
174
+
175
+ let outname = this.__filename + (this.isOverwrite() ? "" : ".es6ify");
176
+ await fs.promises.writeFile(outname, prettyCode, "utf8");
177
+ },
178
+
179
+ /**
180
+ * Plugin that converts object properties which are functions into object methods, eg
181
+ * ```
182
+ * {
183
+ * myMethod: function() {}
184
+ * }
185
+ * ```
186
+ * becomes
187
+ * ```
188
+ * {
189
+ * myMethod() {}
190
+ * }
191
+ * ```
192
+ * @returns
193
+ */
194
+ __pluginFunctionExpressions() {
195
+ return {
196
+ visitor: {
197
+ ObjectExpression(path) {
198
+ for (let i = 0; i < path.node.properties.length; i++) {
199
+ let propNode = path.node.properties[i];
200
+ if (
201
+ propNode.type == "ObjectProperty" &&
202
+ propNode.value.type == "FunctionExpression"
203
+ ) {
204
+ let replacement = types.objectMethod(
205
+ "method",
206
+ propNode.key,
207
+ propNode.value.params,
208
+ propNode.value.body,
209
+ propNode.value.computed,
210
+ propNode.value.generator,
211
+ propNode.value.async
212
+ );
213
+ replacement.loc = propNode.loc;
214
+ replacement.start = propNode.start;
215
+ replacement.end = propNode.end;
216
+ replacement.leadingComments = propNode.leadingComments;
217
+ path.node.properties[i] = replacement;
218
+ }
219
+ }
220
+ }
221
+ }
222
+ };
223
+ },
224
+
225
+ __toArrowExpression(argNode) {
226
+ let body = argNode.body;
227
+ if (body.body.length == 1 && body.body[0].type == "ReturnStatement") {
228
+ body = body.body[0].argument;
229
+ }
230
+ let replacement = types.arrowFunctionExpression(
231
+ argNode.params,
232
+ body,
233
+ argNode.async
234
+ );
235
+ replacement.loc = argNode.loc;
236
+ replacement.start = argNode.start;
237
+ replacement.end = argNode.end;
238
+ replacement.leadingComments = argNode.leadingComments;
239
+ return replacement;
240
+ },
241
+
242
+ /**
243
+ * Tries to convert functions into arrow functions
244
+ * @returns
245
+ */
246
+ __pluginArrowFunctions() {
247
+ let t = this;
248
+ const isTest = this.__filename.indexOf("/test/") > -1;
249
+ let arrowFunctions = this.getArrowFunctions();
250
+
251
+ return {
252
+ visitor: {
253
+ CallExpression(path) {
254
+ if (path.node.callee.type == "MemberExpression") {
255
+ let callee = collapseMemberExpression(path.node.callee);
256
+ if (arrowFunctions == "careful") {
257
+ if (!callee.endsWith(".addListener")) {
258
+ return;
259
+ }
260
+ if (
261
+ path.node.arguments.length != 3 ||
262
+ path.node.arguments[0].type != "StringLiteral" ||
263
+ path.node.arguments[1].type != "ArrowFunctionExpression" ||
264
+ path.node.arguments[2].type != "ThisExpression"
265
+ ) {
266
+ return;
267
+ }
268
+
269
+ } else if (arrowFunctions == "aggressive") {
270
+ if (callee == "qx.event.GlobalError.observeMethod" ||
271
+ callee == "this.assertException" ||
272
+ callee == "this.assertEventFired" ||
273
+ callee == "qx.core.Assert.assertEventFired" ||
274
+ (isTest && callee.endsWith(".resume"))) {
275
+ return;
276
+ }
277
+ }
278
+ } else if (arrowFunctions == "careful") {
279
+ return;
280
+ }
281
+ for (let i = 0; i < path.node.arguments.length; i++){
282
+ let argNode = path.node.arguments[i];
283
+ if (argNode.type == "FunctionExpression") {
284
+ path.node.arguments[i] = t.__toArrowExpression(argNode);
285
+ }
286
+ }
287
+ }
288
+ }
289
+ }
290
+ },
291
+
292
+ /**
293
+ * Where a function has been translated into an arrow function, the this binding is not needed
294
+ * and can be removed
295
+ * @returns
296
+ */
297
+ __pluginRemoveUnnecessaryThis() {
298
+ return {
299
+ visitor: {
300
+ CallExpression(path) {
301
+ if (
302
+ path.node.callee.type == "MemberExpression" &&
303
+ path.node.callee.object.type == "ThisExpression" &&
304
+ path.node.callee.property.type == "Identifier" &&
305
+ path.node.callee.property.name == "addListener" &&
306
+ path.node.arguments.length == 3 &&
307
+ path.node.arguments[0].type == "StringLiteral" &&
308
+ path.node.arguments[1].type == "ArrowFunctionExpression" &&
309
+ path.node.arguments[2].type == "ThisExpression"
310
+ ) {
311
+ qx.lang.Array.removeAt(path.node.arguments, 2);
312
+ }
313
+ }
314
+ }
315
+ }
316
+ },
317
+
318
+ /**
319
+ * Translates `this.base(arguments...)` into `super`
320
+ * @returns
321
+ */
322
+ __pluginSwitchToSuper() {
323
+ let methodNameStack = [];
324
+ function peekMethodName() {
325
+ for (let i = methodNameStack.length - 1; i >= 0; i--) {
326
+ let methodName = methodNameStack[i];
327
+ if (methodName) {
328
+ return methodName;
329
+ }
330
+ }
331
+ return null;
332
+ }
333
+ return {
334
+ visitor: {
335
+ ObjectMethod: {
336
+ enter(path) {
337
+ methodNameStack.push(path.node.key.name||null);
338
+ },
339
+ exit(path) {
340
+ methodNameStack.pop();
341
+ }
342
+ },
343
+ CallExpression(path) {
344
+ if (
345
+ path.node.callee.type == "MemberExpression" &&
346
+ path.node.callee.object.type == "ThisExpression" &&
347
+ path.node.callee.property.type == "Identifier" &&
348
+ path.node.callee.property.name == "base" &&
349
+ path.node.arguments.length >= 1
350
+ ) {
351
+ let args = qx.lang.Array.clone(path.node.arguments);
352
+ args.shift();
353
+ let methodName = peekMethodName();
354
+ if (methodName == "construct") {
355
+ path.node.callee = types.super();
356
+ path.node.arguments = args;
357
+ } else if (methodName) {
358
+ let replacement = types.memberExpression(types.super(), types.identifier(methodName), false, false);
359
+ path.node.callee = replacement;
360
+ path.node.arguments = args;
361
+ }
362
+ }
363
+ }
364
+ }
365
+ }
366
+ }
367
+ }
368
+ });
@@ -86,7 +86,8 @@ qx.Class.define("qx.tool.compiler.makers.AppMaker", {
86
86
  },
87
87
  this.getEnvironment(),
88
88
  target.getDefaultEnvironment(),
89
- target.getEnvironment());
89
+ target.getEnvironment()
90
+ );
90
91
 
91
92
  let preserve = target.getPreserveEnvironment();
92
93
  if (preserve) {