Skip to content

Commit a62ee4d

Browse files
fix: signal attribute values not working with precompile transform
1 parent a3565a4 commit a62ee4d

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

jsx-runtime/src/index.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,19 @@ function jsxTemplate(templates, ...exprs) {
8686
const JS_TO_CSS = {};
8787
const CSS_REGEX = /[A-Z]/g;
8888

89+
/**
90+
* Unwrap potential signals.
91+
* @param {*} value
92+
* @returns {*}
93+
*/
94+
function normalizeAttrValue(value) {
95+
return value !== null &&
96+
typeof value === 'object' &&
97+
typeof value.valueOf === 'function'
98+
? value.valueOf()
99+
: value;
100+
}
101+
89102
/**
90103
* Serialize an HTML attribute to a string. This function is not
91104
* expected to be used directly, but rather through a precompile
@@ -100,6 +113,8 @@ function jsxAttr(name, value) {
100113
if (typeof result === 'string') return result;
101114
}
102115

116+
value = normalizeAttrValue(value);
117+
103118
if (name === 'ref' || name === 'key') return '';
104119
if (name === 'style' && typeof value === 'object') {
105120
let str = '';
@@ -127,7 +142,7 @@ function jsxAttr(name, value) {
127142
return '';
128143
} else if (value === true) return name;
129144

130-
return name + '="' + encodeEntities(value) + '"';
145+
return name + '="' + encodeEntities('' + value) + '"';
131146
}
132147

133148
/**

jsx-runtime/test/browser/jsx-runtime.test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,24 @@ import {
1111
import { setupScratch, teardown } from '../../../test/_util/helpers';
1212
import { encodeEntities } from '../../src/utils';
1313

14+
function createSignal(value) {
15+
return {
16+
value,
17+
peek() {
18+
return value;
19+
},
20+
subscribe() {
21+
return () => {};
22+
},
23+
valueOf() {
24+
return value;
25+
},
26+
toString() {
27+
return String(value);
28+
}
29+
};
30+
}
31+
1432
describe('Babel jsx/jsxDEV', () => {
1533
let scratch;
1634
let prevVNodeOption;
@@ -127,6 +145,12 @@ describe('precompiled JSX', () => {
127145
);
128146
});
129147

148+
it('should support signals', () => {
149+
const sig = createSignal(`&<'"`);
150+
expect(jsxAttr('foo', sig)).to.equal(`foo="&amp;&lt;'&quot;"`);
151+
expect(jsxAttr('style', sig)).to.equal(`style="&amp;&lt;'&quot;"`);
152+
});
153+
130154
it('should call options.attr()', () => {
131155
options.attr = (name, value) => {
132156
return `data-${name}="foo${value}"`;

0 commit comments

Comments
 (0)