This is an automated email from the ASF dual-hosted git repository.
thiagohp pushed a commit to branch feature/requirejs-less
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git
The following commit(s) were added to refs/heads/feature/requirejs-less by this
push:
new 273babbcb TAP5-2810: hopefully final ES module import and init fixes
273babbcb is described below
commit 273babbcb70becae67488eab23bbb7cbf782eb00
Author: Thiago H. de Paula Figueiredo <[email protected]>
AuthorDate: Sat Aug 2 00:49:35 2025 -0300
TAP5-2810: hopefully final ES module import and init fixes
---
.../internal/services/DocumentLinkerImpl.java | 18 +++--
.../internal/services/EsModuleInitsManager.java | 32 +++++++--
.../services/ajax/EsModuleInitializationImpl.java | 11 ++++
.../services/javascript/EsModuleManagerImpl.java | 76 +++++-----------------
.../services/javascript/EsModuleManager.java | 12 ++--
.../src/main/typescript/src/t5/core/pageinit.ts | 8 ++-
.../ajax/JavaScriptSupportAutofocusTests.groovy | 2 +-
.../tapestry5/integration/app1/EsModuleTests.java | 1 -
8 files changed, 76 insertions(+), 84 deletions(-)
diff --git
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
index fd885ce87..41f8ef1a8 100644
---
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
+++
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
@@ -24,6 +24,7 @@ import
org.apache.tapestry5.services.javascript.ModuleConfigurationCallback;
import org.apache.tapestry5.services.javascript.ModuleManager;
import org.apache.tapestry5.services.javascript.StylesheetLink;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -38,7 +39,7 @@ public class DocumentLinkerImpl implements DocumentLinker
private final ModuleInitsManager initsManager = new ModuleInitsManager();
- private final EsModuleInitsManager esModulesinitsManager = new
EsModuleInitsManager();
+ private final EsModuleInitsManager esModulesInitsManager = new
EsModuleInitsManager();
private final List<ModuleConfigurationCallback>
moduleConfigurationCallbacks = CollectionFactory.newList();
@@ -154,11 +155,11 @@ public class DocumentLinkerImpl implements DocumentLinker
addElementBefore(head, existingMeta, "meta", "name", "generator",
"content", tapestryBanner);
}
- final List<EsModuleInitialization> esModuleInits =
esModulesinitsManager.getInits();
- if (isHtmlRoot && !esModuleInits.isEmpty())
+ final List<EsModuleInitialization> imports =
esModulesInitsManager.getImports();
+ if (isHtmlRoot && !imports.isEmpty())
{
esModuleManager.writeImportMap(root.find("head"),
esModuleConfigurationCallbacks);
- esModuleManager.writeImports(root, esModuleInits);
+ esModuleManager.writeImports(root, imports);
}
addScriptElements(root);
@@ -271,14 +272,17 @@ public class DocumentLinkerImpl implements DocumentLinker
"src", url);
}
+ // Write the initialization at this point.
if (requireJsEnabled)
{
- // Write the initialization at this point.
moduleManager.writeInitialization(body, libraryURLs,
initsManager.getSortedInits());
+
+ // Libraries were already added in the line above.
+ esModuleManager.writeInitialization(body, Collections.emptyList(),
esModulesInitsManager.getInitsAsJsonArrays());
}
else
{
- esModuleManager.writeInitialization(body, libraryURLs);
+ esModuleManager.writeInitialization(body, libraryURLs,
esModulesInitsManager.getInitsAsJsonArrays());
}
}
@@ -350,7 +354,7 @@ public class DocumentLinkerImpl implements DocumentLinker
public void addEsModuleInitialization(EsModuleInitialization
initialization)
{
assert initialization != null;
- esModulesinitsManager.add(initialization);
+ esModulesInitsManager.add(initialization);
hasScriptsOrInitializations = true;
}
diff --git
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EsModuleInitsManager.java
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EsModuleInitsManager.java
index 96a01f1d0..c79201b5c 100644
---
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EsModuleInitsManager.java
+++
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EsModuleInitsManager.java
@@ -39,27 +39,39 @@ public class EsModuleInitsManager
{
private final Set<String> modules = CollectionFactory.newSet();
+ private final List<EsModuleInitialization> imports =
CollectionFactory.newList();
+
private final List<EsModuleInitialization> initializations =
CollectionFactory.newList();
public void add(EsModuleInitialization initialization)
{
assert initialization != null;
- // We ignore a module being added again.
- final String moduleName = ((EsModuleInitializationImpl)
initialization).getModuleName();
- if (!modules.contains(moduleName))
+ // We avoid having the same module being imported more than twice.
+ // Also notice non-pure inits (i.e. ones having a function name or
+ // both) are added both to the imports, so they can have
+ // <script type="module"> added for them, and to initializations,
+ // the function call will be made by t5/core/pageinit.
+ final EsModuleInitializationImpl init = (EsModuleInitializationImpl)
initialization;
+ final String moduleName = init.getModuleName();
+ final boolean alreadyPresent = modules.contains(moduleName);
+ if (!init.isPure())
{
initializations.add(initialization);
+ }
+ if (!alreadyPresent)
+ {
+ imports.add(initialization);
modules.add(moduleName);
}
}
/**
- * Returns all previously added inits.
+ * Returns all imports.
*/
- public List<EsModuleInitialization> getInits()
+ public List<EsModuleInitialization> getImports()
{
- return initializations;
+ return imports;
}
/**
@@ -78,7 +90,13 @@ public class EsModuleInitsManager
final JSONArray arguments = initImpl.getArguments();
final JSONArray initArray = new JSONArray();
- initArray.add(initImpl.getModuleName());
+ String moduleName = initImpl.getModuleName();
+ if (initImpl.getFunctionName() != null)
+ {
+ moduleName = moduleName + ":" + initImpl.getFunctionName();
+ }
+
+ initArray.add(moduleName);
if (arguments != null)
{
diff --git
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsModuleInitializationImpl.java
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsModuleInitializationImpl.java
index 1fd947592..663b422f2 100644
---
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsModuleInitializationImpl.java
+++
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsModuleInitializationImpl.java
@@ -76,4 +76,15 @@ public class EsModuleInitializationImpl extends
BaseInitialization<EsModuleIniti
return arguments;
}
+ public boolean isPure()
+ {
+ return functionName == null && arguments == null;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ESInit[moduleName=" + moduleName + ", functionName=" +
functionName + ", arguments=" + arguments + "]";
+ }
+
}
\ No newline at end of file
diff --git
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
index b0f4090d2..9c773cfdd 100644
---
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
+++
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
@@ -25,7 +25,6 @@ import org.apache.tapestry5.commons.util.AvailableValues;
import org.apache.tapestry5.commons.util.CollectionFactory;
import org.apache.tapestry5.commons.util.UnknownValueException;
import org.apache.tapestry5.dom.Element;
-import org.apache.tapestry5.http.TapestryHttpSymbolConstants;
import org.apache.tapestry5.internal.InternalConstants;
import org.apache.tapestry5.internal.services.ajax.EsModuleInitializationImpl;
import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
@@ -48,8 +47,6 @@ import
org.apache.tapestry5.services.javascript.JavaScriptStack;
public class EsModuleManagerImpl implements EsModuleManager
{
- private static final String GENERIC_IMPORTED_VARIABLE = "m";
-
/**
* Name of the JSON object property containing the imports in an import
map.
*/
@@ -58,8 +55,8 @@ public class EsModuleManagerImpl implements EsModuleManager
private static final String CLASSPATH_ROOT = "META-INF/assets/es-modules/";
private final boolean compactJSON;
-
- private final boolean productionMode;
+
+ private final boolean requireJsEnabled;
private final Set<String> extensions;
@@ -88,8 +85,8 @@ public class EsModuleManagerImpl implements EsModuleManager
StreamableResourceSource streamableResourceSource,
@Symbol(SymbolConstants.COMPACT_JSON)
boolean compactJSON,
-
@Symbol(TapestryHttpSymbolConstants.PRODUCTION_MODE)
- boolean productionMode,
+ @Symbol(SymbolConstants.REQUIRE_JS_ENABLED)
+ boolean requireJsEnabled,
@Symbol(SymbolConstants.JAVASCRIPT_INFRASTRUCTURE_PROVIDER)
String infraProvider,
ClasspathScanner classpathScanner,
@@ -97,9 +94,9 @@ public class EsModuleManagerImpl implements EsModuleManager
@Core JavaScriptStack javaScriptStack)
{
this.compactJSON = compactJSON;
+ this.requireJsEnabled = requireJsEnabled;
this.assetSource = assetSource;
this.classpathScanner = classpathScanner;
- this.productionMode = productionMode;
this.resourceChangeTracker = resourceChangeTracker;
this.infraProvider = infraProvider;
@@ -217,8 +214,6 @@ public class EsModuleManagerImpl implements EsModuleManager
Element head = null;
ImportPlacement placement;
EsModuleInitializationImpl init;
- String functionName;
- JSONArray arguments;
List<EsModuleInitialization> allInits = new
ArrayList<>(coreStackInits.size() + inits.size());
allInits.addAll(coreStackInits);
@@ -229,6 +224,7 @@ public class EsModuleManagerImpl implements EsModuleManager
init = (EsModuleInitializationImpl) i;
final String moduleId = init.getModuleName();
+
// Making sure the user doesn't shoot their own foot
final String url = cache.get(moduleId);
if (url == null)
@@ -266,65 +262,23 @@ public class EsModuleManagerImpl implements
EsModuleManager
writeAttributes(script, init);
script.attribute("src", url);
-
- functionName = init.getFunctionName();
- arguments = init.getArguments();
-
- if (!productionMode)
- {
- script.attribute("data-module-id", moduleId);
- final Element log = script.element("script", "type",
"text/javascript");
- log.text(String.format("console.debug('Imported ES module
%s');", moduleId));
- log.moveBefore(script);
- }
-
- // If we have not only the import, but also an automatic function
call
- if (arguments != null || functionName != null)
- {
-
- // TODO: move this logic to a pageinit call, like AMD does
- // t5/core/pageinit:loadLibrariesAndInitialize
- final Element moduleFunctionCall = script.element("script");
-
- moduleFunctionCall.moveAfter(script);
-
- final String moduleFunctionCallFormat =
- "import m from '%s';\n"
- + "import console from 't5/core/console';\n"
- + "\nif (console.debugEnabled) {"
- + "\n console.debug('Invoking %1$s:%2$s(' +
(Array.from(%4$s).map(function(arg) { return JSON.stringify(arg); })).join(\",
\") + ')');"
- + "\n m.%2$s(%3$s);"
- + "\n}\n";
-
-
moduleFunctionCall.text(String.format(moduleFunctionCallFormat,
- moduleId,
- functionName,
- convertToJsFunctionParameters(arguments, compactJSON),
- arguments));
-
- writeAttributes(moduleFunctionCall, init);
-
- // Avoiding duplicated ids
- final String id = moduleFunctionCall.getAttribute("id");
- if (id != null)
- {
- moduleFunctionCall.forceAttributes("id", id +
"-function-call");
- }
-
- }
+ script.attribute("data-module-id", moduleId);
}
}
@Override
- public void writeInitialization(Element body, List<String> libraryURLs)
+ public void writeInitialization(Element body, List<String> libraryURLs,
List<JSONArray> inits)
{
- Element element = body.element("script", "type", "module");
-
- element.raw(String.format("import pageinit from
\"t5/core/pageinit\";\npageinit(%s, []);",
- convert(libraryURLs)));
+ if (!requireJsEnabled || !libraryURLs.isEmpty() || !inits.isEmpty())
+ {
+ Element element = body.element("script", "type", "module");
+
+ element.raw(String.format("import pageinit from
\"t5/core/pageinit\";\npageinit(%s, %s);",
+ convert(libraryURLs), convert(inits)));
+ }
}
private String convert(List<?> input)
diff --git
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
index cc57b47fe..0d97c0024 100644
---
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
+++
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
@@ -16,6 +16,7 @@ import java.util.List;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.ioc.annotations.UsesOrderedConfiguration;
+import org.apache.tapestry5.json.JSONArray;
import
org.apache.tapestry5.services.javascript.EsModuleManager.EsModuleManagerContribution;
/**
@@ -50,10 +51,10 @@ public interface EsModuleManager
*
* @param root
* {@code <root>} element of the page.
- * @param inits
- * specify initialization on the page, based on loading modules,
extacting functions from modules, and invoking those functions
+ * @param imports
+ * imported modules as {@linkplain EsModuleInitialization}
instances.
*/
- void writeImports(Element root, List<EsModuleInitialization> inits);
+ void writeImports(Element root, List<EsModuleInitialization> imports);
/**
@@ -64,9 +65,10 @@ public interface EsModuleManager
*
* @param body {@code body} element of the page.
* @param libraryURLs URLs of the JS files to be included in the page.
- *
+ * @param inits a list of {@linkplain} JSONArray} instances containing the
+ * module initializations.
*/
- void writeInitialization(Element body, List<String> libraryURLs);
+ void writeInitialization(Element body, List<String> libraryURLs,
List<JSONArray> inits);
/**
* Encapsulates a contribution to {@linkplain EsModuleManager}.
diff --git a/tapestry-core/src/main/typescript/src/t5/core/pageinit.ts
b/tapestry-core/src/main/typescript/src/t5/core/pageinit.ts
index 85d13124c..134bce505 100644
--- a/tapestry-core/src/main/typescript/src/t5/core/pageinit.ts
+++ b/tapestry-core/src/main/typescript/src/t5/core/pageinit.ts
@@ -35,7 +35,7 @@ const isOpera = Object.prototype.toString.call(window.opera)
=== '[object Opera]
// @ts-ignore
const isIE = !!window.attachEvent && !isOpera;
-const requireJsEnabled = "true" ==
document.querySelector("body")?.dataset['requireJsEnabled'];
+const requireJsEnabled = "true" ==
document.querySelector("html")?.dataset['requireJsEnabled'];
const rebuildURL = function(path: string) {
if (path.match(/^https?:/)) { return path; }
@@ -113,6 +113,10 @@ const invokeInitializer = function(tracker: () => any,
qualifiedName: string, in
function executeInitializer(moduleLib: any) {
+ if (!requireJsEnabled && moduleLib['default'] != null &&
_.isFunction(moduleLib['default'])) {
+ moduleLib = moduleLib['default'];
+ }
+
try {
// Some modules export nothing but do some full-page initialization,
such as adding
// event handlers to the body.
@@ -167,7 +171,7 @@ const invokeInitializer = function(tracker: () => any,
qualifiedName: string, in
} else {
return import(moduleName).then(function(moduleLib: any) {
- return executeInitializer(moduleLib['default']);
+ return executeInitializer(moduleLib);
});
}
diff --git
a/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportAutofocusTests.groovy
b/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportAutofocusTests.groovy
index c631d4448..7caf1b90d 100644
---
a/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportAutofocusTests.groovy
+++
b/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportAutofocusTests.groovy
@@ -42,7 +42,7 @@ class JavaScriptSupportAutofocusTests extends
InternalBaseTestCase {
replay()
// Test in partial mode, to bypass the logic about importing the
"core' stack.
- def jss = new JavaScriptSupportImpl(linker, stackSource,
stackPathConstructor, null, true, null)
+ def jss = new JavaScriptSupportImpl(linker, stackSource,
stackPathConstructor, null, true, null, true)
cls jss
diff --git
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/EsModuleTests.java
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/EsModuleTests.java
index d2ba735ee..26e85f508 100644
---
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/EsModuleTests.java
+++
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/EsModuleTests.java
@@ -30,7 +30,6 @@ import
org.apache.tapestry5.services.javascript.EsModuleConfigurationCallback;
import org.apache.tapestry5.services.javascript.EsModuleInitialization;
import org.apache.tapestry5.services.javascript.EsModuleManager;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
-import org.openqa.selenium.support.ui.ExpectedCondition;
import org.testng.annotations.Test;
/**