From 2b8a1d35f52d02842456915004ec103c9b42fd2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Tue, 4 Nov 2025 08:38:05 +0100 Subject: [PATCH 01/16] LPD-69958 Undo "Hide JS configuration options for the next release of DXP (since it is currently disabled)" --- .../frontend-js/frontend-js-web/build.gradle | 1 - .../FrontendCachingConfiguration.java | 7 ----- ...hingConfigurationVisibilityController.java | 31 ------------------- 3 files changed, 39 deletions(-) delete mode 100644 modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/configuration/admin/display/FrontendCachingConfigurationVisibilityController.java diff --git a/modules/apps/frontend-js/frontend-js-web/build.gradle b/modules/apps/frontend-js/frontend-js-web/build.gradle index ff1d8e83304576..4fac57ab3ee700 100644 --- a/modules/apps/frontend-js/frontend-js-web/build.gradle +++ b/modules/apps/frontend-js/frontend-js-web/build.gradle @@ -9,7 +9,6 @@ dependencies { compileOnly group: "org.osgi", name: "org.osgi.service.cm", version: "1.6.0" compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations", version: "1.4.0" compileOnly group: "org.osgi", name: "osgi.core", version: "6.0.0" - compileOnly project(":apps:configuration-admin:configuration-admin-api") compileOnly project(":apps:frontend-js:frontend-js-importmaps-extender-api") compileOnly project(":apps:frontend-js:frontend-js-loader-modules-extender-api") compileOnly project(":apps:portal-configuration:portal-configuration-module-configuration-api") diff --git a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/configuration/FrontendCachingConfiguration.java b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/configuration/FrontendCachingConfiguration.java index 578abd6943093e..78973d971b490e 100644 --- a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/configuration/FrontendCachingConfiguration.java +++ b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/configuration/FrontendCachingConfiguration.java @@ -7,7 +7,6 @@ import aQute.bnd.annotation.metatype.Meta; -import com.liferay.portal.configuration.metatype.annotations.ExtendedAttributeDefinition; import com.liferay.portal.configuration.metatype.annotations.ExtendedObjectClassDefinition; /** @@ -30,9 +29,6 @@ public interface FrontendCachingConfiguration { ) public long cssStyleSheetsMaxAge(); - @ExtendedAttributeDefinition( - visibilityControllerKey = "com.liferay.frontend.js.web.internal.configuration.admin.display.FrontendCachingConfigurationVisibilityController" - ) @Meta.AD( deflt = "86400", description = "es-modules-max-age-help", name = "es-modules-max-age", required = false @@ -46,9 +42,6 @@ public interface FrontendCachingConfiguration { ) public boolean sendNoCacheForCSSStyleSheets(); - @ExtendedAttributeDefinition( - visibilityControllerKey = "com.liferay.frontend.js.web.internal.configuration.admin.display.FrontendCachingConfigurationVisibilityController" - ) @Meta.AD( deflt = "false", description = "send-no-cache-for-es-modules-help", name = "send-no-cache-for-es-modules", required = false diff --git a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/configuration/admin/display/FrontendCachingConfigurationVisibilityController.java b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/configuration/admin/display/FrontendCachingConfigurationVisibilityController.java deleted file mode 100644 index e6a6c08e58d38b..00000000000000 --- a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/configuration/admin/display/FrontendCachingConfigurationVisibilityController.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * SPDX-FileCopyrightText: (c) 2025 Liferay, Inc. https://liferay.com - * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06 - */ - -package com.liferay.frontend.js.web.internal.configuration.admin.display; - -import com.liferay.configuration.admin.display.ConfigurationVisibilityController; -import com.liferay.portal.configuration.metatype.annotations.ExtendedObjectClassDefinition; - -import java.io.Serializable; - -import org.osgi.service.component.annotations.Component; - -/** - * @author Iván Zaera Avellón - */ -@Component(service = ConfigurationVisibilityController.class) -public class FrontendCachingConfigurationVisibilityController - implements ConfigurationVisibilityController { - - @Override - public boolean isVisible( - ExtendedObjectClassDefinition.Scope scope, Serializable scopePK) { - - // LPD-69957 - - return false; - } - -} \ No newline at end of file From 4fecebcb2c9c458846f130da70b99c6167d75a92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Thu, 25 Sep 2025 10:55:03 +0200 Subject: [PATCH 02/16] LPD-52709 Reenable Part 3 --- .../HashedFileFrontendResourceRequestHandler.java | 6 ------ .../HashedFileFrontendResourceRequestHandlerTest.java | 9 --------- 2 files changed, 15 deletions(-) diff --git a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/resource/handler/HashedFileFrontendResourceRequestHandler.java b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/resource/handler/HashedFileFrontendResourceRequestHandler.java index a5f2475ccd8c3c..a40561ac431ce4 100644 --- a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/resource/handler/HashedFileFrontendResourceRequestHandler.java +++ b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/resource/handler/HashedFileFrontendResourceRequestHandler.java @@ -56,12 +56,6 @@ public boolean canHandleRequest(HttpServletRequest httpServletRequest) { return true; } - // LPD-52709 - - if (true) { - return false; - } - String hashedFileURI = _hashedFilesRegistry.getHashedFileURI( requestURI); diff --git a/modules/apps/frontend-js/frontend-js-web/src/test/java/com/liferay/frontend/js/web/internal/resource/handler/HashedFileFrontendResourceRequestHandlerTest.java b/modules/apps/frontend-js/frontend-js-web/src/test/java/com/liferay/frontend/js/web/internal/resource/handler/HashedFileFrontendResourceRequestHandlerTest.java index ab5e4cf95f47dc..d8120282b6474b 100644 --- a/modules/apps/frontend-js/frontend-js-web/src/test/java/com/liferay/frontend/js/web/internal/resource/handler/HashedFileFrontendResourceRequestHandlerTest.java +++ b/modules/apps/frontend-js/frontend-js-web/src/test/java/com/liferay/frontend/js/web/internal/resource/handler/HashedFileFrontendResourceRequestHandlerTest.java @@ -32,7 +32,6 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.mockito.MockedStatic; @@ -63,12 +62,8 @@ public void tearDown() { } } - @Ignore @Test public void testCanHandleRequest() throws Exception { - - // LPD-52709 - _mockFallbackKeysSettingsUtil( HashMapBuilder.put( "maxAgeKey", RandomTestUtil.randomLong() @@ -132,12 +127,8 @@ public void testHandleRequestWithHash() throws Exception { Assert.assertFalse(frontendResource.isSendNoCache()); } - @Ignore @Test public void testHandleRequestWithNoConfiguration() throws Exception { - - // LPD-52709 - _mockFallbackKeysSettingsUtil(null); long maxAge = RandomTestUtil.randomLong(); From 83a2ab62222cf0294e0bdf12c0325a9be587162e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Tue, 4 Nov 2025 08:55:41 +0100 Subject: [PATCH 03/16] LPD-52709 Add hashes to JS bundles --- .../cssLoad/writeCSSExportsLoaderModules.mjs | 37 ++++++++++++++----- .../bundle/esbuild/bundleCSSExports.mjs | 1 + .../esbuild/bundleJavaScriptExports.mjs | 22 ++++++----- .../bundle/esbuild/bundleJavaScriptMain.mjs | 22 +++++------ .../esbuild/plugins/getScssLoaderPlugin.mjs | 4 +- .../bundle/esbuild/runEsbuild.mjs | 11 +++++- modules/_node-scripts/bundle/index.mjs | 3 +- 7 files changed, 66 insertions(+), 34 deletions(-) diff --git a/modules/_node-scripts/bundle/cssLoad/writeCSSExportsLoaderModules.mjs b/modules/_node-scripts/bundle/cssLoad/writeCSSExportsLoaderModules.mjs index 994aca6da2f88f..beec4df58a640f 100644 --- a/modules/_node-scripts/bundle/cssLoad/writeCSSExportsLoaderModules.mjs +++ b/modules/_node-scripts/bundle/cssLoad/writeCSSExportsLoaderModules.mjs @@ -6,8 +6,13 @@ import fs from 'fs/promises'; import path from 'path'; -import {BUILD_NPM_EXPORTS_PATH} from '../../util/constants.mjs'; +import { + BUILD_CSS_EXPORTS_PATH, + BUILD_NPM_EXPORTS_PATH, +} from '../../util/constants.mjs'; import getFlatName from '../../util/getFlatName.mjs'; +import calculateFileHash from '../util/calculateFileHash.mjs'; +import extractFileHash from '../util/extractFileHash.mjs'; import getCSSLoadJavaScript from '../util/getCSSLoadJavaScript.mjs'; export default async function writeCSSExportsLoaderModules( @@ -30,17 +35,31 @@ export default async function writeCSSExportsLoaderModules( async function writeCSSExportLoaderModule(webContextPath, moduleName) { const flatModuleName = getFlatName(moduleName); + const baseFlatModuleName = flatModuleName.substring( + 0, + flatModuleName.length - 4 + ); + + const cssFiles = await fs.readdir(path.join(BUILD_CSS_EXPORTS_PATH)); + + const cssFile = cssFiles.find((cssFile) => + cssFile.startsWith(`${baseFlatModuleName}.(`) + ); + + const cssFileHash = extractFileHash(cssFile); + + const source = getCSSLoadJavaScript( + webContextPath, + `__liferay__/css/${baseFlatModuleName}.(${cssFileHash}).css` + ); + + const hash = await calculateFileHash(source); + const cssLoaderPath = path.join( BUILD_NPM_EXPORTS_PATH, - `${flatModuleName}.js` + `${flatModuleName}.(${hash}).js` ); await fs.mkdir(path.dirname(cssLoaderPath), {recursive: true}); - await fs.writeFile( - cssLoaderPath, - getCSSLoadJavaScript( - webContextPath, - `__liferay__/css/${flatModuleName}` - ) - ); + await fs.writeFile(cssLoaderPath, source); } diff --git a/modules/_node-scripts/bundle/esbuild/bundleCSSExports.mjs b/modules/_node-scripts/bundle/esbuild/bundleCSSExports.mjs index 394a4b8ca745aa..c71cc9a99eeefd 100644 --- a/modules/_node-scripts/bundle/esbuild/bundleCSSExports.mjs +++ b/modules/_node-scripts/bundle/esbuild/bundleCSSExports.mjs @@ -30,6 +30,7 @@ async function bundle(moduleName) { const entryPoint = getEntryPoint(moduleName); const esbuildConfig = { + entryNames: '[dir]/[name].([hash])', entryPoints: [entryPoint], loader: { '.png': 'empty', diff --git a/modules/_node-scripts/bundle/esbuild/bundleJavaScriptExports.mjs b/modules/_node-scripts/bundle/esbuild/bundleJavaScriptExports.mjs index dbc1707a59933c..9818a77ae2b887 100644 --- a/modules/_node-scripts/bundle/esbuild/bundleJavaScriptExports.mjs +++ b/modules/_node-scripts/bundle/esbuild/bundleJavaScriptExports.mjs @@ -57,6 +57,7 @@ async function bundle( const esbuildConfig = { alias: projectAlias, bundle: true, + entryNames: '[dir]/[name].([hash])', entryPoints: [entryPoint], format: 'esm', outdir: BUILD_MAIN_EXPORTS_PATH, @@ -103,14 +104,17 @@ async function bundle( const flatModuleName = getFlatName(moduleName); - await runEsbuild(esbuildConfig, flatModuleName); + const {metafile} = await runEsbuild(esbuildConfig, flatModuleName); + const {outputs} = metafile; - await relocateSourcemap( - path.join( - BUILD_MAIN_EXPORTS_PATH, - 'exports', - `${flatModuleName}.js.map` - ), - projectWebContextPath - ); + await Promise.all([ + ...Object.keys(outputs).map(async (output) => { + if (output.endsWith('.map')) { + return relocateSourcemap( + path.join(output), + projectWebContextPath + ); + } + }), + ]); } diff --git a/modules/_node-scripts/bundle/esbuild/bundleJavaScriptMain.mjs b/modules/_node-scripts/bundle/esbuild/bundleJavaScriptMain.mjs index 2f0b9fa8d7afad..6b663512790730 100644 --- a/modules/_node-scripts/bundle/esbuild/bundleJavaScriptMain.mjs +++ b/modules/_node-scripts/bundle/esbuild/bundleJavaScriptMain.mjs @@ -41,6 +41,7 @@ export default async function bundleJavaScriptMain( const esbuildConfig = { alias: projectAlias, bundle: true, + entryNames: '[dir]/[name].([hash])', entryPoints: [ ...Object.keys(submodules).map((submoduleName) => ({ in: path.resolve(submodules[submoduleName]), @@ -97,19 +98,18 @@ export default async function bundleJavaScriptMain( ); } - await runEsbuild(esbuildConfig, 'main'); + const {metafile} = await runEsbuild(esbuildConfig, 'main'); + const {outputs} = metafile; await Promise.all([ - relocateSourcemap( - path.join(BUILD_MAIN_EXPORTS_PATH, 'index.js.map'), - projectWebContextPath - ), - ...Object.keys(submodules).map((submodule) => - relocateSourcemap( - path.join(BUILD_MAIN_EXPORTS_PATH, `${submodule}.js.map`), - projectWebContextPath - ) - ), + ...Object.keys(outputs).map(async (output) => { + if (output.endsWith('.map')) { + return relocateSourcemap( + path.join(output), + projectWebContextPath + ); + } + }), writeLanguageJSON(languageJSON), ]); } diff --git a/modules/_node-scripts/bundle/esbuild/plugins/getScssLoaderPlugin.mjs b/modules/_node-scripts/bundle/esbuild/plugins/getScssLoaderPlugin.mjs index c831b8a26c4092..6c3f63816730e6 100644 --- a/modules/_node-scripts/bundle/esbuild/plugins/getScssLoaderPlugin.mjs +++ b/modules/_node-scripts/bundle/esbuild/plugins/getScssLoaderPlugin.mjs @@ -29,6 +29,8 @@ export default function getScssLoaderPlugin(projectWebContextPath) { async (args) => { const projectPath = path.relative(SRC_PATH, args.path); + const projectBasePath = projectPath.replace(/\.scss$/, ''); + const cssFiles = await fs.readdir( path.join( BUILD_SASS_CACHE_PATH, @@ -36,8 +38,6 @@ export default function getScssLoaderPlugin(projectWebContextPath) { ) ); - const projectBasePath = projectPath.replace(/\.scss$/, ''); - const cssBasename = cssFiles.find((cssFile) => cssFile.startsWith( `${path.basename(projectBasePath)}.(` diff --git a/modules/_node-scripts/bundle/esbuild/runEsbuild.mjs b/modules/_node-scripts/bundle/esbuild/runEsbuild.mjs index bec8b08b981c0e..f350d5f76a19b9 100644 --- a/modules/_node-scripts/bundle/esbuild/runEsbuild.mjs +++ b/modules/_node-scripts/bundle/esbuild/runEsbuild.mjs @@ -8,17 +8,21 @@ import fs from 'fs/promises'; import path from 'path'; export default async function runEsbuild(esbuildConfig, configName) { - await Promise.all([ + const [result] = await Promise.all([ doRunEsbuild(esbuildConfig, configName), writeDebugEsbuildConfig(esbuildConfig, configName), ]); + + return result; } async function doRunEsbuild(esbuildesbuildConfig, configName) { + let result; + const start = performance.now(); try { - await esbuild.build({ + result = await esbuild.build({ define: { // Flag to use React 16 instead of React 18. See render.tsx in frontend-js-react-web. @@ -27,6 +31,7 @@ async function doRunEsbuild(esbuildesbuildConfig, configName) { ? 'true' : 'false', }, + metafile: true, minify: process.env.NODE_ENV === 'production', ...esbuildesbuildConfig, }); @@ -40,6 +45,8 @@ async function doRunEsbuild(esbuildesbuildConfig, configName) { console.log( `⌛ Esbuild for ${configName} took: ${(lapse / 1000).toFixed(3)} s` ); + + return result; } async function writeDebugEsbuildConfig(esbuildConfig, configName) { diff --git a/modules/_node-scripts/bundle/index.mjs b/modules/_node-scripts/bundle/index.mjs index afe5a857544803..a98c423bf181ed 100644 --- a/modules/_node-scripts/bundle/index.mjs +++ b/modules/_node-scripts/bundle/index.mjs @@ -74,7 +74,6 @@ export default async function main() { // CSS exports bundling bundleCSSExports(projectExports), - writeCSSExportsLoaderModules(projectExports, projectWebContextPath), // AMD bridging @@ -100,5 +99,7 @@ export default async function main() { ), ]); + await writeCSSExportsLoaderModules(projectExports, projectWebContextPath); + await writeTimings(start, endConfig); } From b9d4ab28345347c6cd596e77bb6fc43beb396cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Tue, 4 Nov 2025 09:14:23 +0100 Subject: [PATCH 04/16] LPD-52709 Remove dead code # breaking ## What portal-kernel/src/com/liferay/portal/kernel/frontend/esm/FrontendESMUtil.java The method `FrontendESMUtil.getScriptType()` has been removed. ## Why The method was dead code since ESM polyfills were removed. ---- --- .../JSImportMapsConfiguration.java | 33 ------- ...portMapsExtenderTopHeadDynamicInclude.java | 86 ++----------------- .../taglib/JSLoaderTopHeadDynamicInclude.java | 10 +-- .../taglib/aui/PortletDataRendererImpl.java | 5 +- .../src/portal-osgi-configuration.properties | 8 -- .../kernel/frontend/esm/FrontendESMUtil.java | 13 --- .../portal/kernel/frontend/esm/packageinfo | 2 +- .../portlet/render/PortletRenderUtil.java | 3 +- 8 files changed, 16 insertions(+), 144 deletions(-) delete mode 100644 modules/apps/frontend-js/frontend-js-importmaps-extender/src/main/java/com/liferay/frontend/js/importmaps/extender/internal/configuration/JSImportMapsConfiguration.java diff --git a/modules/apps/frontend-js/frontend-js-importmaps-extender/src/main/java/com/liferay/frontend/js/importmaps/extender/internal/configuration/JSImportMapsConfiguration.java b/modules/apps/frontend-js/frontend-js-importmaps-extender/src/main/java/com/liferay/frontend/js/importmaps/extender/internal/configuration/JSImportMapsConfiguration.java deleted file mode 100644 index 3bae08e59ef196..00000000000000 --- a/modules/apps/frontend-js/frontend-js-importmaps-extender/src/main/java/com/liferay/frontend/js/importmaps/extender/internal/configuration/JSImportMapsConfiguration.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com - * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06 - */ - -package com.liferay.frontend.js.importmaps.extender.internal.configuration; - -import aQute.bnd.annotation.metatype.Meta; - -import com.liferay.portal.configuration.metatype.annotations.ExtendedObjectClassDefinition; - -/** - * @author Iván Zaera Avellón - */ -@ExtendedObjectClassDefinition(category = "infrastructure", generateUI = false) -@Meta.OCD( - description = "frontend-js-import-maps-description", - id = "com.liferay.frontend.js.importmaps.extender.internal.configuration.JSImportMapsConfiguration", - localization = "content/Language", - name = "frontend-js-import-maps-configuration-name" -) -public interface JSImportMapsConfiguration { - - @Meta.AD(deflt = "true", name = "enable-import-maps", required = false) - public boolean enableImportMaps(); - - @Meta.AD( - deflt = "false", description = "enable-es-module-shims-help", - name = "enable-es-module-shims", required = false - ) - public boolean enableESModuleShims(); - -} \ No newline at end of file diff --git a/modules/apps/frontend-js/frontend-js-importmaps-extender/src/main/java/com/liferay/frontend/js/importmaps/extender/internal/servlet/taglib/JSImportMapsExtenderTopHeadDynamicInclude.java b/modules/apps/frontend-js/frontend-js-importmaps-extender/src/main/java/com/liferay/frontend/js/importmaps/extender/internal/servlet/taglib/JSImportMapsExtenderTopHeadDynamicInclude.java index 277357017a9db6..394c3c38b4f7d8 100644 --- a/modules/apps/frontend-js/frontend-js-importmaps-extender/src/main/java/com/liferay/frontend/js/importmaps/extender/internal/servlet/taglib/JSImportMapsExtenderTopHeadDynamicInclude.java +++ b/modules/apps/frontend-js/frontend-js-importmaps-extender/src/main/java/com/liferay/frontend/js/importmaps/extender/internal/servlet/taglib/JSImportMapsExtenderTopHeadDynamicInclude.java @@ -7,18 +7,12 @@ import com.liferay.frontend.js.importmaps.extender.DynamicJSImportMapsContributor; import com.liferay.frontend.js.importmaps.extender.JSImportMapsContributor; -import com.liferay.frontend.js.importmaps.extender.internal.configuration.JSImportMapsConfiguration; import com.liferay.frontend.js.importmaps.extender.internal.osgi.util.tracker.DynamicJSImportMapsContributorServiceTrackerCustomizer; import com.liferay.frontend.js.importmaps.extender.internal.osgi.util.tracker.JSImportMapsContributorServiceTrackerCustomizer; -import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil; import com.liferay.portal.kernel.content.security.policy.ContentSecurityPolicyNonceProviderUtil; -import com.liferay.portal.kernel.frontend.esm.FrontendESMUtil; import com.liferay.portal.kernel.servlet.taglib.BaseDynamicInclude; import com.liferay.portal.kernel.servlet.taglib.DynamicInclude; -import com.liferay.portal.kernel.util.HashMapBuilder; import com.liferay.portal.kernel.util.Portal; -import com.liferay.portal.url.builder.AbsolutePortalURLBuilder; -import com.liferay.portal.url.builder.AbsolutePortalURLBuilderFactory; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -30,7 +24,6 @@ import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Deactivate; -import org.osgi.service.component.annotations.Modified; import org.osgi.service.component.annotations.Reference; import org.osgi.util.tracker.ServiceTracker; @@ -38,7 +31,6 @@ * @author Iván Zaera Avellón */ @Component( - configurationPid = "com.liferay.frontend.js.importmaps.extender.internal.configuration.JSImportMapsConfiguration", property = "service.ranking:Integer=" + Integer.MAX_VALUE, service = DynamicInclude.class ) @@ -53,51 +45,15 @@ public void include( PrintWriter printWriter = httpServletResponse.getWriter(); - if (_jsImportMapsConfiguration.enableImportMaps()) { - printWriter.print(""); - - _jsImportMapsCache.writeImportMaps(httpServletRequest, printWriter); - - printWriter.print(""); - } - - if (_jsImportMapsConfiguration.enableESModuleShims()) { - printWriter.print("{\"shimMode\": "); - printWriter.print("true}\n"); - } + printWriter.print(""); + + _jsImportMapsCache.writeImportMaps(httpServletRequest, printWriter); + + printWriter.print(""); } @Override @@ -109,8 +65,6 @@ public void register(DynamicIncludeRegistry dynamicIncludeRegistry) { protected void activate(BundleContext bundleContext) { _bundleContext = bundleContext; - modified(); - _jsImportMapsCache = new JSImportMapsCache(_portal); _dynamicJSImportMapsContributorServiceTracker = new ServiceTracker<>( @@ -141,33 +95,11 @@ protected void deactivate() { _jsImportMapsContributorServiceTracker = null; } - @Modified - protected void modified() { - - // See LPS-165021 - - _jsImportMapsConfiguration = ConfigurableUtil.createConfigurable( - JSImportMapsConfiguration.class, - HashMapBuilder.put( - "enable-es-module-shims", false - ).put( - "enable-import-maps", true - ).build()); - - FrontendESMUtil.setScriptType( - _jsImportMapsConfiguration.enableESModuleShims() ? "module-shim" : - "module"); - } - - @Reference - private AbsolutePortalURLBuilderFactory _absolutePortalURLBuilderFactory; - private volatile BundleContext _bundleContext; private ServiceTracker _dynamicJSImportMapsContributorServiceTracker; private JSImportMapsCache _jsImportMapsCache; - private volatile JSImportMapsConfiguration _jsImportMapsConfiguration; private ServiceTracker _jsImportMapsContributorServiceTracker; diff --git a/modules/apps/frontend-js/frontend-js-loader-modules-extender/src/main/java/com/liferay/frontend/js/loader/modules/extender/internal/servlet/taglib/JSLoaderTopHeadDynamicInclude.java b/modules/apps/frontend-js/frontend-js-loader-modules-extender/src/main/java/com/liferay/frontend/js/loader/modules/extender/internal/servlet/taglib/JSLoaderTopHeadDynamicInclude.java index a88b7a7df70969..52e7056adb66d3 100644 --- a/modules/apps/frontend-js/frontend-js-loader-modules-extender/src/main/java/com/liferay/frontend/js/loader/modules/extender/internal/servlet/taglib/JSLoaderTopHeadDynamicInclude.java +++ b/modules/apps/frontend-js/frontend-js-loader-modules-extender/src/main/java/com/liferay/frontend/js/loader/modules/extender/internal/servlet/taglib/JSLoaderTopHeadDynamicInclude.java @@ -11,7 +11,6 @@ import com.liferay.portal.kernel.content.security.policy.ContentSecurityPolicyNonceProvider; import com.liferay.portal.kernel.content.security.policy.ContentSecurityPolicyNonceProviderUtil; import com.liferay.portal.kernel.feature.flag.FeatureFlagManagerUtil; -import com.liferay.portal.kernel.frontend.esm.FrontendESMUtil; import com.liferay.portal.kernel.servlet.PortalWebResourceConstants; import com.liferay.portal.kernel.servlet.PortalWebResourcesUtil; import com.liferay.portal.kernel.servlet.taglib.BaseDynamicInclude; @@ -82,9 +81,8 @@ public void include( printWriter.write(Boolean.toString(_details.exposeGlobal())); printWriter.write(", logLevel: '"); printWriter.write(_details.logLevel()); - printWriter.write("', moduleType: '"); - printWriter.write(FrontendESMUtil.getScriptType()); - printWriter.write("', namespace:'Liferay', nonce: '"); + printWriter.write("', moduleType: 'module', namespace:'Liferay', "); + printWriter.write("nonce: '"); printWriter.write( _contentSecurityPolicyNonceProvider.getNonce(httpServletRequest)); printWriter.write( @@ -105,8 +103,8 @@ public void include( httpServletRequest); printWriter.write( - absolutePortalURLBuilder.forBundleScript( - _bundle, "/loader.js" + absolutePortalURLBuilder.forWebContextScript( + "frontend-js-loader-modules-extender", "/loader.js" ).build()); printWriter.write("\" type=\""); diff --git a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/aui/PortletDataRendererImpl.java b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/aui/PortletDataRendererImpl.java index e791d74da708a6..0a3ad2dc31b380 100644 --- a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/aui/PortletDataRendererImpl.java +++ b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/aui/PortletDataRendererImpl.java @@ -8,7 +8,6 @@ import com.liferay.petra.string.StringBundler; import com.liferay.petra.string.StringPool; import com.liferay.portal.kernel.content.security.policy.ContentSecurityPolicyNonceProviderUtil; -import com.liferay.portal.kernel.frontend.esm.FrontendESMUtil; import com.liferay.portal.kernel.servlet.taglib.aui.AMDRequire; import com.liferay.portal.kernel.servlet.taglib.aui.ESImport; import com.liferay.portal.kernel.servlet.taglib.aui.JSFragment; @@ -66,9 +65,7 @@ public void write(Collection portletDatas, Writer writer) writer.write("\n"); + writer.write(" type=\"module\">\n"); } // Write ES prologue diff --git a/portal-impl/src/portal-osgi-configuration.properties b/portal-impl/src/portal-osgi-configuration.properties index 879e766f6e7fa2..dd9c03cd0f5d02 100644 --- a/portal-impl/src/portal-osgi-configuration.properties +++ b/portal-impl/src/portal-osgi-configuration.properties @@ -2891,14 +2891,6 @@ # #configuration.override.com.liferay.frontend.js.aui.web.internal.configuration.AUIConfiguration_enableAUIPreload= # - # Env: LIFERAY_CONFIGURATION_PERIOD_OVERRIDE_PERIOD_COM_PERIOD_LIFERAY_PERIOD_FRONTEND_PERIOD_JS_PERIOD_IMPORTMAPS_PERIOD_EXTENDER_PERIOD_INTERNAL_PERIOD_CONFIGURATION_PERIOD__UPPERCASEJ__UPPERCASES__UPPERCASEI_MPORT_UPPERCASEM_APS_UPPERCASEC_ONFIGURATION_UNDERLINE_ENABLE_UPPERCASEE__UPPERCASES__UPPERCASEM_ODULE_UPPERCASES_HIMS - # - #configuration.override.com.liferay.frontend.js.importmaps.extender.internal.configuration.JSImportMapsConfiguration_enableESModuleShims= - # - # Env: LIFERAY_CONFIGURATION_PERIOD_OVERRIDE_PERIOD_COM_PERIOD_LIFERAY_PERIOD_FRONTEND_PERIOD_JS_PERIOD_IMPORTMAPS_PERIOD_EXTENDER_PERIOD_INTERNAL_PERIOD_CONFIGURATION_PERIOD__UPPERCASEJ__UPPERCASES__UPPERCASEI_MPORT_UPPERCASEM_APS_UPPERCASEC_ONFIGURATION_UNDERLINE_ENABLE_UPPERCASEI_MPORT_UPPERCASEM_APS - # - #configuration.override.com.liferay.frontend.js.importmaps.extender.internal.configuration.JSImportMapsConfiguration_enableImportMaps= - # # Env: LIFERAY_CONFIGURATION_PERIOD_OVERRIDE_PERIOD_COM_PERIOD_LIFERAY_PERIOD_FRONTEND_PERIOD_JS_PERIOD_LODASH_PERIOD_WEB_PERIOD_INTERNAL_PERIOD_CONFIGURATION_PERIOD__UPPERCASEJ__UPPERCASES__UPPERCASEL_ODASH_UPPERCASEC_ONFIGURATION_UNDERLINE_ENABLE_UPPERCASEL_ODASH # #configuration.override.com.liferay.frontend.js.lodash.web.internal.configuration.JSLodashConfiguration_enableLodash= diff --git a/portal-kernel/src/com/liferay/portal/kernel/frontend/esm/FrontendESMUtil.java b/portal-kernel/src/com/liferay/portal/kernel/frontend/esm/FrontendESMUtil.java index d0c2c6f071525e..788e0cef0a1bdd 100644 --- a/portal-kernel/src/com/liferay/portal/kernel/frontend/esm/FrontendESMUtil.java +++ b/portal-kernel/src/com/liferay/portal/kernel/frontend/esm/FrontendESMUtil.java @@ -8,8 +8,6 @@ import com.liferay.petra.string.StringBundler; import com.liferay.portal.kernel.theme.ThemeDisplay; -import java.util.concurrent.atomic.AtomicReference; - /** * @author Iván Zaera Avellón */ @@ -39,15 +37,4 @@ public static String buildURL( submodule, ".js"); } - public static String getScriptType() { - return _scriptType.get(); - } - - public static void setScriptType(String scriptType) { - _scriptType.set(scriptType); - } - - private static final AtomicReference _scriptType = - new AtomicReference<>("module"); - } \ No newline at end of file diff --git a/portal-kernel/src/com/liferay/portal/kernel/frontend/esm/packageinfo b/portal-kernel/src/com/liferay/portal/kernel/frontend/esm/packageinfo index b1793a21a72389..682b435622a0aa 100644 --- a/portal-kernel/src/com/liferay/portal/kernel/frontend/esm/packageinfo +++ b/portal-kernel/src/com/liferay/portal/kernel/frontend/esm/packageinfo @@ -1 +1 @@ -version 1.1.0 \ No newline at end of file +version 2.0.0 \ No newline at end of file diff --git a/portal-kernel/src/com/liferay/portal/kernel/portlet/render/PortletRenderUtil.java b/portal-kernel/src/com/liferay/portal/kernel/portlet/render/PortletRenderUtil.java index 3293afa3436308..e345e962eb7991 100644 --- a/portal-kernel/src/com/liferay/portal/kernel/portlet/render/PortletRenderUtil.java +++ b/portal-kernel/src/com/liferay/portal/kernel/portlet/render/PortletRenderUtil.java @@ -9,7 +9,6 @@ import com.liferay.petra.string.StringBundler; import com.liferay.petra.string.StringPool; import com.liferay.portal.kernel.content.security.policy.ContentSecurityPolicyNonceProviderUtil; -import com.liferay.portal.kernel.frontend.esm.FrontendESMUtil; import com.liferay.portal.kernel.frontend.hashed.files.HashedFilesRegistryUtil; import com.liferay.portal.kernel.frontend.hashed.files.HashedFilesUtil; import com.liferay.portal.kernel.log.Log; @@ -606,7 +605,7 @@ private static void _writeJavaScriptPath( if (javaScriptPath.startsWith("module:")) { javaScriptPath = javaScriptPath.substring(7); - type = FrontendESMUtil.getScriptType(); + type = "module"; } printWriter.print(" Date: Tue, 4 Nov 2025 09:35:57 +0100 Subject: [PATCH 05/16] LPD-52709 Change aui:script so that it can use hashed URLs --- util-taglib/bnd.bnd | 2 +- util-taglib/src/META-INF/liferay-aui.tld | 5 +++ .../src/com/liferay/taglib/aui/LinkTag.java | 25 +---------- .../src/com/liferay/taglib/aui/ScriptTag.java | 10 ++++- .../taglib/aui/base/BaseScriptTag.java | 10 +++++ .../com/liferay/taglib/aui/base/packageinfo | 2 +- .../src/com/liferay/taglib/aui/packageinfo | 2 +- .../src/com/liferay/taglib/liferay-aui.xml | 5 +++ .../liferay/taglib/util/HashedFileUtil.java | 44 +++++++++++++++++++ .../src/com/liferay/taglib/util/packageinfo | 2 +- 10 files changed, 79 insertions(+), 28 deletions(-) create mode 100644 util-taglib/src/com/liferay/taglib/util/HashedFileUtil.java diff --git a/util-taglib/bnd.bnd b/util-taglib/bnd.bnd index 660ec2407504ae..7bfa701d3f2f43 100644 --- a/util-taglib/bnd.bnd +++ b/util-taglib/bnd.bnd @@ -1,6 +1,6 @@ Bundle-Name: ${manifest.bundle.name} Bundle-SymbolicName: ${manifest.bundle.symbolic.name} -Bundle-Version: 28.1.2 +Bundle-Version: 28.2.0 Export-Package: com.liferay.taglib.* Import-Package:\ !com.liferay.portal.freemarker,\ diff --git a/util-taglib/src/META-INF/liferay-aui.tld b/util-taglib/src/META-INF/liferay-aui.tld index d57d4520c3f974..aef71f171cb864 100644 --- a/util-taglib/src/META-INF/liferay-aui.tld +++ b/util-taglib/src/META-INF/liferay-aui.tld @@ -1158,6 +1158,11 @@ false true + + hashedFile + false + true + id false diff --git a/util-taglib/src/com/liferay/taglib/aui/LinkTag.java b/util-taglib/src/com/liferay/taglib/aui/LinkTag.java index e46dd973500a9e..0444536e7d879f 100644 --- a/util-taglib/src/com/liferay/taglib/aui/LinkTag.java +++ b/util-taglib/src/com/liferay/taglib/aui/LinkTag.java @@ -7,11 +7,9 @@ import com.liferay.petra.string.StringPool; import com.liferay.portal.kernel.content.security.policy.ContentSecurityPolicyNonceProviderUtil; -import com.liferay.portal.kernel.exception.PortalException; -import com.liferay.portal.kernel.frontend.hashed.files.HashedFilesRegistryUtil; -import com.liferay.portal.kernel.util.PortalUtil; import com.liferay.portal.kernel.util.Validator; import com.liferay.taglib.aui.base.BaseLinkTag; +import com.liferay.taglib.util.HashedFileUtil; import jakarta.servlet.jsp.JspException; import jakarta.servlet.jsp.JspWriter; @@ -52,26 +50,7 @@ public int doEndTag() throws JspException { if (Validator.isNotNull(href)) { if (getHashedFile()) { - String prefix = PortalUtil.getPathModule(); - - String proxyPath = PortalUtil.getPathProxy(); - - prefix = prefix.substring(proxyPath.length()); - - String hashedFileURI = - HashedFilesRegistryUtil.getHashedFileURI( - prefix + StringPool.SLASH + href); - - if (hashedFileURI != null) { - try { - href = - PortalUtil.getCDNHost(getRequest()) + - proxyPath + hashedFileURI; - } - catch (PortalException portalException) { - throw new RuntimeException(portalException); - } - } + href = HashedFileUtil.getURL(getRequest(), href); } _write(jspWriter, "href", href); diff --git a/util-taglib/src/com/liferay/taglib/aui/ScriptTag.java b/util-taglib/src/com/liferay/taglib/aui/ScriptTag.java index 7e610b01147bfa..586be20ff24766 100644 --- a/util-taglib/src/com/liferay/taglib/aui/ScriptTag.java +++ b/util-taglib/src/com/liferay/taglib/aui/ScriptTag.java @@ -15,6 +15,7 @@ import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.kernel.util.WebKeys; import com.liferay.taglib.aui.base.BaseScriptTag; +import com.liferay.taglib.util.HashedFileUtil; import com.liferay.taglib.util.PortalIncludeUtil; import jakarta.servlet.http.HttpServletRequest; @@ -265,7 +266,14 @@ private int _endTag() throws IOException, JspException { _write(jspWriter, "id", getId()); _write(jspWriter, "integrity", getIntegrity()); _write(jspWriter, "referrerpolicy", getReferrerPolicy()); - _write(jspWriter, "src", getSrc()); + + String src = getSrc(); + + if (getHashedFile()) { + src = HashedFileUtil.getURL(getRequest(), src); + } + + _write(jspWriter, "src", src); _write(jspWriter, "type", getType()); String senna = getSenna(); diff --git a/util-taglib/src/com/liferay/taglib/aui/base/BaseScriptTag.java b/util-taglib/src/com/liferay/taglib/aui/base/BaseScriptTag.java index 6a267154cb4603..be62a35eec1687 100644 --- a/util-taglib/src/com/liferay/taglib/aui/base/BaseScriptTag.java +++ b/util-taglib/src/com/liferay/taglib/aui/base/BaseScriptTag.java @@ -40,6 +40,14 @@ public java.lang.String getFetchPriority() { return _fetchPriority; } + public boolean getHashedFile() { + return _hashedFile; + } + + public void setHashedFile(boolean hashedFile) { + _hashedFile = hashedFile; + } + public java.lang.String getId() { return _id; } @@ -138,6 +146,7 @@ protected void cleanUp() { _crossOrigin = null; _defer = false; _fetchPriority = null; + _hashedFile = false; _id = null; _integrity = null; _referrerPolicy = null; @@ -161,6 +170,7 @@ protected String getPage() { private java.lang.String _crossOrigin = null; private boolean _defer = false; private java.lang.String _fetchPriority = null; + private boolean _hashedFile; private java.lang.String _id = null; private java.lang.String _integrity = null; private java.lang.String _referrerPolicy = null; diff --git a/util-taglib/src/com/liferay/taglib/aui/base/packageinfo b/util-taglib/src/com/liferay/taglib/aui/base/packageinfo index e456c681cd9f35..dfded4826d974f 100644 --- a/util-taglib/src/com/liferay/taglib/aui/base/packageinfo +++ b/util-taglib/src/com/liferay/taglib/aui/base/packageinfo @@ -1 +1 @@ -version 18.1.0 \ No newline at end of file +version 18.2.0 \ No newline at end of file diff --git a/util-taglib/src/com/liferay/taglib/aui/packageinfo b/util-taglib/src/com/liferay/taglib/aui/packageinfo index 6b1cd2d89d4aa3..baa016bd1a7785 100644 --- a/util-taglib/src/com/liferay/taglib/aui/packageinfo +++ b/util-taglib/src/com/liferay/taglib/aui/packageinfo @@ -1 +1 @@ -version 19.1.0 \ No newline at end of file +version 19.2.0 \ No newline at end of file diff --git a/util-taglib/src/com/liferay/taglib/liferay-aui.xml b/util-taglib/src/com/liferay/taglib/liferay-aui.xml index e80cfe98f3feeb..8620d07776242b 100644 --- a/util-taglib/src/com/liferay/taglib/liferay-aui.xml +++ b/util-taglib/src/com/liferay/taglib/liferay-aui.xml @@ -1061,6 +1061,11 @@ java.lang.String java.lang.String + + hashedFile + java.lang.Boolean + java.lang.Boolean + id java.lang.String diff --git a/util-taglib/src/com/liferay/taglib/util/HashedFileUtil.java b/util-taglib/src/com/liferay/taglib/util/HashedFileUtil.java new file mode 100644 index 00000000000000..0451a2aa215561 --- /dev/null +++ b/util-taglib/src/com/liferay/taglib/util/HashedFileUtil.java @@ -0,0 +1,44 @@ +/** + * SPDX-FileCopyrightText: (c) 2025 Liferay, Inc. https://liferay.com + * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06 + */ + +package com.liferay.taglib.util; + +import com.liferay.petra.string.StringPool; +import com.liferay.portal.kernel.exception.PortalException; +import com.liferay.portal.kernel.frontend.hashed.files.HashedFilesRegistryUtil; +import com.liferay.portal.kernel.util.PortalUtil; + +import jakarta.servlet.http.HttpServletRequest; + +/** + * @author Iván Zaera Avellón + */ +public class HashedFileUtil { + + public static String getURL( + HttpServletRequest httpServletRequest, String resourcePath) { + + String prefix = PortalUtil.getPathModule(); + + String proxyPath = PortalUtil.getPathProxy(); + + prefix = prefix.substring(proxyPath.length()); + + String unhashedFileURI = prefix + StringPool.SLASH + resourcePath; + + String hashedFileURI = HashedFilesRegistryUtil.getHashedFileURI( + unhashedFileURI); + + String uri = (hashedFileURI == null) ? unhashedFileURI : hashedFileURI; + + try { + return PortalUtil.getCDNHost(httpServletRequest) + proxyPath + uri; + } + catch (PortalException portalException) { + throw new RuntimeException(portalException); + } + } + +} \ No newline at end of file diff --git a/util-taglib/src/com/liferay/taglib/util/packageinfo b/util-taglib/src/com/liferay/taglib/util/packageinfo index f7a759e8701cdb..755bd3f5c7277b 100644 --- a/util-taglib/src/com/liferay/taglib/util/packageinfo +++ b/util-taglib/src/com/liferay/taglib/util/packageinfo @@ -1 +1 @@ -version 15.0.0 \ No newline at end of file +version 15.1.0 \ No newline at end of file From 294b91d5b12c6226490be13d3e840de2cef5cabd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Tue, 4 Nov 2025 09:36:28 +0100 Subject: [PATCH 06/16] LPD-52709 Prepare editors to use hashed URLs Note that we are not hashing the file names yet because they rely on Java tooling but at least we leverage the new configurable time based caching infrastructure. --- .../resources/META-INF/resources/resources.jsp | 14 ++++++++------ .../src/main/resources/META-INF/resources/init.jsp | 1 - .../resources/META-INF/resources/resources.jsp | 11 +++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/modules/apps/frontend-editor/frontend-editor-alloyeditor-web/src/main/resources/META-INF/resources/resources.jsp b/modules/apps/frontend-editor/frontend-editor-alloyeditor-web/src/main/resources/META-INF/resources/resources.jsp index 6eb65951dd0075..ecc7ea29b14fc2 100644 --- a/modules/apps/frontend-editor/frontend-editor-alloyeditor-web/src/main/resources/META-INF/resources/resources.jsp +++ b/modules/apps/frontend-editor/frontend-editor-alloyeditor-web/src/main/resources/META-INF/resources/resources.jsp @@ -8,6 +8,12 @@ <%@ include file="/init.jsp" %> <% +String alloyEditorServletContextName = PortalWebResourcesUtil.getServletContext( + PortalWebResourceConstants.RESOURCE_TYPE_EDITOR_ALLOYEDITOR +).getServletContextName(); +String ckEditorServletContextName = PortalWebResourcesUtil.getServletContext( + PortalWebResourceConstants.RESOURCE_TYPE_EDITOR_CKEDITOR +).getServletContextName(); String editorName = (String)request.getAttribute(AlloyEditorConstants.ATTRIBUTE_NAMESPACE + ":editorName"); %> @@ -16,18 +22,14 @@ String editorName = (String)request.getAttribute(AlloyEditorConstants.ATTRIBUTE_ > - <% - long javaScriptLastModified = PortalWebResourcesUtil.getLastModified(PortalWebResourceConstants.RESOURCE_TYPE_EDITOR_ALLOYEDITOR); - %> - window.ALLOYEDITOR_BASEPATH = '<%= PortalUtil.getPathProxy() + application.getContextPath() %>/alloyeditor/'; - + - + diff --git a/modules/apps/frontend-editor/frontend-editor-ckeditor-web/src/main/resources/META-INF/resources/init.jsp b/modules/apps/frontend-editor/frontend-editor-ckeditor-web/src/main/resources/META-INF/resources/init.jsp index d65cf6c70a1e78..85e49e97ac629b 100644 --- a/modules/apps/frontend-editor/frontend-editor-ckeditor-web/src/main/resources/META-INF/resources/init.jsp +++ b/modules/apps/frontend-editor/frontend-editor-ckeditor-web/src/main/resources/META-INF/resources/init.jsp @@ -30,7 +30,6 @@ page import="com.liferay.portal.kernel.util.GetterUtil" %><%@ page import="com.liferay.portal.kernel.util.HashMapBuilder" %><%@ page import="com.liferay.portal.kernel.util.HtmlUtil" %><%@ page import="com.liferay.portal.kernel.util.JavaConstants" %><%@ -page import="com.liferay.portal.kernel.util.PortalUtil" %><%@ page import="com.liferay.portal.kernel.util.SessionClicks" %><%@ page import="com.liferay.portal.kernel.util.TextFormatter" %><%@ page import="com.liferay.portal.kernel.util.URLCodec" %><%@ diff --git a/modules/apps/frontend-editor/frontend-editor-ckeditor-web/src/main/resources/META-INF/resources/resources.jsp b/modules/apps/frontend-editor/frontend-editor-ckeditor-web/src/main/resources/META-INF/resources/resources.jsp index 7e38ca0b61e263..85a133b99f9033 100644 --- a/modules/apps/frontend-editor/frontend-editor-ckeditor-web/src/main/resources/META-INF/resources/resources.jsp +++ b/modules/apps/frontend-editor/frontend-editor-ckeditor-web/src/main/resources/META-INF/resources/resources.jsp @@ -8,6 +8,9 @@ <%@ include file="/init.jsp" %> <% +String ckEditorServletContextName = PortalWebResourcesUtil.getServletContext( + PortalWebResourceConstants.RESOURCE_TYPE_EDITOR_CKEDITOR +).getServletContextName(); String editorName = (String)request.getAttribute(CKEditorConstants.ATTRIBUTE_NAMESPACE + ":editorName"); boolean inlineEdit = GetterUtil.getBoolean((String)request.getAttribute(CKEditorConstants.ATTRIBUTE_NAMESPACE + ":inlineEdit")); String inlineEditSaveURL = GetterUtil.getString((String)request.getAttribute(CKEditorConstants.ATTRIBUTE_NAMESPACE + ":inlineEditSaveURL")); @@ -22,14 +25,10 @@ String inlineEditSaveURL = GetterUtil.getString((String)request.getAttribute(CKE } - <% - long javaScriptLastModified = PortalWebResourcesUtil.getLastModified(PortalWebResourceConstants.RESOURCE_TYPE_EDITOR_CKEDITOR); - %> - - + - + From 975251bc61b94b3d6cabc1413f968b3ba6c88711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Tue, 4 Nov 2025 09:41:41 +0100 Subject: [PATCH 07/16] LPD-52709 Use hashed URLs instead of legacy ones Note that for some bundles we also hashify the file names to achieve infinite caching. --- .../taglib/LodashTopHeadDynamicInclude.java | 4 ++-- .../node-scripts.config.js | 2 +- .../taglib/SVG4EverybodyTopHeadDynamicInclude.java | 14 +++++++------- .../frontend-js-web/node-scripts.config.js | 2 +- .../LiferayGlobalObjectPostAUIDynamicInclude.java | 12 ++++++------ 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/modules/apps/frontend-js/frontend-js-lodash-web/src/main/java/com/liferay/frontend/js/lodash/web/internal/servlet/taglib/LodashTopHeadDynamicInclude.java b/modules/apps/frontend-js/frontend-js-lodash-web/src/main/java/com/liferay/frontend/js/lodash/web/internal/servlet/taglib/LodashTopHeadDynamicInclude.java index d81ac879d14ac5..3bf0be4a073ac3 100644 --- a/modules/apps/frontend-js/frontend-js-lodash-web/src/main/java/com/liferay/frontend/js/lodash/web/internal/servlet/taglib/LodashTopHeadDynamicInclude.java +++ b/modules/apps/frontend-js/frontend-js-lodash-web/src/main/java/com/liferay/frontend/js/lodash/web/internal/servlet/taglib/LodashTopHeadDynamicInclude.java @@ -61,8 +61,8 @@ public void include( printWriter.print(" data-senna-track=\"permanent\" src=\""); printWriter.print( - absolutePortalURLBuilder.forBundleScript( - _bundleContext.getBundle(), fileName + absolutePortalURLBuilder.forWebContextScript( + "frontend-js-lodash-web", fileName ).build()); printWriter.println("\" type=\"text/javascript\">"); diff --git a/modules/apps/frontend-js/frontend-js-svg4everybody-web/node-scripts.config.js b/modules/apps/frontend-js/frontend-js-svg4everybody-web/node-scripts.config.js index 4c334868a2b5f1..0234e6c9a48914 100644 --- a/modules/apps/frontend-js/frontend-js-svg4everybody-web/node-scripts.config.js +++ b/modules/apps/frontend-js/frontend-js-svg4everybody-web/node-scripts.config.js @@ -9,7 +9,7 @@ module.exports = { customBuild: { esbuild: { bundle: true, - entryNames: 'index', + entryNames: 'index.([hash])', entryPoints: [ path.resolve( 'src', diff --git a/modules/apps/frontend-js/frontend-js-svg4everybody-web/src/main/java/com/liferay/frontend/js/svg4everybody/web/internal/servlet/taglib/SVG4EverybodyTopHeadDynamicInclude.java b/modules/apps/frontend-js/frontend-js-svg4everybody-web/src/main/java/com/liferay/frontend/js/svg4everybody/web/internal/servlet/taglib/SVG4EverybodyTopHeadDynamicInclude.java index 1e5de0f4e3d18f..a49eebcee67904 100644 --- a/modules/apps/frontend-js/frontend-js-svg4everybody-web/src/main/java/com/liferay/frontend/js/svg4everybody/web/internal/servlet/taglib/SVG4EverybodyTopHeadDynamicInclude.java +++ b/modules/apps/frontend-js/frontend-js-svg4everybody-web/src/main/java/com/liferay/frontend/js/svg4everybody/web/internal/servlet/taglib/SVG4EverybodyTopHeadDynamicInclude.java @@ -24,7 +24,7 @@ import com.liferay.portal.kernel.util.WebKeys; import com.liferay.portal.url.builder.AbsolutePortalURLBuilder; import com.liferay.portal.url.builder.AbsolutePortalURLBuilderFactory; -import com.liferay.portal.url.builder.BundleScriptAbsolutePortalURLBuilder; +import com.liferay.portal.url.builder.WebContextScriptAbsolutePortalURLBuilder; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -109,16 +109,16 @@ public void include( httpServletRequest)); printWriter.print(" data-senna-track=\"permanent\" src=\""); - BundleScriptAbsolutePortalURLBuilder - bundleScriptAbsolutePortalURLBuilder = - absolutePortalURLBuilder.forBundleScript( - _bundleContext.getBundle(), jsFileName); + WebContextScriptAbsolutePortalURLBuilder + webContextScriptAbsolutePortalURLBuilder = + absolutePortalURLBuilder.forWebContextScript( + "frontend-js-svg4everybody-web", jsFileName); if (!cdnDynamicResourcesEnabled) { - bundleScriptAbsolutePortalURLBuilder.ignoreCDNHost(); + webContextScriptAbsolutePortalURLBuilder.ignoreCDNHost(); } - printWriter.print(bundleScriptAbsolutePortalURLBuilder.build()); + printWriter.print(webContextScriptAbsolutePortalURLBuilder.build()); printWriter.println("\" type=\"text/javascript\">"); } diff --git a/modules/apps/frontend-js/frontend-js-web/node-scripts.config.js b/modules/apps/frontend-js/frontend-js-web/node-scripts.config.js index d4494145dbb21f..7f3e024b453cbf 100644 --- a/modules/apps/frontend-js/frontend-js-web/node-scripts.config.js +++ b/modules/apps/frontend-js/frontend-js-web/node-scripts.config.js @@ -9,7 +9,7 @@ module.exports = { customBuild: { esbuild: { bundle: true, - entryNames: 'Liferay', + entryNames: 'Liferay.([hash])', entryPoints: [ path.resolve( 'src', diff --git a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPostAUIDynamicInclude.java b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPostAUIDynamicInclude.java index c78f9dbd5df51a..3978abd0a3da74 100644 --- a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPostAUIDynamicInclude.java +++ b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPostAUIDynamicInclude.java @@ -14,7 +14,7 @@ import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.url.builder.AbsolutePortalURLBuilder; import com.liferay.portal.url.builder.AbsolutePortalURLBuilderFactory; -import com.liferay.portal.url.builder.BundleScriptAbsolutePortalURLBuilder; +import com.liferay.portal.url.builder.WebContextScriptAbsolutePortalURLBuilder; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -57,14 +57,14 @@ public void include( _absolutePortalURLBuilderFactory.getAbsolutePortalURLBuilder( httpServletRequest); - BundleScriptAbsolutePortalURLBuilder - bundleScriptAbsolutePortalURLBuilder = - absolutePortalURLBuilder.forBundleScript( - _bundle, "/Liferay.js"); + WebContextScriptAbsolutePortalURLBuilder + webContextScriptAbsolutePortalURLBuilder = + absolutePortalURLBuilder.forWebContextScript( + "frontend-js-web", "/Liferay.js"); _renderScript( httpServletRequest, httpServletResponse.getWriter(), - bundleScriptAbsolutePortalURLBuilder.build(), + webContextScriptAbsolutePortalURLBuilder.build(), "text/javascript"); } catch (Exception exception) { From 0ab035aa06a697604f974112c8a4c8358e3025ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Tue, 4 Nov 2025 09:42:58 +0100 Subject: [PATCH 08/16] LPD-52709 Use hashed URLs for portlet's JS files Note that we are not hashing the file names yet because that needs changes in the tooling, but at least we leverage the new configurable time based caching infrastructure. --- .../portlet/render/PortletRenderUtil.java | 154 +----------------- 1 file changed, 9 insertions(+), 145 deletions(-) diff --git a/portal-kernel/src/com/liferay/portal/kernel/portlet/render/PortletRenderUtil.java b/portal-kernel/src/com/liferay/portal/kernel/portlet/render/PortletRenderUtil.java index e345e962eb7991..0c63a04c8e3b92 100644 --- a/portal-kernel/src/com/liferay/portal/kernel/portlet/render/PortletRenderUtil.java +++ b/portal-kernel/src/com/liferay/portal/kernel/portlet/render/PortletRenderUtil.java @@ -6,7 +6,6 @@ package com.liferay.portal.kernel.portlet.render; import com.liferay.petra.io.StreamUtil; -import com.liferay.petra.string.StringBundler; import com.liferay.petra.string.StringPool; import com.liferay.portal.kernel.content.security.policy.ContentSecurityPolicyNonceProviderUtil; import com.liferay.portal.kernel.frontend.hashed.files.HashedFilesRegistryUtil; @@ -15,7 +14,6 @@ import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.LayoutTypePortlet; import com.liferay.portal.kernel.model.Portlet; -import com.liferay.portal.kernel.model.Theme; import com.liferay.portal.kernel.theme.ThemeDisplay; import com.liferay.portal.kernel.util.HashMapBuilder; import com.liferay.portal.kernel.util.HtmlUtil; @@ -46,7 +44,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Predicate; /** * @author Iván Zaera Avellón @@ -196,110 +193,6 @@ private static List _getAllPortlets( return allPortlets; } - private static List _getComboServletURLs( - Collection portletResourceAccessors, - Collection portlets, Predicate predicate, - long timestamp, String urlPrefix, Set visitedURLs) { - - if (predicate == null) { - predicate = s -> true; - } - - List urls = new ArrayList<>(); - - StringBundler comboServletSB = new StringBundler(); - - for (Portlet portlet : portlets) { - for (PortletResourceAccessor portletResourceAccessor : - portletResourceAccessors) { - - String contextPath = null; - - if (portletResourceAccessor.isPortalResource()) { - contextPath = PortalUtil.getPathContext(); - } - else { - contextPath = - PortalUtil.getPathProxy() + portlet.getContextPath(); - } - - Collection portletResources = - portletResourceAccessor.get(portlet); - - for (String portletResource : portletResources) { - if (!predicate.test(portletResource)) { - continue; - } - - String prefix = null; - - for (String specialPrefix : _specialPrefixes) { - if (portletResource.startsWith(specialPrefix)) { - portletResource = portletResource.substring( - specialPrefix.length()); - - prefix = specialPrefix; - - break; - } - } - - boolean absolute = HttpComponentsUtil.hasProtocol( - portletResource); - - if (!absolute) { - portletResource = contextPath + portletResource; - } - - if (Validator.isNotNull(prefix)) { - portletResource = prefix + portletResource; - } - - if (visitedURLs.contains(portletResource)) { - continue; - } - - visitedURLs.add(portletResource); - - if (absolute || Validator.isNotNull(prefix)) { - urls.add(portletResource); - } - else { - comboServletSB.append(StringPool.AMPERSAND); - - if (!portletResourceAccessor.isPortalResource()) { - comboServletSB.append(portlet.getPortletId()); - comboServletSB.append(StringPool.COLON); - } - - comboServletSB.append( - HtmlUtil.escapeURL(portletResource)); - - timestamp = Math.max(timestamp, portlet.getTimestamp()); - } - } - } - } - - if (comboServletSB.length() > 0) { - String url = urlPrefix + comboServletSB; - - url = HttpComponentsUtil.addParameter(url, "t", timestamp); - - urls.add(url); - } - - return urls; - } - - private static String _getMinifierType(URLType urlType) { - if (urlType == URLType.CSS) { - return "css"; - } - - return "js"; - } - private static PortletRenderParts _getPortletRenderParts( HttpServletRequest httpServletRequest, String portletHTML, Portlet portlet, boolean portletOnLayout) { @@ -434,12 +327,15 @@ private static List _getStaticURLs( contextPath + portletResource, themeDisplay); } else if (urlType == URLType.JAVASCRIPT) { - Portlet rootPortlet = portlet.getRootPortlet(); + portletResource = contextPath + portletResource; - portletResource = PortalUtil.getStaticResourceURL( - httpServletRequest, - contextPath + portletResource, - rootPortlet.getTimestamp()); + String hashedFileURI = + HashedFilesRegistryUtil.getHashedFileURI( + portletResource); + + if (hashedFileURI != null) { + portletResource = hashedFileURI; + } } else { throw new UnsupportedOperationException( @@ -488,43 +384,11 @@ private static Collection _getURLs( List urls; - if (urlType == URLType.CSS) { + if ((urlType == URLType.CSS) || (urlType == URLType.JAVASCRIPT)) { urls = _getStaticURLs( httpServletRequest, portletResourceAccessors, portlets, urlType, visitedURLs); } - else if (urlType == URLType.JAVASCRIPT) { - ThemeDisplay themeDisplay = - (ThemeDisplay)httpServletRequest.getAttribute( - WebKeys.THEME_DISPLAY); - - boolean fastLoad = themeDisplay.isThemeJsFastLoad(); - - if (fastLoad) { - Predicate predicate = - resource -> !themeDisplay.isIncludedJs(resource); - - Theme theme = themeDisplay.getTheme(); - - urls = _getComboServletURLs( - portletResourceAccessors, portlets, predicate, - theme.getTimestamp(), - PortalUtil.getStaticResourceURL( - httpServletRequest, - themeDisplay.getCDNDynamicResourcesHost() + - themeDisplay.getPathContext() + "/combo", - StringBundler.concat( - "minifierType=", _getMinifierType(urlType), - "&themeId=", themeDisplay.getThemeId()), - -1), - visitedURLs); - } - else { - urls = _getStaticURLs( - httpServletRequest, portletResourceAccessors, portlets, - urlType, visitedURLs); - } - } else { throw new UnsupportedOperationException( "Unsupported URL type " + urlType); From 26023d46c44ce309fb32aab4747caa6662a8c519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Tue, 4 Nov 2025 09:43:25 +0100 Subject: [PATCH 09/16] LPD-52709 Add logging --- ...hedFileFrontendResourceRequestHandler.java | 17 +++++++++++++++ ...leSheetFrontendResourceRequestHandler.java | 21 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/resource/handler/HashedFileFrontendResourceRequestHandler.java b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/resource/handler/HashedFileFrontendResourceRequestHandler.java index a40561ac431ce4..fd4c8147a3156c 100644 --- a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/resource/handler/HashedFileFrontendResourceRequestHandler.java +++ b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/resource/handler/HashedFileFrontendResourceRequestHandler.java @@ -7,6 +7,8 @@ import com.liferay.frontend.js.web.internal.resource.FrontendResource; import com.liferay.frontend.js.web.internal.resource.HashedFileFrontendResource; +import com.liferay.petra.string.StringBundler; +import com.liferay.petra.string.StringPool; import com.liferay.portal.kernel.frontend.hashed.files.HashedFilesRegistry; import com.liferay.portal.kernel.frontend.hashed.files.HashedFilesUtil; import com.liferay.portal.kernel.log.Log; @@ -81,6 +83,10 @@ public FrontendResource handleRequest(HttpServletRequest httpServletRequest) String requestHash = HashedFilesUtil.getHash(requestURI); if (requestHash != null) { + if (_log.isDebugEnabled()) { + _log.debug("Handling request " + requestURI); + } + return _createFrontendResource( _portal.getCompanyId(httpServletRequest), requestHash, true, requestURI); @@ -90,11 +96,22 @@ public FrontendResource handleRequest(HttpServletRequest httpServletRequest) requestURI); if (hashedFileURI == null) { + if (_log.isDebugEnabled()) { + _log.debug("Handling request " + requestURI); + } + return _createFrontendResource( _portal.getCompanyId(httpServletRequest), null, false, requestURI); } + if (_log.isDebugEnabled()) { + _log.debug( + StringBundler.concat( + "Handling request ", requestURI, " [static file: ", + hashedFileURI, StringPool.CLOSE_BRACKET)); + } + return _createFrontendResource( _portal.getCompanyId(httpServletRequest), HashedFilesUtil.getHash(hashedFileURI), false, hashedFileURI); diff --git a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/resource/handler/StyleSheetFrontendResourceRequestHandler.java b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/resource/handler/StyleSheetFrontendResourceRequestHandler.java index e860c9424b1094..078dc37554f0e9 100644 --- a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/resource/handler/StyleSheetFrontendResourceRequestHandler.java +++ b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/resource/handler/StyleSheetFrontendResourceRequestHandler.java @@ -8,10 +8,13 @@ import com.liferay.frontend.js.web.internal.configuration.FrontendCachingConfiguration; import com.liferay.frontend.js.web.internal.resource.FrontendResource; import com.liferay.frontend.js.web.internal.resource.StyleSheetFrontendResource; +import com.liferay.petra.string.StringBundler; import com.liferay.petra.string.StringPool; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.frontend.hashed.files.HashedFilesRegistry; import com.liferay.portal.kernel.frontend.hashed.files.HashedFilesUtil; +import com.liferay.portal.kernel.log.Log; +import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.Theme; import com.liferay.portal.kernel.service.ThemeLocalService; import com.liferay.portal.kernel.util.Portal; @@ -83,6 +86,10 @@ public FrontendResource handleRequest(HttpServletRequest httpServletRequest) SortedMap tokens = _getTokens(httpServletRequest); if (requestHash != null) { + if (_log.isDebugEnabled()) { + _log.debug("Handling request: " + requestURI); + } + return _createFrontendResource( requestHash, tokens == null, requestURI, tokens); } @@ -91,9 +98,20 @@ public FrontendResource handleRequest(HttpServletRequest httpServletRequest) requestURI); if (hashedFileURI == null) { + if (_log.isDebugEnabled()) { + _log.debug("Handling request: " + requestURI); + } + return _createFrontendResource(null, false, requestURI, tokens); } + if (_log.isDebugEnabled()) { + _log.debug( + StringBundler.concat( + "Handling request ", requestURI, " [static file: ", + hashedFileURI, StringPool.CLOSE_BRACKET)); + } + return _createFrontendResource( HashedFilesUtil.getHash(hashedFileURI), false, hashedFileURI, tokens); @@ -166,6 +184,9 @@ private SortedMap _getTokens( return tokens; } + private static final Log _log = LogFactoryUtil.getLog( + StyleSheetFrontendResourceRequestHandler.class); + private final FrontendCachingConfiguration _frontendCachingConfiguration; private final HashedFilesRegistry _hashedFilesRegistry; private final Portal _portal; From 15f13bd8e39f2049ca83a7061a6b5d1254a3edb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Thu, 25 Sep 2025 11:11:05 +0200 Subject: [PATCH 10/16] LPD-52709 Move headless tests to Chrome 139 --- .../portalweb/tests/enduser/exportimport/ExportImport.testcase | 1 + .../portalweb/tests/enduser/exportimport/ExportTemplate.testcase | 1 + .../sitetemplates/cpsitetemplates/CPSitetemplates.testcase | 1 + .../enduser/sitetemplates/upgrades/SitetemplatesUpgrade.testcase | 1 + .../tests/enduser/staging/usecase/RemoteStaging.testcase | 1 + .../portalweb/tests/enduser/staging/usecase/Staging.testcase | 1 + .../tests/enduser/staging/usecase/StagingUsecase.testcase | 1 + .../enduser/staging/usecase/StagingUsecaseWithRoles.testcase | 1 + .../staging/usecase/StagingUsecaseWithVersioning.testcase | 1 + .../tests/enduser/wem/site/SiteTemplatesWithPermissions.testcase | 1 + 10 files changed, 10 insertions(+) diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/exportimport/ExportImport.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/exportimport/ExportImport.testcase index 1eaa31d686f507..ad57ac426978cf 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/exportimport/ExportImport.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/exportimport/ExportImport.testcase @@ -1,6 +1,7 @@ @component-name = "portal-headless" definition { + property browser.chrome.version = "139.0"; property ci.retries.disabled = "true"; property portal.release = "true"; property portal.upstream = "true"; diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/exportimport/ExportTemplate.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/exportimport/ExportTemplate.testcase index b785a230c14519..ed8d190e3df86d 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/exportimport/ExportTemplate.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/exportimport/ExportTemplate.testcase @@ -1,6 +1,7 @@ @component-name = "portal-headless" definition { + property browser.chrome.version = "139.0"; property ci.retries.disabled = "true"; property portal.release = "true"; property portal.upstream = "true"; diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/sitetemplates/cpsitetemplates/CPSitetemplates.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/sitetemplates/cpsitetemplates/CPSitetemplates.testcase index edf0a3f1acad6f..759aeb420bdd5d 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/sitetemplates/cpsitetemplates/CPSitetemplates.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/sitetemplates/cpsitetemplates/CPSitetemplates.testcase @@ -1,6 +1,7 @@ @component-name = "portal-headless" definition { + property browser.chrome.version = "139.0"; property ci.retries.disabled = "true"; property portal.release = "true"; property portal.upstream = "true"; diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/sitetemplates/upgrades/SitetemplatesUpgrade.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/sitetemplates/upgrades/SitetemplatesUpgrade.testcase index 5ebb01a3429c50..a40f2d77463358 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/sitetemplates/upgrades/SitetemplatesUpgrade.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/sitetemplates/upgrades/SitetemplatesUpgrade.testcase @@ -1,6 +1,7 @@ @component-name = "portal-headless" definition { + property browser.chrome.version = "139.0"; property ci.retries.disabled = "true"; property custom.properties = "passwords.encryption.algorithm.legacy=PBKDF2WithHmacSHA1/160/128000"; property database.types = "db2,mariadb,mysql,oracle,postgresql,sqlserver"; diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/RemoteStaging.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/RemoteStaging.testcase index 7fe7d94fe77c76..81bd4f4ea1c771 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/RemoteStaging.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/RemoteStaging.testcase @@ -2,6 +2,7 @@ definition { property app.server.bundles.size = "1"; + property browser.chrome.version = "139.0"; property ci.retries.disabled = "true"; property custom.properties = "auth.verifier.TunnelAuthVerifier.hosts.allowed=${line.separator}tunneling.servlet.shared.secret=1234567890123456"; property databases.size = "1"; diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/Staging.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/Staging.testcase index edc7785901ade1..4762791dda189e 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/Staging.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/Staging.testcase @@ -1,6 +1,7 @@ @component-name = "portal-headless" definition { + property browser.chrome.version = "139.0"; property ci.retries.disabled = "true"; property custom.properties = "feature.flag.LPD-35013=false"; property osgi.modules.includes = "wiki"; diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/StagingUsecase.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/StagingUsecase.testcase index c151993b314726..d24c0f442ee61f 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/StagingUsecase.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/StagingUsecase.testcase @@ -1,6 +1,7 @@ @component-name = "portal-headless" definition { + property browser.chrome.version = "139.0"; property ci.retries.disabled = "true"; property custom.properties = "feature.flag.LPD-35013=false"; property osgi.modules.includes = "wiki"; diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/StagingUsecaseWithRoles.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/StagingUsecaseWithRoles.testcase index c62b85a06ec5e5..5832d988a57bf1 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/StagingUsecaseWithRoles.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/StagingUsecaseWithRoles.testcase @@ -1,6 +1,7 @@ @component-name = "portal-headless" definition { + property browser.chrome.version = "139.0"; property ci.retries.disabled = "true"; property portal.release = "true"; property portal.upstream = "true"; diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/StagingUsecaseWithVersioning.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/StagingUsecaseWithVersioning.testcase index e2c79c0e58f66f..9e2c02ff8389a5 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/StagingUsecaseWithVersioning.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/staging/usecase/StagingUsecaseWithVersioning.testcase @@ -1,6 +1,7 @@ @component-name = "portal-headless" definition { + property browser.chrome.version = "139.0"; property ci.retries.disabled = "true"; property portal.release = "true"; property portal.upstream = "true"; diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/wem/site/SiteTemplatesWithPermissions.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/wem/site/SiteTemplatesWithPermissions.testcase index bce2015b81507f..f58c3b2a8357bb 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/wem/site/SiteTemplatesWithPermissions.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/wem/site/SiteTemplatesWithPermissions.testcase @@ -1,6 +1,7 @@ @component-name = "portal-headless" definition { + property browser.chrome.version = "139.0"; property ci.retries.disabled = "true"; property portal.release = "true"; property portal.upstream = "true"; From 03a56590126441338149beafe36d5f764815202f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Thu, 25 Sep 2025 11:12:35 +0200 Subject: [PATCH 11/16] LPD-52709 Move upgrade tests to Chrome 139 --- .../tests/coreinfrastructure/upgrades/DBStoreUpgrade.testcase | 1 + .../coreinfrastructure/upgrades/PortalSmokeAutoUpgrade.testcase | 1 + .../coreinfrastructure/upgrades/PortalSmokeUpgrade.testcase | 1 + .../coreinfrastructure/upgrades/VirtualInstancesUpgrade.testcase | 1 + .../enduser/wem/upgrades/layout/WidgetPagesUpgrade.testcase | 1 + 5 files changed, 5 insertions(+) diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/DBStoreUpgrade.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/DBStoreUpgrade.testcase index 304dbfad8b1c69..d576da65599948 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/DBStoreUpgrade.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/DBStoreUpgrade.testcase @@ -1,6 +1,7 @@ @component-name = "portal-db-infrastructure" definition { + property browser.chrome.version = "139.0"; property custom.properties = "dl.store.impl=com.liferay.portal.store.db.DBStore"; property portal.release = "true"; property portal.upstream = "true"; diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/PortalSmokeAutoUpgrade.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/PortalSmokeAutoUpgrade.testcase index 18aa6687409427..9f4b42d5c4987c 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/PortalSmokeAutoUpgrade.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/PortalSmokeAutoUpgrade.testcase @@ -2,6 +2,7 @@ definition { property app.server.types = "jboss,tomcat,weblogic,wildfly"; + property browser.chrome.version = "139.0"; property ci.retries.disabled = "true"; property database.auto.upgrade.enabled = "true"; property database.types = "db2,mariadb,mysql,oracle,postgresql,sqlserver"; diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/PortalSmokeUpgrade.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/PortalSmokeUpgrade.testcase index 6ee54baef3b78e..114fa319fb724d 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/PortalSmokeUpgrade.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/PortalSmokeUpgrade.testcase @@ -2,6 +2,7 @@ definition { property app.server.types = "jboss,tomcat,weblogic,wildfly"; + property browser.chrome.version = "139.0"; property ci.retries.disabled = "true"; property database.types = "db2,mariadb,mysql,oracle,postgresql,sqlserver"; property portal.release = "true"; diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/VirtualInstancesUpgrade.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/VirtualInstancesUpgrade.testcase index 4621c46d875ae9..8224df8d71da3d 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/VirtualInstancesUpgrade.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/coreinfrastructure/upgrades/VirtualInstancesUpgrade.testcase @@ -1,6 +1,7 @@ @component-name = "portal-db-infrastructure" definition { + property browser.chrome.version = "139.0"; property portal.release = "true"; property portal.upstream = "true"; property test.assert.warning.exceptions = "true"; diff --git a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/wem/upgrades/layout/WidgetPagesUpgrade.testcase b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/wem/upgrades/layout/WidgetPagesUpgrade.testcase index 6e1a1d7ea42b6c..13db5688e3cd79 100644 --- a/portal-web/test/functional/com/liferay/portalweb/tests/enduser/wem/upgrades/layout/WidgetPagesUpgrade.testcase +++ b/portal-web/test/functional/com/liferay/portalweb/tests/enduser/wem/upgrades/layout/WidgetPagesUpgrade.testcase @@ -1,6 +1,7 @@ @component-name = "portal-db-infrastructure" definition { + property browser.chrome.version = "139.0"; property ci.retries.disabled = "true"; property portal.release = "true"; property portal.upstream = "true"; From 02db058dca8910a9263ba084a89ff0c7a83ac276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Wed, 26 Nov 2025 14:13:33 +0100 Subject: [PATCH 12/16] LPD-52709 Fix test frontend-js-web/main/DynamicInlineScroll.spec.ts > Check user pagination url working correctly The legacy JS bundles in frontend-js-web use a custom build which bypasses the usual language handling plugin. Because of that we need to make sure that language keys end up in language.json and that they are loaded before the code using them is executed. --- ...erayGlobalObjectPostAUIDynamicInclude.java | 34 +++++++++++++++---- .../META-INF/resources/language.json | 19 +++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 modules/apps/frontend-js/frontend-js-web/src/main/resources/META-INF/resources/language.json diff --git a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPostAUIDynamicInclude.java b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPostAUIDynamicInclude.java index 3978abd0a3da74..b0ba5cca3811a9 100644 --- a/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPostAUIDynamicInclude.java +++ b/modules/apps/frontend-js/frontend-js-web/src/main/java/com/liferay/frontend/js/web/internal/servlet/taglib/LiferayGlobalObjectPostAUIDynamicInclude.java @@ -5,6 +5,7 @@ package com.liferay.frontend.js.web.internal.servlet.taglib; +import com.liferay.petra.string.StringPool; import com.liferay.portal.kernel.content.security.policy.ContentSecurityPolicyNonceProviderUtil; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; @@ -63,9 +64,16 @@ public void include( "frontend-js-web", "/Liferay.js"); _renderScript( - httpServletRequest, httpServletResponse.getWriter(), + null, httpServletRequest, httpServletResponse.getWriter(), webContextScriptAbsolutePortalURLBuilder.build(), "text/javascript"); + + _renderScript( + "await import(`@liferay/language" + + "/${Liferay.ThemeDisplay.getLanguageId()}/frontend-js-web" + + "/all.js`);", + httpServletRequest, httpServletResponse.getWriter(), null, + "module"); } catch (Exception exception) { _log.error(exception); @@ -90,8 +98,8 @@ protected void deactivate() { } private void _renderScript( - HttpServletRequest httpServletRequest, PrintWriter printWriter, - String src, String type) { + String content, HttpServletRequest httpServletRequest, + PrintWriter printWriter, String src, String type) { printWriter.print(""); + printWriter.print("\">"); + + if (Validator.isNotNull(content)) { + printWriter.print(content); + } + + printWriter.println(""); } private static final Log _log = LogFactoryUtil.getLog( diff --git a/modules/apps/frontend-js/frontend-js-web/src/main/resources/META-INF/resources/language.json b/modules/apps/frontend-js/frontend-js-web/src/main/resources/META-INF/resources/language.json new file mode 100644 index 00000000000000..629655881227f9 --- /dev/null +++ b/modules/apps/frontend-js/frontend-js-web/src/main/resources/META-INF/resources/language.json @@ -0,0 +1,19 @@ +{ + "keys": [ + "are-you-sure-you-want-to-remove-this-component", + "danger", + "due-to-inactivity-your-session-has-expired", + "due-to-inactivity-your-session-will-expire", + "no-reviewers-were-found", + "extend", + "minimize", + "page-x", + "please-contact-the-administrator-to-assign-reviewers", + "proceed", + "restore", + "reviewer", + "session-expires-in-x", + "there-was-an-unexpected-error.-please-refresh-the-current-page", + "this-change-will-only-be-shown-after-you-refresh-the-page" + ] +} \ No newline at end of file From acd0e2d4565c4615856bc8a2d54f525ce2a689c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Wed, 26 Nov 2025 14:37:23 +0100 Subject: [PATCH 13/16] LPD-52709 Fix frontend-js-web/main/liferayGlobalObject.spec.ts > CORS does not stop requests when CDN is enabled --- .../tests/frontend-js-web/main/liferayGlobalObject.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/test/playwright/tests/frontend-js-web/main/liferayGlobalObject.spec.ts b/modules/test/playwright/tests/frontend-js-web/main/liferayGlobalObject.spec.ts index c004450aab1e68..cb0d1a72829c5f 100644 --- a/modules/test/playwright/tests/frontend-js-web/main/liferayGlobalObject.spec.ts +++ b/modules/test/playwright/tests/frontend-js-web/main/liferayGlobalObject.spec.ts @@ -37,7 +37,7 @@ test( const crossoriginAttr = await page .locator( - 'script[src^="http://127.0.0.1/o/frontend-js-web/Liferay.js"]' + 'script[src^="http://127.0.0.1/o/frontend-js-web/Liferay.("]' ) .getAttribute('crossorigin', {timeout: 1000}); @@ -52,7 +52,7 @@ test( await page.getByRole('button', {name: 'Save'}).click(); await expect( - page.locator('script[src^="/o/frontend-js-web/Liferay.js"]') + page.locator('script[src^="/o/frontend-js-web/Liferay.("]') ).not.toHaveAttribute('crossorigin', ''); }); } From ac34657e1c09e1d45b2ee4a34f0dba4f32687aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Thu, 27 Nov 2025 14:08:57 +0100 Subject: [PATCH 14/16] LPD-52709 Fix PortletRenderUtilTest --- .../portlet/render/PortletRenderUtilTest.java | 110 ++++++++++-------- 1 file changed, 62 insertions(+), 48 deletions(-) diff --git a/portal-kernel/test/unit/com/liferay/portal/kernel/portlet/render/PortletRenderUtilTest.java b/portal-kernel/test/unit/com/liferay/portal/kernel/portlet/render/PortletRenderUtilTest.java index 2a3c1befa13607..2d51d75392a81e 100644 --- a/portal-kernel/test/unit/com/liferay/portal/kernel/portlet/render/PortletRenderUtilTest.java +++ b/portal-kernel/test/unit/com/liferay/portal/kernel/portlet/render/PortletRenderUtilTest.java @@ -78,25 +78,29 @@ public void testGetPortletRenderParts() throws Exception { portletRenderParts.getHeaderCssPaths()); _assertEquals( Arrays.asList( - "/header-portal.js?t=7", "/nocombo-header-portal.js?t=7", - "/o/portlet-web/header-portlet.js?t=7", - "/o/portlet-web/nocombo-header-portlet.js?t=7", + "/header-portal.(" + _HASH + ").js", + "/nocombo-header-portal.(" + _HASH + ").js", + "/o/portlet-web/header-portlet.(" + _HASH + ").js", + "/o/portlet-web/nocombo-header-portlet.(" + _HASH + ").js", "http://example.com/header-portal.js", "http://example.com/header-portlet.js", - "module:/module-header-portal.js?t=7", - "module:/o/portlet-web/module-header-portlet.js?t=7", + "module:/module-header-portal.(" + _HASH + ").js", + "module:/o/portlet-web/module-header-portlet.(" + _HASH + + ").js", "module:http://example.com/module-header-portal.js", "module:http://example.com/module-header-portlet.js"), portletRenderParts.getHeaderJavaScriptPaths()); _assertEquals( Arrays.asList( - "/footer-portal.js?t=7", "/nocombo-footer-portal.js?t=7", - "/o/portlet-web/footer-portlet.js?t=7", - "/o/portlet-web/nocombo-footer-portlet.js?t=7", + "/footer-portal.(" + _HASH + ").js", + "/nocombo-footer-portal.(" + _HASH + ").js", + "/o/portlet-web/footer-portlet.(" + _HASH + ").js", + "/o/portlet-web/nocombo-footer-portlet.(" + _HASH + ").js", "http://example.com/footer-portal.js", "http://example.com/footer-portlet.js", - "module:/module-footer-portal.js?t=7", - "module:/o/portlet-web/module-footer-portlet.js?t=7", + "module:/module-footer-portal.(" + _HASH + ").js", + "module:/o/portlet-web/module-footer-portlet.(" + _HASH + + ").js", "module:http://example.com/module-footer-portal.js", "module:http://example.com/module-footer-portlet.js"), portletRenderParts.getFooterJavaScriptPaths()); @@ -144,14 +148,16 @@ public void testGetPortletRenderPartsWithContext() throws Exception { portletRenderParts.getHeaderCssPaths()); _assertEquals( Arrays.asList( - "/portal/header-portal.js?t=7", - "/portal/nocombo-header-portal.js?t=7", - "/portal/o/portlet-web/header-portlet.js?t=7", - "/portal/o/portlet-web/nocombo-header-portlet.js?t=7", + "/portal/header-portal.(" + _HASH + ").js", + "/portal/nocombo-header-portal.(" + _HASH + ").js", + "/portal/o/portlet-web/header-portlet.(" + _HASH + ").js", + "/portal/o/portlet-web/nocombo-header-portlet.(" + _HASH + + ").js", "http://example.com/header-portal.js", "http://example.com/header-portlet.js", - "module:/portal/module-header-portal.js?t=7", - "module:/portal/o/portlet-web/module-header-portlet.js?t=7", + "module:/portal/module-header-portal.(" + _HASH + ").js", + "module:/portal/o/portlet-web/module-header-portlet.(" + _HASH + + ").js", "module:http://example.com/module-header-portal.js", "module:http://example.com/module-header-portlet.js"), portletRenderParts.getHeaderJavaScriptPaths()); @@ -171,14 +177,16 @@ public void testGetPortletRenderPartsWithContext() throws Exception { portletRenderParts.getFooterCssPaths()); _assertEquals( Arrays.asList( - "/portal/footer-portal.js?t=7", - "/portal/nocombo-footer-portal.js?t=7", - "/portal/o/portlet-web/footer-portlet.js?t=7", - "/portal/o/portlet-web/nocombo-footer-portlet.js?t=7", + "/portal/footer-portal.(" + _HASH + ").js", + "/portal/nocombo-footer-portal.(" + _HASH + ").js", + "/portal/o/portlet-web/footer-portlet.(" + _HASH + ").js", + "/portal/o/portlet-web/nocombo-footer-portlet.(" + _HASH + + ").js", "http://example.com/footer-portal.js", "http://example.com/footer-portlet.js", - "module:/portal/module-footer-portal.js?t=7", - "module:/portal/o/portlet-web/module-footer-portlet.js?t=7", + "module:/portal/module-footer-portal.(" + _HASH + ").js", + "module:/portal/o/portlet-web/module-footer-portlet.(" + _HASH + + ").js", "module:http://example.com/module-footer-portal.js", "module:http://example.com/module-footer-portlet.js"), portletRenderParts.getFooterJavaScriptPaths()); @@ -217,15 +225,16 @@ public void testGetPortletRenderPartsWithContextAndProxy() portletRenderParts.getHeaderCssPaths()); _assertEquals( Arrays.asList( - "/proxy/portal/header-portal.js?t=7", - "/proxy/portal/nocombo-header-portal.js?t=7", - "/proxy/portal/o/portlet-web/header-portlet.js?t=7", - "/proxy/portal/o/portlet-web/nocombo-header-portlet.js?t=7", + "/proxy/portal/header-portal.(" + _HASH + ").js", + "/proxy/portal/nocombo-header-portal.(" + _HASH + ").js", + "/proxy/portal/o/portlet-web/header-portlet.(" + _HASH + ").js", + "/proxy/portal/o/portlet-web/nocombo-header-portlet.(" + _HASH + + ").js", "http://example.com/header-portal.js", "http://example.com/header-portlet.js", - "module:/proxy/portal/module-header-portal.js?t=7", - "module:/proxy/portal/o/portlet-web/module-header-portlet.js?" + - "t=7", + "module:/proxy/portal/module-header-portal.(" + _HASH + ").js", + "module:/proxy/portal/o/portlet-web/module-header-portlet.(" + + _HASH + ").js", "module:http://example.com/module-header-portal.js", "module:http://example.com/module-header-portlet.js"), portletRenderParts.getHeaderJavaScriptPaths()); @@ -247,15 +256,16 @@ public void testGetPortletRenderPartsWithContextAndProxy() portletRenderParts.getFooterCssPaths()); _assertEquals( Arrays.asList( - "/proxy/portal/footer-portal.js?t=7", - "/proxy/portal/nocombo-footer-portal.js?t=7", - "/proxy/portal/o/portlet-web/footer-portlet.js?t=7", - "/proxy/portal/o/portlet-web/nocombo-footer-portlet.js?t=7", + "/proxy/portal/footer-portal.(" + _HASH + ").js", + "/proxy/portal/nocombo-footer-portal.(" + _HASH + ").js", + "/proxy/portal/o/portlet-web/footer-portlet.(" + _HASH + ").js", + "/proxy/portal/o/portlet-web/nocombo-footer-portlet.(" + _HASH + + ").js", "http://example.com/footer-portal.js", "http://example.com/footer-portlet.js", - "module:/proxy/portal/module-footer-portal.js?t=7", - "module:/proxy/portal/o/portlet-web/module-footer-portlet.js?" + - "t=7", + "module:/proxy/portal/module-footer-portal.(" + _HASH + ").js", + "module:/proxy/portal/o/portlet-web/module-footer-portlet.(" + + _HASH + ").js", "module:http://example.com/module-footer-portal.js", "module:http://example.com/module-footer-portlet.js"), portletRenderParts.getFooterJavaScriptPaths()); @@ -290,14 +300,16 @@ public void testGetPortletRenderPartsWithProxy() throws Exception { portletRenderParts.getHeaderCssPaths()); _assertEquals( Arrays.asList( - "/proxy/header-portal.js?t=7", - "/proxy/nocombo-header-portal.js?t=7", - "/proxy/o/portlet-web/header-portlet.js?t=7", - "/proxy/o/portlet-web/nocombo-header-portlet.js?t=7", + "/proxy/header-portal.(" + _HASH + ").js", + "/proxy/nocombo-header-portal.(" + _HASH + ").js", + "/proxy/o/portlet-web/header-portlet.(" + _HASH + ").js", + "/proxy/o/portlet-web/nocombo-header-portlet.(" + _HASH + + ").js", "http://example.com/header-portal.js", "http://example.com/header-portlet.js", - "module:/proxy/module-header-portal.js?t=7", - "module:/proxy/o/portlet-web/module-header-portlet.js?t=7", + "module:/proxy/module-header-portal.(" + _HASH + ").js", + "module:/proxy/o/portlet-web/module-header-portlet.(" + _HASH + + ").js", "module:http://example.com/module-header-portal.js", "module:http://example.com/module-header-portlet.js"), portletRenderParts.getHeaderJavaScriptPaths()); @@ -317,14 +329,16 @@ public void testGetPortletRenderPartsWithProxy() throws Exception { portletRenderParts.getFooterCssPaths()); _assertEquals( Arrays.asList( - "/proxy/footer-portal.js?t=7", - "/proxy/nocombo-footer-portal.js?t=7", - "/proxy/o/portlet-web/footer-portlet.js?t=7", - "/proxy/o/portlet-web/nocombo-footer-portlet.js?t=7", + "/proxy/footer-portal.(" + _HASH + ").js", + "/proxy/nocombo-footer-portal.(" + _HASH + ").js", + "/proxy/o/portlet-web/footer-portlet.(" + _HASH + ").js", + "/proxy/o/portlet-web/nocombo-footer-portlet.(" + _HASH + + ").js", "http://example.com/footer-portal.js", "http://example.com/footer-portlet.js", - "module:/proxy/module-footer-portal.js?t=7", - "module:/proxy/o/portlet-web/module-footer-portlet.js?t=7", + "module:/proxy/module-footer-portal.(" + _HASH + ").js", + "module:/proxy/o/portlet-web/module-footer-portlet.(" + _HASH + + ").js", "module:http://example.com/module-footer-portal.js", "module:http://example.com/module-footer-portlet.js"), portletRenderParts.getFooterJavaScriptPaths()); From ef0fab1e8937c784132f4fb922e3656625e423bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Mon, 1 Dec 2025 11:55:48 +0100 Subject: [PATCH 15/16] LPD-52709 Add hashes to import maps This should fix most of the failing tests for build https://github.com/liferay-frontend/liferay-portal/pull/5112#issuecomment-3589802391 --- .../AbsolutePortalURLBuilderImpl.java | 4 +- .../ESModuleAbsolutePortalURLBuilderImpl.java | 59 +++---------------- 2 files changed, 10 insertions(+), 53 deletions(-) diff --git a/modules/apps/portal-url-builder/portal-url-builder-impl/src/main/java/com/liferay/portal/url/builder/internal/AbsolutePortalURLBuilderImpl.java b/modules/apps/portal-url-builder/portal-url-builder-impl/src/main/java/com/liferay/portal/url/builder/internal/AbsolutePortalURLBuilderImpl.java index 9965933d1d0327..966795f2e9418e 100644 --- a/modules/apps/portal-url-builder/portal-url-builder-impl/src/main/java/com/liferay/portal/url/builder/internal/AbsolutePortalURLBuilderImpl.java +++ b/modules/apps/portal-url-builder/portal-url-builder-impl/src/main/java/com/liferay/portal/url/builder/internal/AbsolutePortalURLBuilderImpl.java @@ -96,8 +96,8 @@ public ESModuleAbsolutePortalURLBuilder forESModule( String webContextPath, String esModulePath) { return new ESModuleAbsolutePortalURLBuilderImpl( - esModulePath, _getCDNHost(_httpServletRequest), _pathModule, - _pathProxy, webContextPath); + _getCDNHost(_httpServletRequest), esModulePath, + _hashedFilesRegistry, _pathModule, _pathProxy, webContextPath); } @Override diff --git a/modules/apps/portal-url-builder/portal-url-builder-impl/src/main/java/com/liferay/portal/url/builder/internal/ESModuleAbsolutePortalURLBuilderImpl.java b/modules/apps/portal-url-builder/portal-url-builder-impl/src/main/java/com/liferay/portal/url/builder/internal/ESModuleAbsolutePortalURLBuilderImpl.java index 87566dd69ea98c..b3d14142d80212 100644 --- a/modules/apps/portal-url-builder/portal-url-builder-impl/src/main/java/com/liferay/portal/url/builder/internal/ESModuleAbsolutePortalURLBuilderImpl.java +++ b/modules/apps/portal-url-builder/portal-url-builder-impl/src/main/java/com/liferay/portal/url/builder/internal/ESModuleAbsolutePortalURLBuilderImpl.java @@ -5,68 +5,25 @@ package com.liferay.portal.url.builder.internal; -import com.liferay.petra.string.StringBundler; -import com.liferay.petra.string.StringPool; +import com.liferay.portal.kernel.frontend.hashed.files.HashedFilesRegistry; import com.liferay.portal.url.builder.ESModuleAbsolutePortalURLBuilder; -import com.liferay.portal.url.builder.internal.util.URLUtil; /** * @author Iván Zaera Avellón */ public class ESModuleAbsolutePortalURLBuilderImpl + extends BaseWebContextResourceAbsolutePortalURLBuilderImpl + implements ESModuleAbsolutePortalURLBuilder { public ESModuleAbsolutePortalURLBuilderImpl( - String esModulePath, String cdnHost, String pathModule, + String cdnHost, String esModulePath, + HashedFilesRegistry hashedFilesRegistry, String pathModule, String pathProxy, String webContextPath) { - if (!esModulePath.startsWith(StringPool.SLASH)) { - esModulePath = StringPool.SLASH + esModulePath; - } - - if (!webContextPath.startsWith(StringPool.SLASH)) { - webContextPath = StringPool.SLASH + webContextPath; - } - - _esModulePath = esModulePath; - _cdnHost = cdnHost; - _pathModule = pathModule; - _pathProxy = pathProxy; - _webContextPath = webContextPath; + super( + cdnHost, hashedFilesRegistry, pathModule, pathProxy, + "/__liferay__/" + esModulePath, webContextPath); } - @Override - public String build() { - StringBundler sb = new StringBundler(); - - URLUtil.appendURL( - sb, _cdnHost, _ignoreCDNHost, _ignorePathProxy, - _pathModule + _webContextPath + "/__liferay__", _pathProxy, - _esModulePath); - - return sb.toString(); - } - - @Override - public ESModuleAbsolutePortalURLBuilder ignoreCDNHost() { - _ignoreCDNHost = true; - - return this; - } - - @Override - public ESModuleAbsolutePortalURLBuilder ignorePathProxy() { - _ignorePathProxy = true; - - return this; - } - - private final String _cdnHost; - private final String _esModulePath; - private boolean _ignoreCDNHost; - private boolean _ignorePathProxy; - private final String _pathModule; - private final String _pathProxy; - private final String _webContextPath; - } \ No newline at end of file From b2eb97c06b1472f01b742d07f1827e8723c60016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Zaera=20Avell=C3=B3n?= Date: Fri, 28 Nov 2025 10:03:00 +0100 Subject: [PATCH 16/16] LPD-52709 Update node-scripts SHA --- modules/_node-scripts/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/_node-scripts/package.json b/modules/_node-scripts/package.json index 18bb8736849432..cbf865afdea9da 100644 --- a/modules/_node-scripts/package.json +++ b/modules/_node-scripts/package.json @@ -4,7 +4,7 @@ "node-scripts": "./bin.js" }, "com.liferay": { - "sha256": "00d2a972afe65186b666efa058975f387ea44673708b4158204d3bbdba5cc781" + "sha256": "731360bca3b133cedbdc76f8b0ee91196992ac777cbd90f7b21ae9f4105701fd" }, "dependencies": { "@babel/preset-env": "7.24.7",