Skip to content

Commit

Permalink
[FEATURE] ES2023 Support
Browse files Browse the repository at this point in the history
Ensures valid build outputs also for projects using latest ES2023 syntax.

Hashbangs e.g. '#!/usr/bin/env node' are allowed in source files but won't be included in bundles (e.g. Component-preload.js) by UI5 Tooling.

JIRA: CPOUI5FOUNDATION-850
  • Loading branch information
flovogt committed Jun 24, 2024
1 parent e26d637 commit 097049d
Show file tree
Hide file tree
Showing 23 changed files with 427 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module.exports = {
},
"env": {
"node": true,
"es2022": true
"es2023": true
},
"extends": ["eslint:recommended", "plugin:ava/recommended", "google"],
"plugins": [
Expand Down
8 changes: 8 additions & 0 deletions lib/lbt/bundle/Builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ function makeStringLiteral(str) {
}) + "'";
}

function removeHashbang(str) {
return str.replace(/^#!(.*)/, "");
}

function isEmptyBundle(resolvedBundle) {
return resolvedBundle.sections.every((section) => section.modules.length === 0);
}
Expand Down Expand Up @@ -278,6 +282,7 @@ class BundleBuilder {
async writeRawModule(moduleName, resource) {
this.outW.ensureNewLine();
let moduleContent = (await resource.buffer()).toString();
moduleContent = removeHashbang(moduleContent);
if (this.options.sourceMap) {
let moduleSourceMap;
({moduleContent, moduleSourceMap} =
Expand Down Expand Up @@ -384,6 +389,7 @@ class BundleBuilder {
// console.log("Processing " + moduleName);
const resource = await this.pool.findResourceWithInfo(moduleName);
let moduleContent = (await resource.buffer()).toString();
moduleContent = removeHashbang(moduleContent);
let moduleSourceMap;
if (this.options.sourceMap) {
({moduleContent, moduleSourceMap} =
Expand Down Expand Up @@ -444,6 +450,7 @@ class BundleBuilder {
// The module should be written to a new line in order for dev-tools to map breakpoints to it
outW.ensureNewLine();
let moduleContent = (await resource.buffer()).toString();
moduleContent = removeHashbang(moduleContent);
if (this.options.sourceMap) {
let moduleSourceMap;
({moduleContent, moduleSourceMap} =
Expand All @@ -463,6 +470,7 @@ class BundleBuilder {
log.warn(
`Module ${moduleName} requires top level scope and can only be embedded as a string (requires 'eval')`);
let moduleContent = (await resource.buffer()).toString();
moduleContent = removeHashbang(moduleContent);
if (this.options.sourceMap) {
// We are actually not interested in the source map this module might contain,
// but we should make sure to remove any "sourceMappingURL" from the module content before
Expand Down
2 changes: 1 addition & 1 deletion lib/lbt/utils/parseUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const hasOwn = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
* - Adjust the JSModuleAnalyzer test "Check for consistency between VisitorKeys and EnrichedVisitorKeys"
* (See comments in test for details)
*/
export const ecmaVersion = 2022;
export const ecmaVersion = 2023;

export function parseJS(code, userOptions = {}) {
// allowed options and their defaults
Expand Down
16 changes: 16 additions & 0 deletions test/expected/build/application.m/dest/Component-dbg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
sap.ui.define(["sap/ui/core/UIComponent", "sap/ui/core/mvc/View"], (UIComponent, View) => {
"use strict";
return UIComponent.extend("application.m.Component", {
metadata: {
manifest: "json",
interfaces: [
"sap.ui.core.IAsyncContentCreation"
]
},
createContent() {
return View.create({
viewName: "module:application/m/MyView"
})
}
});
});
12 changes: 12 additions & 0 deletions test/expected/build/application.m/dest/Component-preload.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions test/expected/build/application.m/dest/Component.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/expected/build/application.m/dest/Component.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions test/expected/build/application.m/dest/MyView-dbg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env node
sap.ui.define([
"sap/ui/core/mvc/View",
"sap/m/Button"
], (View, Button) => {
"use strict";
return View.extend("application.m.MyView", {
async createContent() {
return new Button({
id: this.createId("myButton"),
text: "My Button"
});
}
});
});
3 changes: 3 additions & 0 deletions test/expected/build/application.m/dest/MyView.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/expected/build/application.m/dest/MyView.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions test/expected/build/application.m/dest/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Application M</title>

<script id="sap-ui-bootstrap"
src="resources/sap-ui-core.js"
data-sap-ui-xx-waitForTheme="true"
data-sap-ui-theme="sap_horizon"
data-sap-ui-resourceRoots='{
"application.m": "./"
}'
data-sap-ui-onInit="module:sap/ui/core/ComponentSupport"
data-sap-ui-compatVersion="edge"
data-sap-ui-async="true">
</script>
</head>

<body class="sapUiBody">
<div data-sap-ui-component data-name="application.m" data-id="container" data-settings='{"id" : "m"}'></div>
</body>
</html>
23 changes: 23 additions & 0 deletions test/expected/build/application.m/dest/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"_version": "1.21.0",
"sap.app": {
"id": "application.m",
"type": "application",
"applicationVersion": {
"version": "1.0.0"
}
},
"sap.ui5": {
"contentDensities": {
"compact": true,
"cozy": true
},
"dependencies": {
"minUI5Version": "1.108.0",
"libs": {
"sap.ui.core": {},
"sap.m": {}
}
}
}
}
8 changes: 8 additions & 0 deletions test/fixtures/application.m/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "application.m",
"version": "1.0.0",
"description": "Simple SAPUI5 based application",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}
}
5 changes: 5 additions & 0 deletions test/fixtures/application.m/ui5.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
specVersion: "2.6"
type: application
metadata:
name: application.m
16 changes: 16 additions & 0 deletions test/fixtures/application.m/webapp/Component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
sap.ui.define(["sap/ui/core/UIComponent", "sap/ui/core/mvc/View"], (UIComponent, View) => {
"use strict";
return UIComponent.extend("application.m.Component", {
metadata: {
manifest: "json",
interfaces: [
"sap.ui.core.IAsyncContentCreation"
]
},
createContent() {
return View.create({
viewName: "module:application/m/MyView"
})
}
});
});
15 changes: 15 additions & 0 deletions test/fixtures/application.m/webapp/MyView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env node
sap.ui.define([
"sap/ui/core/mvc/View",
"sap/m/Button"
], (View, Button) => {
"use strict";
return View.extend("application.m.MyView", {
async createContent() {
return new Button({
id: this.createId("myButton"),
text: "My Button"
});
}
});
});
24 changes: 24 additions & 0 deletions test/fixtures/application.m/webapp/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Application M</title>

<script id="sap-ui-bootstrap"
src="resources/sap-ui-core.js"
data-sap-ui-xx-waitForTheme="true"
data-sap-ui-theme="sap_horizon"
data-sap-ui-resourceRoots='{
"application.m": "./"
}'
data-sap-ui-onInit="module:sap/ui/core/ComponentSupport"
data-sap-ui-compatVersion="edge"
data-sap-ui-async="true">
</script>
</head>

<body class="sapUiBody">
<div data-sap-ui-component data-name="application.m" data-id="container" data-settings='{"id" : "m"}'></div>
</body>
</html>
23 changes: 23 additions & 0 deletions test/fixtures/application.m/webapp/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"_version": "1.21.0",
"sap.app": {
"id": "application.m",
"type": "application",
"applicationVersion": {
"version": "1.0.0"
}
},
"sap.ui5": {
"contentDensities": {
"compact": true,
"cozy": true
},
"dependencies": {
"minUI5Version": "1.108.0",
"libs": {
"sap.ui.core": {},
"sap.m": {}
}
}
}
}
21 changes: 21 additions & 0 deletions test/lib/builder/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const applicationIPath = path.join(__dirname, "..", "..", "fixtures", "applicati
const applicationJPath = path.join(__dirname, "..", "..", "fixtures", "application.j");
const applicationKPath = path.join(__dirname, "..", "..", "fixtures", "application.k");
const applicationLPath = path.join(__dirname, "..", "..", "fixtures", "application.l");
const applicationMPath = path.join(__dirname, "..", "..", "fixtures", "application.m");
const applicationØPath = path.join(__dirname, "..", "..", "fixtures", "application.ø");
const collectionPath = path.join(__dirname, "..", "..", "fixtures", "collection");
const libraryDPath = path.join(__dirname, "..", "..", "fixtures", "library.d");
Expand Down Expand Up @@ -522,6 +523,26 @@ test.serial("Build application.l: minification excludes, w/ namespace", async (t
t.pass();
});

test.serial("Build application.m: bundle should not contain hashbang but an empty line", async (t) => {
const destPath = "./test/tmp/build/application.m/dest";
const expectedPath = path.join("test", "expected", "build", "application.m", "dest");

const graph = await graphFromPackageDependencies({
cwd: applicationMPath
});
graph.setTaskRepository(taskRepository);
await graph.build({
destPath
});

const expectedFiles = await findFiles(expectedPath);
// Check for all directories and files
await directoryDeepEqual(t, destPath, expectedPath);
// Check for all file contents
await checkFileContentsIgnoreLineFeeds(t, expectedFiles, expectedPath, destPath);
t.pass();
});

test.serial("Build application.ø", async (t) => {
const destPath = "./test/tmp/build/application.ø/dest";
const expectedPath = path.join("test", "expected", "build", "application.ø", "dest");
Expand Down
Loading

0 comments on commit 097049d

Please sign in to comment.