Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Response with leading or trailing newline characters causes "Cannot read properties of null (reading 'htmx-internal-data')" error #2942

Closed
gritvald opened this issue Oct 4, 2024 · 1 comment

Comments

@gritvald
Copy link
Contributor

gritvald commented Oct 4, 2024

htmx version: 2.0.2

I have the following input:

<input
    type="text"
    name="phrase"
    hx-get="/search"
    hx-trigger="input changed delay:300ms"
    hx-target="#availableAssetList"
/>

The /search endpoint returns HTML with some newlines at the top and bottom of the response (line numbers are not part of the response):

1. 
2. 
3. 
4.     <ul >
5.         
6.     </ul>
7. 
8. 

An exception is thrown from the getInternalData function because the elt param has a null value:

function getInternalData(elt) {
  const dataProp = 'htmx-internal-data'
  let data = elt[dataProp]  // elt === null
  if (!data) {
    data = elt[dataProp] = {}
  }
  return data
}

Below is the value of the child variable from the makeAjaxLoadTask function call frame:

child = {
    assignedSlot: null,
    baseURI: "...",
    childNodes: NodeList [],
    data: "\n\n\n    ",
    firstChild: null,
    isConnected: true,
    lastChild: null,
    length: 7,
    nextElementSibling: ul.htmx-added,
    nextSibling: ul.htmx-added,
    nodeName: "#text",
    nodeType: 3,
    nodeValue: "\n\n\n    ",
    ownerDocument: document,
    parentElement: div#availableAssetList.htmx-settling,
    parentNode: div#availableAssetList.htmx-settling,
    previousElementSibling: null,
    previousSibling: null,
    textContent: "\n\n\n    ",
    wholeText: "\n\n\n    "
}

Next, child is passed to asElement, which returns null, which is then passed through the processNode -> initNode -> getInternalData call chain:

function makeAjaxLoadTask(child) {
  return function() {
    removeClassFromElement(child, htmx.config.addedClass)
    processNode(asElement(child))
    processFocus(asParentNode(child))
    triggerEvent(child, 'htmx:load')
  }
}

When I strip leading and trailing newlines from the response everything works fine.

Maybe it's somehow related to #2613 and #2913.

@gritvald
Copy link
Contributor Author

gritvald commented Oct 12, 2024

I've found the issue.

I had defined a custom Node class that shadowed the built-in Node. This was the reason why insertNodesBefore was scheduling a settling task for text nodes - TEXT_NODE was undefined in my custom Node class, which is why the following test was always passing:

if (child.nodeType !== Node.TEXT_NODE && child.nodeType !== Node.COMMENT_NODE) {
    settleInfo.tasks.push(makeAjaxLoadTask(child))
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant