jsf.js_next_gen 4.0.0-RC.24 → 4.0.0-RC.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/window/faces-development.js +130 -33
- package/dist/window/faces-development.js.br +0 -0
- package/dist/window/faces-development.js.gz +0 -0
- package/dist/window/faces-development.js.map +1 -1
- package/dist/window/faces.js +1 -1
- package/dist/window/faces.js.br +0 -0
- package/dist/window/faces.js.gz +0 -0
- package/dist/window/faces.js.map +1 -1
- package/dist/window/jsf-development.js +130 -33
- package/dist/window/jsf-development.js.br +0 -0
- package/dist/window/jsf-development.js.gz +0 -0
- package/dist/window/jsf-development.js.map +1 -1
- package/dist/window/jsf.js +1 -1
- package/dist/window/jsf.js.br +0 -0
- package/dist/window/jsf.js.gz +0 -0
- package/dist/window/jsf.js.map +1 -1
- package/package.json +4 -4
- package/src/main/typescript/impl/AjaxImpl.ts +31 -3
- package/src/main/typescript/impl/core/Const.ts +1 -1
- package/src/main/typescript/impl/xhrCore/RequestDataResolver.ts +49 -2
- package/src/main/typescript/impl/xhrCore/Response.ts +3 -2
- package/src/main/typescript/impl/xhrCore/ResponseProcessor.ts +4 -4
- package/src/main/typescript/impl/xhrCore/XhrFormData.ts +44 -25
- package/src/main/typescript/impl/xhrCore/XhrRequest.ts +29 -9
- package/src/main/typescript/test/xhrCore/FileUploadTest.spec.ts +2 -0
- package/src/main/typescript/test/xhrCore/NamespacesRequestTest.spec.ts +8 -8
- package/src/main/typescript/test/xhrCore/ResponseTest.spec.ts +6 -5
- package/src/main/typescript/test/xhrCore/ResponseTest23.spec.ts +2 -2
- package/src/main/typescript/test/xhrCore/XhrFormDataTest.spec.ts +1 -0
- package/target/impl/AjaxImpl.js +19 -1
- package/target/impl/AjaxImpl.js.map +1 -1
- package/target/impl/core/Const.js +2 -2
- package/target/impl/core/Const.js.map +1 -1
- package/target/impl/xhrCore/RequestDataResolver.js +48 -1
- package/target/impl/xhrCore/RequestDataResolver.js.map +1 -1
- package/target/impl/xhrCore/Response.js +1 -1
- package/target/impl/xhrCore/Response.js.map +1 -1
- package/target/impl/xhrCore/ResponseProcessor.js +3 -3
- package/target/impl/xhrCore/ResponseProcessor.js.map +1 -1
- package/target/impl/xhrCore/XhrFormData.js +36 -19
- package/target/impl/xhrCore/XhrFormData.js.map +1 -1
- package/target/impl/xhrCore/XhrRequest.js +11 -2
- package/target/impl/xhrCore/XhrRequest.js.map +1 -1
- package/target/test/xhrCore/FileUploadTest.spec.js +1 -0
- package/target/test/xhrCore/FileUploadTest.spec.js.map +1 -1
- package/target/test/xhrCore/NamespacesRequestTest.spec.js +8 -7
- package/target/test/xhrCore/NamespacesRequestTest.spec.js.map +1 -1
- package/target/test/xhrCore/ResponseTest.spec.js +6 -3
- package/target/test/xhrCore/ResponseTest.spec.js.map +1 -1
- package/target/test/xhrCore/ResponseTest23.spec.js +2 -2
- package/target/test/xhrCore/ResponseTest23.spec.js.map +1 -1
- package/target/test/xhrCore/XhrFormDataTest.spec.js +1 -0
- package/target/test/xhrCore/XhrFormDataTest.spec.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jsf.js_next_gen",
|
|
3
|
-
"version": "4.0.0-RC.
|
|
3
|
+
"version": "4.0.0-RC.27",
|
|
4
4
|
"description": "A next generation typescript reimplementation of jsf.js",
|
|
5
5
|
"main": "dist/window/faces.js",
|
|
6
6
|
"scripts": {
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"compression-webpack-plugin": "^10.0.0",
|
|
31
31
|
"html-webpack-plugin": "^5.5.0",
|
|
32
32
|
"http-server": "^14.1.1",
|
|
33
|
-
"jsdom": "^21.
|
|
33
|
+
"jsdom": "^21.1.0",
|
|
34
34
|
"jsdom-global": "^3.0.2",
|
|
35
35
|
"mocha": "^10.2.0",
|
|
36
|
-
"npm-check-updates": "^16.6.
|
|
36
|
+
"npm-check-updates": "^16.6.3",
|
|
37
37
|
"nyc": "^15.1.0",
|
|
38
38
|
"replace-in-file": "^6.3.5",
|
|
39
39
|
"rxjs": "^7.8.0",
|
|
@@ -48,6 +48,6 @@
|
|
|
48
48
|
"webpack-dev-server": "^4.11.1"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"mona-dish": "^0.24.
|
|
51
|
+
"mona-dish": "^0.24.5"
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -48,13 +48,20 @@ import {
|
|
|
48
48
|
P_WINDOW_ID,
|
|
49
49
|
CTX_PARAM_RENDER,
|
|
50
50
|
SOURCE,
|
|
51
|
-
HTML_TAG_FORM,
|
|
51
|
+
HTML_TAG_FORM,
|
|
52
|
+
CTX_OPTIONS_PARAMS,
|
|
53
|
+
VIEW_ID,
|
|
54
|
+
$faces,
|
|
55
|
+
EMPTY_STR,
|
|
56
|
+
CTX_PARAM_MF_INTERNAL,
|
|
57
|
+
NAMED_VIEWROOT,
|
|
58
|
+
NAMING_CONTAINER_ID
|
|
52
59
|
} from "./core/Const";
|
|
53
60
|
import {
|
|
54
61
|
resolveDefaults,
|
|
55
62
|
resolveDelay,
|
|
56
63
|
resolveForm,
|
|
57
|
-
resolveTimeout, resolveViewId
|
|
64
|
+
resolveTimeout, resolveViewId, resolveViewRootId, resoveNamingContainerMapper
|
|
58
65
|
} from "./xhrCore/RequestDataResolver";
|
|
59
66
|
|
|
60
67
|
/*
|
|
@@ -337,6 +344,7 @@ export module Implementation {
|
|
|
337
344
|
assignClientWindowId(form, requestCtx);
|
|
338
345
|
assignExecute(options, requestCtx, form, elementId);
|
|
339
346
|
assignRender(options, requestCtx, form, elementId);
|
|
347
|
+
assignNamingContainerData(internalCtx, form);
|
|
340
348
|
|
|
341
349
|
//now we enqueue the request as asynchronous runnable into our request
|
|
342
350
|
//queue and let the queue take over the rest
|
|
@@ -522,7 +530,10 @@ export module Implementation {
|
|
|
522
530
|
throw new Error(getMessage("ERR_VIEWSTATE"));
|
|
523
531
|
}
|
|
524
532
|
|
|
525
|
-
|
|
533
|
+
const dummyContext = new Config({});
|
|
534
|
+
assignNamingContainerData(dummyContext, DQ.byId(form))
|
|
535
|
+
|
|
536
|
+
let formData = new XhrFormData(element, resoveNamingContainerMapper(dummyContext));
|
|
526
537
|
return formData.toString();
|
|
527
538
|
}
|
|
528
539
|
|
|
@@ -603,6 +614,23 @@ export module Implementation {
|
|
|
603
614
|
}
|
|
604
615
|
}
|
|
605
616
|
|
|
617
|
+
/**
|
|
618
|
+
* determines the current naming container
|
|
619
|
+
* and assigns it internally
|
|
620
|
+
*
|
|
621
|
+
* @param internalContext
|
|
622
|
+
* @param formElement
|
|
623
|
+
* @private
|
|
624
|
+
*/
|
|
625
|
+
function assignNamingContainerData(internalContext: Config, formElement: DQ) {
|
|
626
|
+
const viewRootId = resolveViewRootId(formElement);
|
|
627
|
+
|
|
628
|
+
if(!!viewRootId) {
|
|
629
|
+
internalContext.assign(NAMED_VIEWROOT).value = true;
|
|
630
|
+
internalContext.assign(NAMING_CONTAINER_ID).value = viewRootId;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
606
634
|
/**
|
|
607
635
|
* transforms the user values to the expected one
|
|
608
636
|
* with the proper none all form and this handling
|
|
@@ -22,7 +22,7 @@ export const XML_ATTR_NAMED_VIEWROOT = "namedViewRoot";
|
|
|
22
22
|
export const NAMED_VIEWROOT = "namedViewRoot";
|
|
23
23
|
|
|
24
24
|
export const P_PARTIAL_SOURCE = "jakarta.faces.source";
|
|
25
|
-
export const
|
|
25
|
+
export const NAMING_CONTAINER_ID = "myfaces.partialId";
|
|
26
26
|
|
|
27
27
|
export const VIEW_ID = "myfaces.viewId";
|
|
28
28
|
export const P_VIEWSTATE = "jakarta.faces.ViewState";
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {Config, DomQuery, DQ} from "mona-dish";
|
|
17
|
+
import {AssocArrayCollector, Config, DomQuery, DQ} from "mona-dish";
|
|
18
18
|
import {
|
|
19
19
|
$faces,
|
|
20
20
|
$nsp,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
DELAY_NONE,
|
|
24
24
|
EMPTY_FUNC,
|
|
25
25
|
EMPTY_STR,
|
|
26
|
-
ENCODED_URL,
|
|
26
|
+
ENCODED_URL, NAMED_VIEWROOT, NAMING_CONTAINER_ID,
|
|
27
27
|
P_VIEWSTATE,
|
|
28
28
|
REQ_TYPE_GET,
|
|
29
29
|
REQ_TYPE_POST
|
|
@@ -50,6 +50,7 @@ import {Assertions} from "../util/Assertions";
|
|
|
50
50
|
* @param funcName
|
|
51
51
|
*/
|
|
52
52
|
export function resolveHandlerFunc(requestContext: Config, responseContext: Config, funcName: string) {
|
|
53
|
+
responseContext = responseContext || new Config({});
|
|
53
54
|
return responseContext.getIf(funcName)
|
|
54
55
|
.orElseLazy(() =>requestContext.getIf(funcName).value)
|
|
55
56
|
.orElse(EMPTY_FUNC).value;
|
|
@@ -89,6 +90,52 @@ export function resolveViewId(form: DQ): string {
|
|
|
89
90
|
return form.id.value.indexOf(viewStateViewId) === 0 ? viewStateViewId : "";
|
|
90
91
|
}
|
|
91
92
|
|
|
93
|
+
export function resolveViewRootId(form: DQ): string {
|
|
94
|
+
const viewState = form.querySelectorAll(`input[type='hidden'][name*='${$nsp(P_VIEWSTATE)}']`).attr("name").orElse("").value;
|
|
95
|
+
const divider = $faces().separatorchar;
|
|
96
|
+
const viewId = viewState.split(divider, 2)[0];
|
|
97
|
+
//different to the identifier the form id is never prepended to the viewstate
|
|
98
|
+
return viewId.indexOf($nsp(P_VIEWSTATE)) === -1 ? viewId : "";
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* as per jsdoc before the request it must be ensured that every post argument
|
|
103
|
+
* is prefixed with the naming container id (there is an exception in mojarra with
|
|
104
|
+
* the element=element param, which we have to follow here as well.
|
|
105
|
+
* (inputs are prefixed by name anyway normally this only affects our standard parameters)
|
|
106
|
+
* @private
|
|
107
|
+
*/
|
|
108
|
+
export function resoveNamingContainerMapper(internalContext: Config): (key: string, value: any) => [string, any] {
|
|
109
|
+
const isNamedViewRoot = internalContext.getIf(NAMED_VIEWROOT).isPresent();
|
|
110
|
+
if(!isNamedViewRoot) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const partialId = internalContext.getIf(NAMING_CONTAINER_ID).value;
|
|
114
|
+
const SEP = $faces().separatorchar;
|
|
115
|
+
const prefix = partialId + SEP;
|
|
116
|
+
return (key: string, value: any) => (key.indexOf(prefix) == 0) ? [key, value] : [prefix + key, value];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* we provide the same for configs
|
|
121
|
+
* @param internalContext
|
|
122
|
+
*/
|
|
123
|
+
export function resoveConfigNamingContainerMapper(internalContext: Config): (config: Config) => ExtConfig {
|
|
124
|
+
const isNamedViewRoot = internalContext.getIf(NAMED_VIEWROOT).isPresent();
|
|
125
|
+
if(!isNamedViewRoot) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const partialId = internalContext.getIf(NAMING_CONTAINER_ID).value;
|
|
129
|
+
const SEP = $faces().separatorchar;
|
|
130
|
+
const prefix = partialId + SEP;
|
|
131
|
+
return (config: Config) => {
|
|
132
|
+
let assoc = config.stream
|
|
133
|
+
.map(([key, data]) => (key.indexOf(prefix) == 0) ? [key, data] : [prefix + key, data])
|
|
134
|
+
.collect(new AssocArrayCollector() as any);
|
|
135
|
+
return new ExtConfig(assoc);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
92
139
|
export function resolveTimeout(options: Config): number {
|
|
93
140
|
let getCfg = ExtLang.getLocalOrGlobalConfig;
|
|
94
141
|
return options.getIf(CTX_OPTIONS_TIMEOUT).value ?? getCfg(options.value, CTX_OPTIONS_TIMEOUT, 0);
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
P_VIEWBODY,
|
|
33
33
|
P_VIEWHEAD,
|
|
34
34
|
P_VIEWROOT,
|
|
35
|
-
|
|
35
|
+
NAMING_CONTAINER_ID,
|
|
36
36
|
XML_TAG_PARTIAL_RESP,
|
|
37
37
|
RESPONSE_XML,
|
|
38
38
|
XML_TAG_AFTER,
|
|
@@ -101,7 +101,8 @@ export module Response {
|
|
|
101
101
|
// under or in body as identifier
|
|
102
102
|
|
|
103
103
|
let partialId:string = node?.id?.value;
|
|
104
|
-
internalContext.assignIf(!!partialId,
|
|
104
|
+
internalContext.assignIf(!!partialId, NAMING_CONTAINER_ID).value = partialId; // second case mojarra
|
|
105
|
+
|
|
105
106
|
// there must be at least one container viewstate element resembling the viewroot that we know
|
|
106
107
|
// this is named
|
|
107
108
|
responseProcessor.updateNamedViewRootState();
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
P_RENDER,
|
|
51
51
|
P_RENDER_OVERRIDE,
|
|
52
52
|
P_VIEWSTATE,
|
|
53
|
-
|
|
53
|
+
NAMING_CONTAINER_ID,
|
|
54
54
|
RESPONSE_XML,
|
|
55
55
|
SEL_CLIENT_WINDOW_ELEM,
|
|
56
56
|
SEL_VIEWSTATE_ELEM,
|
|
@@ -348,7 +348,7 @@ export class ResponseProcessor implements IResponseProcessor {
|
|
|
348
348
|
fixViewStates() {
|
|
349
349
|
Stream.ofAssoc<StateHolder>(this.internalContext.getIf(APPLIED_VST).orElse({}).value)
|
|
350
350
|
.each(([, value]) => {
|
|
351
|
-
const namingContainerId = this.internalContext.getIf(
|
|
351
|
+
const namingContainerId = this.internalContext.getIf(NAMING_CONTAINER_ID);
|
|
352
352
|
const namedViewRoot = !!this.internalContext.getIf(NAMED_VIEWROOT).value
|
|
353
353
|
const affectedForms = this.getContainerForms(namingContainerId)
|
|
354
354
|
.filter(affectedForm => this.isInExecuteOrRender(affectedForm));
|
|
@@ -366,7 +366,7 @@ export class ResponseProcessor implements IResponseProcessor {
|
|
|
366
366
|
fixClientWindow() {
|
|
367
367
|
Stream.ofAssoc<StateHolder>(this.internalContext.getIf(APPLIED_CLIENT_WINDOW).orElse({}).value)
|
|
368
368
|
.each(([, value]) => {
|
|
369
|
-
const namingContainerId = this.internalContext.getIf(
|
|
369
|
+
const namingContainerId = this.internalContext.getIf(NAMING_CONTAINER_ID);
|
|
370
370
|
const namedViewRoot = !!this.internalContext.getIf(NAMED_VIEWROOT).value;
|
|
371
371
|
const affectedForms = this.getContainerForms(namingContainerId)
|
|
372
372
|
.filter(affectedForm => this.isInExecuteOrRender(affectedForm));
|
|
@@ -376,7 +376,7 @@ export class ResponseProcessor implements IResponseProcessor {
|
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
updateNamedViewRootState() {
|
|
379
|
-
let partialId = this.internalContext.getIf(
|
|
379
|
+
let partialId = this.internalContext.getIf(NAMING_CONTAINER_ID);
|
|
380
380
|
let namedViewRoot = this.internalContext.getIf(NAMED_VIEWROOT);
|
|
381
381
|
if(partialId.isPresent() &&
|
|
382
382
|
(namedViewRoot.isAbsent() ||
|
|
@@ -14,11 +14,14 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import {ArrayCollector, Config, DQ, Lang, LazyStream, Stream} from "mona-dish";
|
|
17
|
-
import {EMPTY_STR, IDENT_ALL, IDENT_FORM, P_VIEWSTATE} from "../core/Const";
|
|
17
|
+
import {$nsp, EMPTY_STR, IDENT_ALL, IDENT_FORM, P_VIEWSTATE} from "../core/Const";
|
|
18
18
|
import isString = Lang.isString;
|
|
19
19
|
import {ExtConfig, ExtDomQuery} from "../util/ExtDomQuery";
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
type ParamsMapper<V, K> = (key: V, item: K) => [V, K];
|
|
23
|
+
const defaultParamsMapper: ParamsMapper<string, any> = (key, item) => [key, item];
|
|
24
|
+
|
|
22
25
|
/**
|
|
23
26
|
* A unified form data class
|
|
24
27
|
* which builds upon our configuration.
|
|
@@ -49,15 +52,15 @@ export class XhrFormData extends Config {
|
|
|
49
52
|
* @param executes the executes id list for the elements to being processed
|
|
50
53
|
* @param partialIds partial ids to collect, to reduce the data sent down
|
|
51
54
|
*/
|
|
52
|
-
constructor(private dataSource: DQ | string, viewState?: string, executes?: string[], private partialIds?: string[]) {
|
|
55
|
+
constructor(private dataSource: DQ | string, private paramsMapper: ParamsMapper<string, any> = defaultParamsMapper, viewState?: string, executes?: string[], private partialIds?: string[]) {
|
|
53
56
|
super({});
|
|
54
57
|
//a call to getViewState before must pass the encoded line
|
|
55
58
|
//a call from getViewState passes the form element as datasource,
|
|
56
59
|
//so we have two call points
|
|
57
60
|
// atm we basically encode twice, to keep the code leaner
|
|
58
|
-
// this will be later
|
|
59
|
-
// which are already covered by an external
|
|
60
|
-
// the encoding a second time, because they are overwritten by the
|
|
61
|
+
// this will be later optimized, practically elements
|
|
62
|
+
// which are already covered by an external ViewState do not need
|
|
63
|
+
// the encoding a second time, because they are overwritten by the ViewState again
|
|
61
64
|
if (isString(dataSource)) {
|
|
62
65
|
this.assignEncodedString(<string>this.dataSource);
|
|
63
66
|
} else {
|
|
@@ -109,10 +112,11 @@ export class XhrFormData extends Config {
|
|
|
109
112
|
* @param form the form holding the view state value
|
|
110
113
|
*/
|
|
111
114
|
private applyViewState(form: DQ) {
|
|
112
|
-
let viewStateElement = form.querySelectorAllDeep(`[name*='${P_VIEWSTATE}'`);
|
|
115
|
+
let viewStateElement = form.querySelectorAllDeep(`[name*='${$nsp(P_VIEWSTATE)}'`);
|
|
113
116
|
let viewState = viewStateElement.inputValue;
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
|
|
118
|
+
let viewStateName = viewStateElement.name.value;
|
|
119
|
+
this.assignIf(viewState.isPresent(), viewStateName).value = [viewState.value];
|
|
116
120
|
}
|
|
117
121
|
|
|
118
122
|
/**
|
|
@@ -120,7 +124,7 @@ export class XhrFormData extends Config {
|
|
|
120
124
|
* as key value entry
|
|
121
125
|
* @param encoded
|
|
122
126
|
*/
|
|
123
|
-
assignEncodedString(encoded: string) {
|
|
127
|
+
assignEncodedString(encoded: string, overwrite = true) {
|
|
124
128
|
// this code filters out empty strings as key value pairs
|
|
125
129
|
let keyValueEntries = decodeURIComponent(encoded).split(/&/gi)
|
|
126
130
|
.filter(item => !!(item || '')
|
|
@@ -132,7 +136,7 @@ export class XhrFormData extends Config {
|
|
|
132
136
|
* assign a set of key value pairs passed as array ['key=val1', 'key2=val2']
|
|
133
137
|
* @param keyValueEntries
|
|
134
138
|
*/
|
|
135
|
-
assignString(keyValueEntries: string[]) {
|
|
139
|
+
assignString(keyValueEntries: string[], overwrite = true) {
|
|
136
140
|
let toMerge = new ExtConfig({});
|
|
137
141
|
|
|
138
142
|
function splitToKeyVal(line: string) {
|
|
@@ -143,19 +147,20 @@ export class XhrFormData extends Config {
|
|
|
143
147
|
return keyVal.length < 3 ? [keyVal?.[0] ?? [], keyVal?.[1] ?? []] : keyVal;
|
|
144
148
|
}
|
|
145
149
|
|
|
146
|
-
//TODO fix files...
|
|
147
150
|
Stream.of(...keyValueEntries)
|
|
148
151
|
.map(line => splitToKeyVal(line))
|
|
149
152
|
//special case of having keys without values
|
|
150
153
|
.map(keyVal => fixKeyWithoutVal(keyVal))
|
|
154
|
+
.map(keyVal => this.paramsMapper(keyVal[0] as string, keyVal[1]))
|
|
151
155
|
.each(keyVal => {
|
|
152
156
|
toMerge.append(keyVal[0] as string).value = keyVal?.splice(1)?.join("") ?? "";
|
|
153
157
|
});
|
|
154
158
|
//merge with overwrite but no append! (aka no double entries are allowed)
|
|
155
|
-
this.shallowMerge(toMerge);
|
|
159
|
+
this.shallowMerge(toMerge, overwrite);
|
|
156
160
|
}
|
|
157
161
|
|
|
158
162
|
/**
|
|
163
|
+
* @param paramsMapper ... pre encode the params if needed, default is to map them 1:1
|
|
159
164
|
* @returns a Form data representation, this is needed for file submits
|
|
160
165
|
*/
|
|
161
166
|
toFormData(): FormData {
|
|
@@ -175,17 +180,18 @@ export class XhrFormData extends Config {
|
|
|
175
180
|
*
|
|
176
181
|
* @param defaultStr optional default value if nothing is there to encode
|
|
177
182
|
*/
|
|
178
|
-
toString(defaultStr = EMPTY_STR): string {
|
|
183
|
+
toString( defaultStr = EMPTY_STR): string {
|
|
179
184
|
if (this.isAbsent()) {
|
|
180
185
|
return defaultStr;
|
|
181
186
|
}
|
|
182
187
|
let entries = LazyStream.of(...Object.keys(this.value))
|
|
183
188
|
.filter(key => this.value.hasOwnProperty(key))
|
|
184
|
-
.flatMap(key => Stream.of(...this.value[key])
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
+
.flatMap(key => Stream.of(...this.value[key])
|
|
190
|
+
.map(val => {
|
|
191
|
+
return this.paramsMapper(key, val)
|
|
192
|
+
}))
|
|
193
|
+
//we cannot encode file elements that is handled by multipart requests anyway
|
|
194
|
+
.filter(([, value]) => !(value instanceof ExtDomQuery.global().File))
|
|
189
195
|
.map(keyVal => {
|
|
190
196
|
return `${encodeURIComponent(keyVal[0])}=${encodeURIComponent(keyVal[1])}`;
|
|
191
197
|
})
|
|
@@ -222,8 +228,7 @@ export class XhrFormData extends Config {
|
|
|
222
228
|
*
|
|
223
229
|
*/
|
|
224
230
|
this.encodeSubmittableFields(this, <DQ>this.dataSource, this.partialIds);
|
|
225
|
-
|
|
226
|
-
if (this.getIf(P_VIEWSTATE).isPresent()) {
|
|
231
|
+
if (this.getIf($nsp(P_VIEWSTATE)).isPresent()) {
|
|
227
232
|
return;
|
|
228
233
|
}
|
|
229
234
|
|
|
@@ -251,13 +256,27 @@ export class XhrFormData extends Config {
|
|
|
251
256
|
}
|
|
252
257
|
|
|
253
258
|
//lets encode the form elements
|
|
254
|
-
|
|
259
|
+
let formElements = toEncode.deepElements.encodeFormElement();
|
|
260
|
+
const mapped = this.remapKeysForNamingContainer(formElements);
|
|
261
|
+
this.shallowMerge(mapped);
|
|
255
262
|
}
|
|
256
263
|
|
|
257
|
-
private
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
264
|
+
private remapKeysForNamingContainer(formElements: Config): Config {
|
|
265
|
+
let ret = new Config({});
|
|
266
|
+
formElements.stream
|
|
267
|
+
.map(([key, item]) => this.paramsMapper(key, item))
|
|
268
|
+
.each( ([key, item]) => {
|
|
269
|
+
ret.assign(key).value = item;
|
|
261
270
|
});
|
|
271
|
+
return ret;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
private appendInputs(ret: any) {
|
|
275
|
+
Stream.ofAssoc(this.value)
|
|
276
|
+
.flatMap(([key, item]) =>
|
|
277
|
+
Stream.of(...(item as Array<any>)).map(item => {
|
|
278
|
+
return {key, item};
|
|
279
|
+
}))
|
|
280
|
+
.each(({key, item}) => ret.append(key, item))
|
|
262
281
|
}
|
|
263
282
|
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import {AsyncRunnable} from "../util/AsyncRunnable";
|
|
18
|
-
import {Config, DQ, Stream} from "mona-dish";
|
|
18
|
+
import {Config, DQ, DQ$, Stream} from "mona-dish";
|
|
19
19
|
import {Implementation} from "../AjaxImpl";
|
|
20
20
|
|
|
21
21
|
import {XhrFormData} from "./XhrFormData";
|
|
@@ -23,7 +23,7 @@ import {ErrorData} from "./ErrorData";
|
|
|
23
23
|
import {EventData} from "./EventData";
|
|
24
24
|
import {ExtLang} from "../util/Lang";
|
|
25
25
|
import {
|
|
26
|
-
$faces,
|
|
26
|
+
$faces, $nsp,
|
|
27
27
|
BEGIN,
|
|
28
28
|
COMPLETE,
|
|
29
29
|
CONTENT_TYPE,
|
|
@@ -31,10 +31,10 @@ import {
|
|
|
31
31
|
CTX_PARAM_REQ_PASS_THR,
|
|
32
32
|
ERROR,
|
|
33
33
|
HEAD_FACES_REQ,
|
|
34
|
-
MALFORMEDXML,
|
|
34
|
+
MALFORMEDXML, NAMED_VIEWROOT,
|
|
35
35
|
NO_TIMEOUT,
|
|
36
36
|
ON_ERROR,
|
|
37
|
-
ON_EVENT, P_EXECUTE, P_PARTIAL_SOURCE,
|
|
37
|
+
ON_EVENT, P_EXECUTE, P_PARTIAL_SOURCE, P_VIEWSTATE, NAMING_CONTAINER_ID,
|
|
38
38
|
REQ_ACCEPT,
|
|
39
39
|
REQ_TYPE_GET,
|
|
40
40
|
REQ_TYPE_POST, SOURCE,
|
|
@@ -43,9 +43,15 @@ import {
|
|
|
43
43
|
URL_ENCODED,
|
|
44
44
|
VAL_AJAX
|
|
45
45
|
} from "../core/Const";
|
|
46
|
-
import {
|
|
46
|
+
import {
|
|
47
|
+
resolveFinalUrl,
|
|
48
|
+
resolveHandlerFunc,
|
|
49
|
+
resolveViewRootId, resoveConfigNamingContainerMapper,
|
|
50
|
+
resoveNamingContainerMapper
|
|
51
|
+
} from "./RequestDataResolver";
|
|
47
52
|
import failSaveExecute = ExtLang.failSaveExecute;
|
|
48
53
|
import {ExtConfig} from "../util/ExtDomQuery";
|
|
54
|
+
import {ResponseProcessor} from "./ResponseProcessor";
|
|
49
55
|
|
|
50
56
|
/**
|
|
51
57
|
* Faces XHR Request Wrapper
|
|
@@ -115,10 +121,14 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
|
|
|
115
121
|
let executesArr = () => {
|
|
116
122
|
return this.requestContext.getIf(CTX_PARAM_REQ_PASS_THR, P_EXECUTE).get("none").value.split(/\s+/gi);
|
|
117
123
|
};
|
|
118
|
-
try {
|
|
119
124
|
|
|
125
|
+
try {
|
|
120
126
|
let formElement = this.sourceForm.getAsElem(0).value;
|
|
127
|
+
|
|
128
|
+
// by spec the viewstate must be called to provide
|
|
129
|
+
// decorated encoding capabilities
|
|
121
130
|
let viewState = $faces().getViewState(formElement);
|
|
131
|
+
|
|
122
132
|
// encoded we need to decode
|
|
123
133
|
// We generated a base representation of the current form
|
|
124
134
|
// in case someone has overloaded the viewState with additional decorators we merge
|
|
@@ -127,8 +137,12 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
|
|
|
127
137
|
// whatever the formData object delivers
|
|
128
138
|
// the partialIdsArray arr is almost deprecated legacy code where we allowed to send a separate list of partial
|
|
129
139
|
// ids for reduced load and server processing, this will be removed soon, we can handle the same via execute
|
|
130
|
-
// anyway
|
|
131
|
-
|
|
140
|
+
// anyway
|
|
141
|
+
|
|
142
|
+
// per spec every parameter sent into the request must be naming container
|
|
143
|
+
// prefixed
|
|
144
|
+
const namingContainerMapper = resoveNamingContainerMapper(this.internalContext);
|
|
145
|
+
let formData: XhrFormData = new XhrFormData(this.sourceForm, namingContainerMapper, viewState, executesArr(), this.partialIdsArray);
|
|
132
146
|
|
|
133
147
|
this.contentType = formData.isMultipartRequest ? "undefined" : this.contentType;
|
|
134
148
|
|
|
@@ -142,6 +156,10 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
|
|
|
142
156
|
// information
|
|
143
157
|
|
|
144
158
|
try {
|
|
159
|
+
// per spec every param sent down needs to be remapped
|
|
160
|
+
// and prefixed by the naming container id
|
|
161
|
+
let configNamingContainerMapper = resoveConfigNamingContainerMapper(this.internalContext);
|
|
162
|
+
// requestPassThroughParams = configNamingContainerMapper(requestPassThroughParams);
|
|
145
163
|
formData.shallowMerge(requestPassThroughParams, true, true);
|
|
146
164
|
} finally {
|
|
147
165
|
this.requestContext.$nspEnabled = true;
|
|
@@ -178,8 +196,9 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
|
|
|
178
196
|
// setting, they accept headers automatically
|
|
179
197
|
ignoreErr(() => xhrObject.setRequestHeader(REQ_ACCEPT, STD_ACCEPT));
|
|
180
198
|
|
|
181
|
-
this.sendEvent(BEGIN);
|
|
182
199
|
|
|
200
|
+
|
|
201
|
+
this.sendEvent(BEGIN);
|
|
183
202
|
this.sendRequest(formData);
|
|
184
203
|
|
|
185
204
|
} catch (e) {
|
|
@@ -374,4 +393,5 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
|
|
|
374
393
|
Implementation.sendError(errorData, eventHandler);
|
|
375
394
|
}
|
|
376
395
|
|
|
396
|
+
|
|
377
397
|
}
|
|
@@ -174,11 +174,11 @@ describe('Namespacing tests', function () {
|
|
|
174
174
|
let resultsMap = {};
|
|
175
175
|
for (let val of arsArr) {
|
|
176
176
|
let keyVal = val.split("=");
|
|
177
|
-
resultsMap[keyVal[0]] = keyVal[1];
|
|
177
|
+
resultsMap[unescape(keyVal[0])] = unescape(keyVal[1]);
|
|
178
178
|
}
|
|
179
|
-
|
|
180
|
-
expect(resultsMap["pass1"]).to.eq("pass1");
|
|
181
|
-
expect(resultsMap["pass2"]).to.eq("pass2");
|
|
179
|
+
const NAMING_CONTAINER_PREF = "jd_0:";
|
|
180
|
+
expect(resultsMap[NAMING_CONTAINER_PREF + "pass1"]).to.eq("pass1");
|
|
181
|
+
expect(resultsMap[NAMING_CONTAINER_PREF + "pass2"]).to.eq("pass2");
|
|
182
182
|
expect(!!resultsMap["render"]).to.be.false;
|
|
183
183
|
expect(!!resultsMap["execute"]).to.be.false;
|
|
184
184
|
|
|
@@ -191,10 +191,10 @@ describe('Namespacing tests', function () {
|
|
|
191
191
|
let viewState = Stream.ofAssoc(resultsMap).filter(data => data[0].indexOf(P_VIEWSTATE) != -1).map(item => item[1]).first().value;
|
|
192
192
|
|
|
193
193
|
expect(viewState).to.eq("booga");
|
|
194
|
-
expect(resultsMap[P_PARTIAL_SOURCE]).to.eq(
|
|
195
|
-
expect(resultsMap[P_AJAX]).to.eq("true");
|
|
196
|
-
expect(resultsMap[P_RENDER]).to.eq(
|
|
197
|
-
expect(resultsMap[P_EXECUTE]).to.eq(
|
|
194
|
+
expect(resultsMap[NAMING_CONTAINER_PREF + P_PARTIAL_SOURCE]).to.eq("jd_0:input_2");
|
|
195
|
+
expect(resultsMap[NAMING_CONTAINER_PREF + P_AJAX]).to.eq("true");
|
|
196
|
+
expect(resultsMap[NAMING_CONTAINER_PREF + P_RENDER]).to.eq("jd_0:blarg jd_0:input_2");
|
|
197
|
+
expect(resultsMap[NAMING_CONTAINER_PREF + P_EXECUTE]).to.eq("jd_0:input_1 jd_0:input_2");
|
|
198
198
|
} finally {
|
|
199
199
|
send.restore();
|
|
200
200
|
}
|
|
@@ -225,7 +225,7 @@ describe('Tests of the various aspects of the response protocol functionality',
|
|
|
225
225
|
|
|
226
226
|
});
|
|
227
227
|
|
|
228
|
-
it("must have updated the viewstates properly", function () {
|
|
228
|
+
it("must have updated the viewstates properly", function (done) {
|
|
229
229
|
DQ.byId("cmd_eval").click();
|
|
230
230
|
/*js full submit form, coming from the integration tests*/
|
|
231
231
|
window.document.body.innerHTML = `<form id="j_id__v_0" name="j_id__v_0" method="post" action="/IntegrationJSTest/integrationtestsjasmine/test7-eventtest.jsf"
|
|
@@ -252,10 +252,11 @@ describe('Tests of the various aspects of the response protocol functionality',
|
|
|
252
252
|
</changes>
|
|
253
253
|
</partial-response>`);
|
|
254
254
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
255
|
+
setTimeout(() => {
|
|
256
|
+
expect(DQ$("[name*='jakarta.faces.ViewState']").isPresent()).to.be.true;
|
|
257
|
+
expect(DQ$("[name*='jakarta.faces.ViewState']").val == "RTUyRDI0NzE4QzAxM0E5RDAwMDAwMDVD").to.be.true;
|
|
258
|
+
done();
|
|
259
|
+
}, 100);
|
|
259
260
|
});
|
|
260
261
|
|
|
261
262
|
|
|
@@ -228,7 +228,7 @@ describe('Tests of the various aspects of the response protocol functionality',
|
|
|
228
228
|
|
|
229
229
|
});
|
|
230
230
|
|
|
231
|
-
it("must have updated the viewstates properly", function () {
|
|
231
|
+
it("must have updated the viewstates properly 2.3", function () {
|
|
232
232
|
DQ.byId("cmd_eval").click();
|
|
233
233
|
/*js full submit form, coming from the integration tests*/
|
|
234
234
|
window.document.body.innerHTML = `<form id="j_id__v_0" name="j_id__v_0" method="post" action="/IntegrationJSTest/integrationtestsjasmine/test7-eventtest.jsf"
|
|
@@ -263,7 +263,7 @@ describe('Tests of the various aspects of the response protocol functionality',
|
|
|
263
263
|
});
|
|
264
264
|
|
|
265
265
|
|
|
266
|
-
it("must have updated the viewstates properly with lenient update block", function () {
|
|
266
|
+
it("must have updated the viewstates properly with lenient update block 2.3", function () {
|
|
267
267
|
DQ.byId("cmd_eval").click();
|
|
268
268
|
/*js full submit form, coming from the integration tests*/
|
|
269
269
|
window.document.body.innerHTML = `<form id="j_id__v_0" name="j_id__v_0" method="post" action="/IntegrationJSTest/integrationtestsjasmine/test7-eventtest.jsf"
|
package/target/impl/AjaxImpl.js
CHANGED
|
@@ -279,6 +279,7 @@ var Implementation;
|
|
|
279
279
|
assignClientWindowId(form, requestCtx);
|
|
280
280
|
assignExecute(options, requestCtx, form, elementId);
|
|
281
281
|
assignRender(options, requestCtx, form, elementId);
|
|
282
|
+
assignNamingContainerData(internalCtx, form);
|
|
282
283
|
//now we enqueue the request as asynchronous runnable into our request
|
|
283
284
|
//queue and let the queue take over the rest
|
|
284
285
|
Implementation.queueHandler.addRequestToQueue(elem, form, requestCtx, internalCtx, delay, timeout);
|
|
@@ -451,7 +452,9 @@ var Implementation;
|
|
|
451
452
|
if (!element.isTag(Const_1.HTML_TAG_FORM)) {
|
|
452
453
|
throw new Error(getMessage("ERR_VIEWSTATE"));
|
|
453
454
|
}
|
|
454
|
-
|
|
455
|
+
const dummyContext = new mona_dish_1.Config({});
|
|
456
|
+
assignNamingContainerData(dummyContext, mona_dish_1.DQ.byId(form));
|
|
457
|
+
let formData = new XhrFormData_1.XhrFormData(element, (0, RequestDataResolver_1.resoveNamingContainerMapper)(dummyContext));
|
|
455
458
|
return formData.toString();
|
|
456
459
|
}
|
|
457
460
|
Implementation.getViewState = getViewState;
|
|
@@ -526,6 +529,21 @@ var Implementation;
|
|
|
526
529
|
targetContext.assign(Const_1.CTX_PARAM_REQ_PASS_THR, Const_1.P_CLIENT_WINDOW).value = clientWindow;
|
|
527
530
|
}
|
|
528
531
|
}
|
|
532
|
+
/**
|
|
533
|
+
* determines the current naming container
|
|
534
|
+
* and assigns it internally
|
|
535
|
+
*
|
|
536
|
+
* @param internalContext
|
|
537
|
+
* @param formElement
|
|
538
|
+
* @private
|
|
539
|
+
*/
|
|
540
|
+
function assignNamingContainerData(internalContext, formElement) {
|
|
541
|
+
const viewRootId = (0, RequestDataResolver_1.resolveViewRootId)(formElement);
|
|
542
|
+
if (!!viewRootId) {
|
|
543
|
+
internalContext.assign(Const_1.NAMED_VIEWROOT).value = true;
|
|
544
|
+
internalContext.assign(Const_1.NAMING_CONTAINER_ID).value = viewRootId;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
529
547
|
/**
|
|
530
548
|
* transforms the user values to the expected one
|
|
531
549
|
* with the proper none all form and this handling
|