FIX: Use only a valid JavaScript identifier as the client side object name - #144
Conversation
… name An object name that is not a valid JavaScript identifier was written into the script as given, which broke the script or changed what it does. The builder already refused a configured name that did not match the identifier pattern, but the query.fod-js-object-name evidence was used with no check, and reserved words were accepted from both. A name requested with that evidence that is not valid is now ignored, the configured name is used and a warning is logged. The configured name check now also refuses reserved words, and the element's public constructor applies the same check, so a name that does not come through the builder is refused too. JavaScriptObjectNameTests renders the script with a different name from the builder and from evidence, parses it and runs it with the GraalVM JavaScript engine the module already depends on, so no browser is needed.
The script defines a constructor called fiftyoneDegreesManager and calls it to create the object, so an object with that name would clash with it. The name is now refused in configuration and ignored with a warning in evidence, like the reserved words.
An empty configured object name was treated as no name at all, so it quietly became fod. An empty name is a name that cannot work, so the element now refuses it when it is built, the same as any other name that is not a valid JavaScript identifier. A name that is not configured is now a null name, which means fod, and the builder starts with fod rather than with an empty name.
Proven in CIFull build and test run on this branch: https://github.com/51Degrees/pipeline-java/actions/runs/35187912996 A draft pull request only runs the link lint, so the Pull Requests workflow was dispatched against this branch as a dry run to get real evidence. Nothing was merged, and the log shows why: with no pull request based on this branch the run builds the branch on its own as pull request 0, and the checkout and completion steps both print "Not running for a PR". All 15 jobs finished green, being 11 build and test jobs (Java 8, 11, 17 and 21 on Ubuntu and Windows, and Java 11, 17 and 21 on macOS), the pull request lookup, the configure step, the performance comparison and the completion step. Reading the job logs rather than the conclusions, each job reports 23 Maven module summaries, and on Java 11 and later they add up to 647 tests run with 0 failures, 0 errors and 0 skipped. Java 8 runs 632, the difference being the tests that need a later Java. The log contains no "BUILD FAILURE", no "FAILURES!", no "ERRORS!" and no summary line with a non-zero failure or error count. The pull request has not been marked ready and no review has been requested. |
Problem
An object name that is not a valid JavaScript identifier was written into the script as given, which broke the script or changed what it does.
The name of the client side object (
fodby default) comes from two places.JavaScriptBuilderElementBuilder.setObjectName. This already refused a name that did not match the identifier pattern, but it accepted reserved words such asvar.query.fod-js-object-nameevidence.JavaScriptBuilderElement.buildJavaScriptused any non-empty value with no check at all, and the template writes the name into thevardeclaration, the session storage key, thewindow["<name>Evidence"]lookup and the warning shown when the script is loaded twice.Change
JavaScriptBuilderElement.isValidObjectNameaccepts a name only when it matches^[A-Za-z_$][A-Za-z0-9_$]*$and is not on the refused list. That list holds the reserved words of the language, plus two further groups.Infinity,NaNandundefinedare refused because a top levelvarcannot replace them, so the object would silently never be created.fiftyoneDegreesManageris refused because it is the constructor the script defines and calls to create the object. The other languages use the same list.query.fod-js-object-nameevidence that is not valid, including an empty value, is ignored. The configured name is used instead and a warning is logged. The warning does not repeat the requested value.setObjectNameuses the same check, so a name on the refused list is now refused withPipelineConfigurationExceptionas well.fod, because no name was configured, and an empty name is refused.The rendered output for a valid name is unchanged.
Tests
JavaScriptObjectNameTestsneeds no browser. It renders the script against a mocked flow data, parses it, and then runs it with the GraalVM JavaScript engine the module already depends on, against a minimalwindow,documentandsessionStorage.ObjectName_FromBuilder_UsedThroughoutandObjectName_FromEvidence_UsedThroughoutusemyFod. They check the script declaresvar myFodand nevervar fod, that the storage key and the evidence lookup usemyFod, that the script parses, and that once runwindow.myFodexists,complete,onChangeandrefreshare functions andmyFod.device.ismobileistrue.ObjectName_InvalidFromEvidence_DefaultUsedcoversa;b//,9bad,x"y, the empty string,classandfiftyoneDegreesManager. Each must give a workingfodobject, a script that parses, one warning, and none of the requested text in the code. The line that holds the script's own request parameters is left out of that last check, because it carries the page's query back to the endpoint as url encoded JSON strings, which is data and not code.ObjectName_InvalidFromEvidence_ConfiguredNameUsedchecks the fallback is the configured name and not alwaysfod.ObjectName_InvalidFromBuilder_RefusedandObjectName_InvalidFromConstructor_Refusedcheck the configuration error, including forfiftyoneDegreesManager.Verification
Run with
mvn -o -pl pipeline.javascriptbuilder -am test -Dtest=JavaScriptObjectNameTests,JavaScriptBuilderElementBuilderTests,CookieTests -Dsurefire.failIfNoSpecifiedTests=false.JavaScriptBuilderTestswas not run because it starts Chrome.CookieTests, 14 inJavaScriptBuilderElementBuilderTests, 20 inJavaScriptObjectNameTests).main, the first version ofJavaScriptObjectNameTests(17 tests) gave 11 failures. All four constructor cases, the reserved word builder case, all five invalid evidence cases and the configured fallback case failed. For the empty value,mainalready fell back tofod, so that case failed only on the new warning.fiftyoneDegreesManagercases were the only failures, 3 out of 20.Outstanding
JavaScriptBuilderTests.JavaScriptBuilderElement_VerifyObjNamestill runs in a browser and still passes a valid name, so it is unaffected.Alignment with the other languages, third commit
An empty configured name was treated as no name at all and quietly became
fod. The agreed rule is that a name which is not configured at all, meaning absent or null, meansfod, and that a configured name which is not valid, including an empty one, is refused when the element is built. The third commit brings this repository to that rule.fod.JavaScriptBuilderElementBuilderstarts withfodrather than with an empty name, andsetObjectName(null)leaves that default in place.ObjectName_InvalidFromConstructor_Refusednow covers the empty name, andObjectName_NotConfigured_DefaultUsedchecks that a name that was never set, a name set to null and a null name given to the constructor all give a workingfodobject.With the third commit's source changes removed and its tests in place, 2 of the 22 tests fail:
With the third commit, the module's tests pass, leaving out
JavaScriptBuilderTestsbecause it starts a browser:The session id and the sequence are handled in a separate draft, #145, which changes the same file in different methods.
The same change in the other ports
The Node port of this change is
pipeline-node#206.
The merges between this draft, #143 and #145 were run locally in both
directions and all six are clean. The three way merge was built and tested
as well, giving
Tests run: 74, Failures: 0, Errors: 0, Skipped: 0andBUILD SUCCESSforpipeline.javascriptbuilder, leaving out the test thatstarts a browser. So the three can land in any order without a merge.
CI on this branch, 17 September 2026
The "Pull Requests" workflow was dispatched on this branch with
dryrun=true,which builds the branch and merges nothing. Run
35187912996
ran on
1f60be0, the head of this branch, and concluded success with all 15jobs green. In the
Ubuntu_Java_21job the Maven totals are 647 tests run, 0failures, 0 errors and 6 skipped, with no error lines in the log.
This branch is three commits behind
mainand merges into it cleanly.The nightly checks out the pull request, merges
maininto it and buildsthat before it merges anything, so the combination is tested there.