jsf.js_next_gen 4.0.0-RC.22 → 4.0.0-RC.25

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.
Files changed (54) hide show
  1. package/dist/window/faces-development.js +117 -33
  2. package/dist/window/faces-development.js.br +0 -0
  3. package/dist/window/faces-development.js.gz +0 -0
  4. package/dist/window/faces-development.js.map +1 -1
  5. package/dist/window/faces.js +1 -1
  6. package/dist/window/faces.js.br +0 -0
  7. package/dist/window/faces.js.gz +0 -0
  8. package/dist/window/faces.js.map +1 -1
  9. package/dist/window/jsf-development.js +117 -33
  10. package/dist/window/jsf-development.js.br +0 -0
  11. package/dist/window/jsf-development.js.gz +0 -0
  12. package/dist/window/jsf-development.js.map +1 -1
  13. package/dist/window/jsf.js +1 -1
  14. package/dist/window/jsf.js.br +0 -0
  15. package/dist/window/jsf.js.gz +0 -0
  16. package/dist/window/jsf.js.map +1 -1
  17. package/package.json +2 -2
  18. package/src/main/typescript/impl/AjaxImpl.ts +31 -3
  19. package/src/main/typescript/impl/core/Const.ts +1 -1
  20. package/src/main/typescript/impl/xhrCore/IResponseProcessor.ts +7 -0
  21. package/src/main/typescript/impl/xhrCore/RequestDataResolver.ts +28 -1
  22. package/src/main/typescript/impl/xhrCore/Response.ts +31 -26
  23. package/src/main/typescript/impl/xhrCore/ResponseProcessor.ts +16 -4
  24. package/src/main/typescript/impl/xhrCore/XhrFormData.ts +40 -18
  25. package/src/main/typescript/impl/xhrCore/XhrRequest.ts +17 -8
  26. package/src/main/typescript/test/xhrCore/FileUploadTest.spec.ts +2 -0
  27. package/src/main/typescript/test/xhrCore/NamespacesRequestTest.spec.ts +8 -8
  28. package/src/main/typescript/test/xhrCore/ResponseTest.spec.ts +6 -5
  29. package/src/main/typescript/test/xhrCore/ResponseTest23.spec.ts +2 -2
  30. package/src/main/typescript/test/xhrCore/XhrFormDataTest.spec.ts +1 -0
  31. package/target/impl/AjaxImpl.js +19 -1
  32. package/target/impl/AjaxImpl.js.map +1 -1
  33. package/target/impl/core/Const.js +2 -2
  34. package/target/impl/core/Const.js.map +1 -1
  35. package/target/impl/xhrCore/RequestDataResolver.js +28 -1
  36. package/target/impl/xhrCore/RequestDataResolver.js.map +1 -1
  37. package/target/impl/xhrCore/Response.js +16 -13
  38. package/target/impl/xhrCore/Response.js.map +1 -1
  39. package/target/impl/xhrCore/ResponseProcessor.js +14 -3
  40. package/target/impl/xhrCore/ResponseProcessor.js.map +1 -1
  41. package/target/impl/xhrCore/XhrFormData.js +31 -12
  42. package/target/impl/xhrCore/XhrFormData.js.map +1 -1
  43. package/target/impl/xhrCore/XhrRequest.js +1 -1
  44. package/target/impl/xhrCore/XhrRequest.js.map +1 -1
  45. package/target/test/xhrCore/FileUploadTest.spec.js +1 -0
  46. package/target/test/xhrCore/FileUploadTest.spec.js.map +1 -1
  47. package/target/test/xhrCore/NamespacesRequestTest.spec.js +8 -7
  48. package/target/test/xhrCore/NamespacesRequestTest.spec.js.map +1 -1
  49. package/target/test/xhrCore/ResponseTest.spec.js +6 -3
  50. package/target/test/xhrCore/ResponseTest.spec.js.map +1 -1
  51. package/target/test/xhrCore/ResponseTest23.spec.js +2 -2
  52. package/target/test/xhrCore/ResponseTest23.spec.js.map +1 -1
  53. package/target/test/xhrCore/XhrFormDataTest.spec.js +1 -0
  54. 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.22",
3
+ "version": "4.0.0-RC.25",
4
4
  "description": "A next generation typescript reimplementation of jsf.js",
5
5
  "main": "dist/window/faces.js",
6
6
  "scripts": {
@@ -48,6 +48,6 @@
48
48
  "webpack-dev-server": "^4.11.1"
49
49
  },
50
50
  "dependencies": {
51
- "mona-dish": "^0.24.3"
51
+ "mona-dish": "^0.24.4"
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, CTX_OPTIONS_PARAMS, VIEW_ID, $faces, EMPTY_STR
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
- let formData = new XhrFormData(element);
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 PARTIAL_ID = "partialId";
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";
@@ -149,4 +149,11 @@ export interface IResponseProcessor {
149
149
  * send last event
150
150
  */
151
151
  done(): void;
152
+
153
+ /**
154
+ * update internal state to
155
+ * check whether we still are in a named view root
156
+ * (can change after a navigation)
157
+ */
158
+ updateNamedViewRootState();
152
159
  }
@@ -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,32 @@ 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
+
92
119
  export function resolveTimeout(options: Config): number {
93
120
  let getCfg = ExtLang.getLocalOrGlobalConfig;
94
121
  return options.getIf(CTX_OPTIONS_TIMEOUT).value ?? getCfg(options.value, CTX_OPTIONS_TIMEOUT, 0);
@@ -32,11 +32,11 @@ import {
32
32
  P_VIEWBODY,
33
33
  P_VIEWHEAD,
34
34
  P_VIEWROOT,
35
- PARTIAL_ID,
35
+ NAMING_CONTAINER_ID,
36
36
  XML_TAG_PARTIAL_RESP,
37
37
  RESPONSE_XML,
38
38
  XML_TAG_AFTER,
39
- XML_TAG_BEFORE, NAMED_VIEWROOT, XML_ATTR_NAMED_VIEWROOT
39
+ XML_TAG_BEFORE, NAMED_VIEWROOT, XML_ATTR_NAMED_VIEWROOT, P_VIEWSTATE, $faces
40
40
  } from "../core/Const";
41
41
  import {resolveContexts, resolveResponseXML} from "./ResonseDataResolver";
42
42
  import {ExtConfig} from "../util/ExtDomQuery";
@@ -76,6 +76,7 @@ export module Response {
76
76
  // doing any evaluations even on embedded scripts.
77
77
  // Usually this does not matter, the client window comes in almost last always anyway
78
78
  // we maybe drop this deferred assignment in the future, but myfaces did it until now.
79
+ responseProcessor.updateNamedViewRootState();
79
80
  responseProcessor.fixViewStates();
80
81
  responseProcessor.fixClientWindow();
81
82
  responseProcessor.globalEval();
@@ -86,21 +87,25 @@ export module Response {
86
87
  /**
87
88
  * highest node partial-response from there the main operations are triggered
88
89
  */
89
- function processPartialTag(node: XMLQuery, responseProcessor: IResponseProcessor, internalContext) {
90
-
91
- let namedAttr = node.attr(XML_ATTR_NAMED_VIEWROOT);
92
- // MyFaces.
93
- // there are two differences here on how we determine the naming container scenario
94
- // mojarra only partial reponse identifier, and if there is none we do not have any naming container
95
- // myfaces either uses the reponse identifier
96
- let namedViewRoot = namedAttr.isPresent() ? namedAttr.value === "true" : false;
97
- if(!namedAttr.isPresent() && node.id) { // defauts fallback if namedViewRoot is not set, if node id is set
98
- // it defaults to a naming container
99
- namedViewRoot = !(document?.head?.id);
100
- }
90
+ function processPartialTag(node: XMLQuery, responseProcessor: IResponseProcessor, internalContext) {
91
+
92
+
93
+ /*
94
+ https://javaee.github.io/javaserverfaces/docs/2.2/javadocs/web-partialresponse.html#ns_xsd
95
+ The "partial-response" element is the root of the partial response information hierarchy,
96
+ and contains nested elements for all possible elements that can exist in the response.
97
+ This element must have an "id" attribute whose value is the return from calling getContainerClientId()
98
+ on the UIViewRoot to which this response pertains.
99
+ */
100
+ // we can determine whether we are in a naming container scenario by checking whether the passed view id is present in the page
101
+ // under or in body as identifier
101
102
 
102
- internalContext.assignIf(node?.id ?? document?.head.id, PARTIAL_ID).value = node?.id ?? document?.head.id; // second case mojarra
103
- internalContext.assign(NAMED_VIEWROOT).value = namedViewRoot;
103
+ let partialId:string = node?.id?.value;
104
+ internalContext.assignIf(!!partialId, NAMING_CONTAINER_ID).value = partialId; // second case mojarra
105
+
106
+ // there must be at least one container viewstate element resembling the viewroot that we know
107
+ // this is named
108
+ responseProcessor.updateNamedViewRootState();
104
109
 
105
110
  const SEL_SUB_TAGS = [XML_TAG_ERROR, XML_TAG_REDIRECT, XML_TAG_CHANGES].join(",");
106
111
 
@@ -122,12 +127,12 @@ export module Response {
122
127
  }
123
128
 
124
129
  let processInsert = function (responseProcessor: IResponseProcessor, node: XMLQuery) {
125
- // path1 insert after as child tags
126
- if(node.querySelectorAll([XML_TAG_BEFORE, XML_TAG_AFTER].join(",")).length) {
127
- responseProcessor.insertWithSubTags(node);
128
- } else { // insert before after with id
129
- responseProcessor.insert(node);
130
- }
130
+ // path1 insert after as child tags
131
+ if(node.querySelectorAll([XML_TAG_BEFORE, XML_TAG_AFTER].join(",")).length) {
132
+ responseProcessor.insertWithSubTags(node);
133
+ } else { // insert before after with id
134
+ responseProcessor.insert(node);
135
+ }
131
136
 
132
137
  };
133
138
 
@@ -137,7 +142,7 @@ export module Response {
137
142
  * @param node
138
143
  * @param responseProcessor
139
144
  */
140
- function processChangesTag(node: XMLQuery, responseProcessor: IResponseProcessor): boolean {
145
+ function processChangesTag(node: XMLQuery, responseProcessor: IResponseProcessor): boolean {
141
146
  const ALLOWED_TAGS = [XML_TAG_UPDATE, XML_TAG_EVAL, XML_TAG_INSERT, XML_TAG_DELETE, XML_TAG_ATTRIBUTES, XML_TAG_EXTENSION].join(", ");
142
147
  node.querySelectorAll(ALLOWED_TAGS).each(
143
148
  (node: XMLQuery) => {
@@ -190,8 +195,8 @@ export module Response {
190
195
  * @param node
191
196
  * @param responseProcessor
192
197
  */
193
- function processUpdateTag(node: XMLQuery, responseProcessor: IResponseProcessor) {
194
- // early state storing, if no state we perform a normal update cycle
198
+ function processUpdateTag(node: XMLQuery, responseProcessor: IResponseProcessor) {
199
+ // early state storing, if no state we perform a normal update cycle
195
200
  if (!storeState(responseProcessor, node)) {
196
201
  handleElementUpdate(node, responseProcessor);
197
202
  }
@@ -203,7 +208,7 @@ export module Response {
203
208
  * @param node
204
209
  * @param responseProcessor
205
210
  */
206
- function handleElementUpdate(node: XMLQuery, responseProcessor: IResponseProcessor) {
211
+ function handleElementUpdate(node: XMLQuery, responseProcessor: IResponseProcessor) {
207
212
  let cdataBlock = node.cDATAAsString;
208
213
  switch (node.id.value) {
209
214
  case $nsp(P_VIEWROOT) :
@@ -50,7 +50,7 @@ import {
50
50
  P_RENDER,
51
51
  P_RENDER_OVERRIDE,
52
52
  P_VIEWSTATE,
53
- PARTIAL_ID,
53
+ NAMING_CONTAINER_ID,
54
54
  RESPONSE_XML,
55
55
  SEL_CLIENT_WINDOW_ELEM,
56
56
  SEL_VIEWSTATE_ELEM,
@@ -348,8 +348,8 @@ 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(PARTIAL_ID);
352
- const namedViewRoot = !!this.internalContext.getIf(PARTIAL_ID).value
351
+ const namingContainerId = this.internalContext.getIf(NAMING_CONTAINER_ID);
352
+ const namedViewRoot = !!this.internalContext.getIf(NAMED_VIEWROOT).value
353
353
  const affectedForms = this.getContainerForms(namingContainerId)
354
354
  .filter(affectedForm => this.isInExecuteOrRender(affectedForm));
355
355
 
@@ -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(PARTIAL_ID);
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));
@@ -375,6 +375,18 @@ export class ResponseProcessor implements IResponseProcessor {
375
375
  });
376
376
  }
377
377
 
378
+ updateNamedViewRootState() {
379
+ let partialId = this.internalContext.getIf(NAMING_CONTAINER_ID);
380
+ let namedViewRoot = this.internalContext.getIf(NAMED_VIEWROOT);
381
+ if(partialId.isPresent() &&
382
+ (namedViewRoot.isAbsent() ||
383
+ !namedViewRoot.value)) {
384
+ const SEP = $faces().separatorchar;
385
+ this.internalContext.assign(NAMED_VIEWROOT).value = (!!document.getElementById(partialId.value)) || DQ$(`input[name*='${$nsp(P_VIEWSTATE)}']`)
386
+ .filter(node => node.attr("name").value.indexOf(partialId.value + SEP) == 0).length > 0;
387
+ }
388
+ }
389
+
378
390
  /**
379
391
  * all processing done we can close the request and send the appropriate events
380
392
  */
@@ -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,7 +52,7 @@ 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,
@@ -109,10 +112,10 @@ 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
117
  // this.appendIf(viewState.isPresent(), P_VIEWSTATE).value = viewState.value;
115
- this.appendIf(viewState.isPresent(), viewStateElement.name.value).value = viewState.value;
118
+ this.appendIf(viewState.isPresent(), this.remapKeyForNamingContainer(viewStateElement.name.value)).value = viewState.value;
116
119
  }
117
120
 
118
121
  /**
@@ -143,11 +146,11 @@ export class XhrFormData extends Config {
143
146
  return keyVal.length < 3 ? [keyVal?.[0] ?? [], keyVal?.[1] ?? []] : keyVal;
144
147
  }
145
148
 
146
- //TODO fix files...
147
149
  Stream.of(...keyValueEntries)
148
150
  .map(line => splitToKeyVal(line))
149
151
  //special case of having keys without values
150
152
  .map(keyVal => fixKeyWithoutVal(keyVal))
153
+ .map(keyVal => this.paramsMapper(keyVal[0] as string, keyVal[1]))
151
154
  .each(keyVal => {
152
155
  toMerge.append(keyVal[0] as string).value = keyVal?.splice(1)?.join("") ?? "";
153
156
  });
@@ -156,6 +159,7 @@ export class XhrFormData extends Config {
156
159
  }
157
160
 
158
161
  /**
162
+ * @param paramsMapper ... pre encode the params if needed, default is to map them 1:1
159
163
  * @returns a Form data representation, this is needed for file submits
160
164
  */
161
165
  toFormData(): FormData {
@@ -175,17 +179,18 @@ export class XhrFormData extends Config {
175
179
  *
176
180
  * @param defaultStr optional default value if nothing is there to encode
177
181
  */
178
- toString(defaultStr = EMPTY_STR): string {
182
+ toString( defaultStr = EMPTY_STR): string {
179
183
  if (this.isAbsent()) {
180
184
  return defaultStr;
181
185
  }
182
186
  let entries = LazyStream.of(...Object.keys(this.value))
183
187
  .filter(key => this.value.hasOwnProperty(key))
184
- .flatMap(key => Stream.of(...this.value[key]).map(val => [key, val])
185
- //we cannot encode file elements that is handled by multipart requests anyway
186
- .filter(([, value]) => !(value instanceof ExtDomQuery.global().File))
187
- .collect(new ArrayCollector()))
188
-
188
+ .flatMap(key => Stream.of(...this.value[key])
189
+ .map(val => {
190
+ return this.paramsMapper(key, val)
191
+ }))
192
+ //we cannot encode file elements that is handled by multipart requests anyway
193
+ .filter(([, value]) => !(value instanceof ExtDomQuery.global().File))
189
194
  .map(keyVal => {
190
195
  return `${encodeURIComponent(keyVal[0])}=${encodeURIComponent(keyVal[1])}`;
191
196
  })
@@ -222,8 +227,7 @@ export class XhrFormData extends Config {
222
227
  *
223
228
  */
224
229
  this.encodeSubmittableFields(this, <DQ>this.dataSource, this.partialIds);
225
-
226
- if (this.getIf(P_VIEWSTATE).isPresent()) {
230
+ if (this.getIf($nsp(P_VIEWSTATE)).isPresent()) {
227
231
  return;
228
232
  }
229
233
 
@@ -251,13 +255,31 @@ export class XhrFormData extends Config {
251
255
  }
252
256
 
253
257
  //lets encode the form elements
254
- this.shallowMerge(toEncode.deepElements.encodeFormElement());
258
+ let formElements = toEncode.deepElements.encodeFormElement();
259
+ const mapped = this.remapKeysForNamingCoontainer(formElements);
260
+ this.shallowMerge(mapped);
261
+ }
262
+
263
+ private remapKeysForNamingCoontainer(formElements: Config): Config {
264
+ let ret = new Config({});
265
+ formElements.stream.map(([key, item]) => this.paramsMapper(key, item))
266
+ .each( ([key, item]) => {
267
+ ret.assign(key).value = item;
268
+ });
269
+ return ret;
270
+
271
+ }
272
+
273
+ private remapKeyForNamingContainer(key: string): string {
274
+ return this.paramsMapper(key, "")[0];
255
275
  }
256
276
 
257
277
  private appendInputs(ret: any) {
258
- Stream.of(...Object.keys(this.value))
259
- .each(key => {
260
- Stream.of(...this.value[key]).each(item => ret.append(key, item));
261
- });
278
+ Stream.ofAssoc(this.value)
279
+ .flatMap(([key, item]) =>
280
+ Stream.of(...(item as Array<any>)).map(item => {
281
+ return {key, item};
282
+ }))
283
+ .each(({key, item}) => ret.append(key, item))
262
284
  }
263
285
  }
@@ -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 {resolveFinalUrl, resolveHandlerFunc} from "./RequestDataResolver";
46
+ import {
47
+ resolveFinalUrl,
48
+ resolveHandlerFunc,
49
+ resolveViewRootId,
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,11 @@ 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;
121
127
  let viewState = $faces().getViewState(formElement);
128
+
122
129
  // encoded we need to decode
123
130
  // We generated a base representation of the current form
124
131
  // in case someone has overloaded the viewState with additional decorators we merge
@@ -128,7 +135,7 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
128
135
  // the partialIdsArray arr is almost deprecated legacy code where we allowed to send a separate list of partial
129
136
  // ids for reduced load and server processing, this will be removed soon, we can handle the same via execute
130
137
  // anyway TODO remove the partial ids array
131
- let formData: XhrFormData = new XhrFormData(this.sourceForm, viewState, executesArr(), this.partialIdsArray);
138
+ let formData: XhrFormData = new XhrFormData(this.sourceForm, resoveNamingContainerMapper(this.internalContext), viewState, executesArr(), this.partialIdsArray);
132
139
 
133
140
  this.contentType = formData.isMultipartRequest ? "undefined" : this.contentType;
134
141
 
@@ -178,8 +185,9 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
178
185
  // setting, they accept headers automatically
179
186
  ignoreErr(() => xhrObject.setRequestHeader(REQ_ACCEPT, STD_ACCEPT));
180
187
 
181
- this.sendEvent(BEGIN);
182
188
 
189
+
190
+ this.sendEvent(BEGIN);
183
191
  this.sendRequest(formData);
184
192
 
185
193
  } catch (e) {
@@ -374,4 +382,5 @@ export class XhrRequest implements AsyncRunnable<XMLHttpRequest> {
374
382
  Implementation.sendError(errorData, eventHandler);
375
383
  }
376
384
 
385
+
377
386
  }
@@ -66,6 +66,8 @@ describe('Tests on the xhr core when it starts to call the request', function ()
66
66
  const CONTENT_TYPE = "Content-Type";
67
67
  const POST = "POST";
68
68
 
69
+ global["debug_f"] = true;
70
+
69
71
  try {
70
72
 
71
73
  let button = DomQuery.byId("input_1");
@@ -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(escape("jd_0:input_2"));
195
- expect(resultsMap[P_AJAX]).to.eq("true");
196
- expect(resultsMap[P_RENDER]).to.eq(escape("jd_0:blarg jd_0:input_2"));
197
- expect(resultsMap[P_EXECUTE]).to.eq(escape("jd_0:input_1 jd_0:input_2"));
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
- expect(DQ$("[name*='jakarta.faces.ViewState']").isPresent()).to.be.true;
257
-
258
- expect(DQ$("[name*='jakarta.faces.ViewState']").val == "RTUyRDI0NzE4QzAxM0E5RDAwMDAwMDVD").to.be.true;
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"
@@ -84,6 +84,7 @@ describe('XhrFormData tests', function () {
84
84
  </div>
85
85
  </form>`;
86
86
 
87
+ global.debugf2=true;
87
88
  const xhrFormData = new XhrFormData(DQ.byId("page::form"));
88
89
  const formData = xhrFormData.toString();
89
90