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.
Files changed (53) hide show
  1. package/dist/window/faces-development.js +130 -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 +130 -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 +4 -4
  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/RequestDataResolver.ts +49 -2
  21. package/src/main/typescript/impl/xhrCore/Response.ts +3 -2
  22. package/src/main/typescript/impl/xhrCore/ResponseProcessor.ts +4 -4
  23. package/src/main/typescript/impl/xhrCore/XhrFormData.ts +44 -25
  24. package/src/main/typescript/impl/xhrCore/XhrRequest.ts +29 -9
  25. package/src/main/typescript/test/xhrCore/FileUploadTest.spec.ts +2 -0
  26. package/src/main/typescript/test/xhrCore/NamespacesRequestTest.spec.ts +8 -8
  27. package/src/main/typescript/test/xhrCore/ResponseTest.spec.ts +6 -5
  28. package/src/main/typescript/test/xhrCore/ResponseTest23.spec.ts +2 -2
  29. package/src/main/typescript/test/xhrCore/XhrFormDataTest.spec.ts +1 -0
  30. package/target/impl/AjaxImpl.js +19 -1
  31. package/target/impl/AjaxImpl.js.map +1 -1
  32. package/target/impl/core/Const.js +2 -2
  33. package/target/impl/core/Const.js.map +1 -1
  34. package/target/impl/xhrCore/RequestDataResolver.js +48 -1
  35. package/target/impl/xhrCore/RequestDataResolver.js.map +1 -1
  36. package/target/impl/xhrCore/Response.js +1 -1
  37. package/target/impl/xhrCore/Response.js.map +1 -1
  38. package/target/impl/xhrCore/ResponseProcessor.js +3 -3
  39. package/target/impl/xhrCore/ResponseProcessor.js.map +1 -1
  40. package/target/impl/xhrCore/XhrFormData.js +36 -19
  41. package/target/impl/xhrCore/XhrFormData.js.map +1 -1
  42. package/target/impl/xhrCore/XhrRequest.js +11 -2
  43. package/target/impl/xhrCore/XhrRequest.js.map +1 -1
  44. package/target/test/xhrCore/FileUploadTest.spec.js +1 -0
  45. package/target/test/xhrCore/FileUploadTest.spec.js.map +1 -1
  46. package/target/test/xhrCore/NamespacesRequestTest.spec.js +8 -7
  47. package/target/test/xhrCore/NamespacesRequestTest.spec.js.map +1 -1
  48. package/target/test/xhrCore/ResponseTest.spec.js +6 -3
  49. package/target/test/xhrCore/ResponseTest.spec.js.map +1 -1
  50. package/target/test/xhrCore/ResponseTest23.spec.js +2 -2
  51. package/target/test/xhrCore/ResponseTest23.spec.js.map +1 -1
  52. package/target/test/xhrCore/XhrFormDataTest.spec.js +1 -0
  53. 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.24",
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.0.0",
33
+ "jsdom": "^21.1.0",
34
34
  "jsdom-global": "^3.0.2",
35
35
  "mocha": "^10.2.0",
36
- "npm-check-updates": "^16.6.2",
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.3"
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, 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";
@@ -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
- PARTIAL_ID,
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, PARTIAL_ID).value = partialId; // second case mojarra
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
- PARTIAL_ID,
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(PARTIAL_ID);
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(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));
@@ -376,7 +376,7 @@ export class ResponseProcessor implements IResponseProcessor {
376
376
  }
377
377
 
378
378
  updateNamedViewRootState() {
379
- let partialId = this.internalContext.getIf(PARTIAL_ID);
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 optmized, practically elements
59
- // which are already covered by an external viewstate do not need
60
- // the encoding a second time, because they are overwritten by the viewstate again
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
- // this.appendIf(viewState.isPresent(), P_VIEWSTATE).value = viewState.value;
115
- this.appendIf(viewState.isPresent(), viewStateElement.name.value).value = viewState.value;
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]).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
-
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
- this.shallowMerge(toEncode.deepElements.encodeFormElement());
259
+ let formElements = toEncode.deepElements.encodeFormElement();
260
+ const mapped = this.remapKeysForNamingContainer(formElements);
261
+ this.shallowMerge(mapped);
255
262
  }
256
263
 
257
- 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));
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 {resolveFinalUrl, resolveHandlerFunc} from "./RequestDataResolver";
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 TODO remove the partial ids array
131
- let formData: XhrFormData = new XhrFormData(this.sourceForm, viewState, executesArr(), this.partialIdsArray);
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
  }
@@ -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
 
@@ -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
- let formData = new XhrFormData_1.XhrFormData(element);
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