Kevin Batdorf vor 4 Jahren
Ursprung
Commit
90d826547e
5 geänderte Dateien mit 32 neuen und 6 gelöschten Zeilen
  1. 3 3
      dist/alpine.js
  2. 1 1
      src/directives/bind.js
  3. 1 1
      src/directives/for.js
  4. 1 1
      src/directives/text.js
  5. 26 0
      test/spread.spec.js

+ 3 - 3
dist/alpine.js

@@ -574,7 +574,7 @@
     let forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;
     let stripParensRE = /^\(|\)$/g;
     let forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;
-    let inMatch = expression.match(forAliasRE);
+    let inMatch = String(expression).match(forAliasRE);
     if (!inMatch) return;
     let res = {};
     res.items = inMatch[2].trim();
@@ -671,7 +671,7 @@
     if (attrName === 'value') {
       if (Alpine.ignoreFocusedForValueBinding && document.activeElement.isSameNode(el)) return; // If nested model key is undefined, set the default value to empty string.
 
-      if (value === undefined && expression.match(/\./)) {
+      if (value === undefined && String(expression).match(/\./)) {
         value = '';
       }
 
@@ -754,7 +754,7 @@
 
   function handleTextDirective(el, output, expression) {
     // If nested model key is undefined, set the default value to empty string.
-    if (output === undefined && expression.match(/\./)) {
+    if (output === undefined && String(expression).match(/\./)) {
       output = '';
     }
 

+ 1 - 1
src/directives/bind.js

@@ -8,7 +8,7 @@ export function handleAttributeBindingDirective(component, el, attrName, express
         if (Alpine.ignoreFocusedForValueBinding && document.activeElement.isSameNode(el)) return
 
         // If nested model key is undefined, set the default value to empty string.
-        if (value === undefined && expression.match(/\./)) {
+        if (value === undefined && String(expression).match(/\./)) {
             value = ''
         }
 

+ 1 - 1
src/directives/for.js

@@ -46,7 +46,7 @@ function parseForExpression(expression) {
     let forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
     let stripParensRE = /^\(|\)$/g
     let forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/
-    let inMatch = expression.match(forAliasRE)
+    let inMatch = String(expression).match(forAliasRE)
     if (! inMatch) return
     let res = {}
     res.items = inMatch[2].trim()

+ 1 - 1
src/directives/text.js

@@ -1,6 +1,6 @@
 export function handleTextDirective(el, output, expression) {
     // If nested model key is undefined, set the default value to empty string.
-    if (output === undefined && expression.match(/\./)) {
+    if (output === undefined && String(expression).match(/\./)) {
         output = ''
     }
 

+ 26 - 0
test/spread.spec.js

@@ -215,3 +215,29 @@ test('x-spread event handlers defined as functions receive the event object as t
         expect(document.querySelector("div").__x.$data.eventType).toEqual("click");
     });
 });
+
+test('x-spread undefined values can fail gracefully', async () => {
+    window.data = function () {
+        return {
+            foo: {
+                ['x-text'](){
+                    return this.somethingUndefined;
+                }
+            }
+        };
+    };
+
+    document.body.innerHTML = `
+        <div x-data="window.data()">
+            <button x-text="somethingUndefined">should be empty string</button>
+            <span x-spread="foo">should be empty string<span>
+        </div>
+    `;
+
+    Alpine.start();
+
+    await wait(() => {
+        expect(document.querySelector("button").textContent).toEqual('')
+        expect(document.querySelector("span").textContent).toEqual('')
+    })
+});