Details

      Description

      {markdown}
      Steps to reproduce:

      1. Deploy and navigate to the Icefaces portlet on Pluto.
      2. Click in the "Date of Birth" field and try to select a date from the popup calendar

      If the bug is fixed then the date will be selected and appear in the textbox.

      Otherwise, if the bug still exists then there will be an error in the browser's console log:

      Uncaught TypeError: Cannot read property 'length' of undefined
      http://localhost:8080/pluto/portal/ICE4/__rsicefaces4-portlet-40x200x20-SNAPSHOT0x21!2241321%7C0?ln=ice.core&javax.faces.resource=bridge.js

      The root cause of this issue is that the Liferay Faces `ResponseWriter`s are added to the delegation chain twice (because the Liferay Faces `RenderKit`s are added to the delegation chain twice) which causes `target="body"` scripts, `FacesRequestContext` scripts, and other scripts encoded in `BodyRenderer.encodeEnd()` to never be encoded. Since the `BodyScriptEncodingResponseWriter` detects when `responseWriter.endElement("body")` is called in order to encode body scripts, it must be on the outside of the delegation chain because `ResponseWriterBridgeBodyImpl` suppresses the `<body>` element. However, in the situation described in this issue, one `BodyScriptEncodingResponseWriter` ends up inside a `ResponseWriterBridgeBodyImpl` which causes the issue.

      When this issue occurs, the delegation chain looks something like this:

      *outside*
      `BodyScriptEncodingResponseWriter`
      `ResponseWriterBridgeBodyImpl`
      Other `ResponseWriter`s
      `BodyScriptEncodingResponseWriter`
      `ResponseWriterBridgeBodyImpl`
      Mojarra's base `ResponseWriter`
      *inside*

      Here is an exact description of what occurs because of this delegation chain:

      1. The outer `BodyScriptEncodingResponseWriter` captures third party body scripts and attempts to render them before the closing `</body>`.
      2. The inner `BodyScriptEncodingResponseWriter` re-captures the body scripts encoded by the outer `BodyScriptEncodingResponseWriter`.
      3. The outer `BodyScriptEncodingResponseWriter` calls `responseWriter.endElement("body")`.
      4. The outer `ResponseWriterBridgeBodyImpl` calls `responseWriter.endElement("div")` in order to suppress the `<body>` element.

      So the inner `BodyScriptEncodingResponseWriter` never encodes the captured scripts because `"body".equals(name)` is *not* true in `responseWriter.endElement("div")`.

      The reason that this bug does *not* occur in Liferay is because `BodyScriptEncodingResponseWriter` ends up calling the `LiferayImpl` of `ScriptsEncoder.encodeBodyScripts()` which calls through to Liferay's API for adding scripts before the closing `</body>` tag. This avoids the problem of the scripts being recaptured by the inner `BodyScriptEncodingResponseWriter` since `ScriptsEncoderLiferayImpl.encodeBodyScripts()` never calls a `ResponseWriter`.

      This situation should only occur when external libraries declare a `RenderKitWrapper`, and may also affect Primefaces and Richfaces portlets.

      This issue causes [ICE-10968](http://jira.icesoft.org/browse/ICE-10968).{markdown}

        Attachments

          Activity

            People

            • Assignee:
              kyle.stiemann Kyle Stiemann
              Reporter:
              kyle.stiemann Kyle Stiemann
              Participants of an Issue:
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Packages

                Version Package
                util-2.0.0
                util-3.0.0
                bridge-impl-3.0.0
                bridge-ext-5.0.0
                bridge-impl-4.0.0
                bridge-impl-5.0.0