Skip to content

Commit

Permalink
[BUGFIX lts] unique-id: Adjust uniqueId() implementation to only ge…
Browse files Browse the repository at this point in the history
…nerate valid selectors

Regular UUIDs are allowed to start with numeric digits, but CSS selectors may not start with those. This change adjusts the implementation to only return UUIDs starting with a letter instead of a digit.

(cherry picked from commit 2ffa93d)
  • Loading branch information
Turbo87 authored and chancancode committed Jun 21, 2022
1 parent 7ae2487 commit d145ab2
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
8 changes: 5 additions & 3 deletions packages/@ember/-internals/glimmer/lib/helpers/unique-id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ export default internalHelper((): Reference<string> => {
// This code should be reasonably fast, and provide a unique value every time
// it's called, which is what we need here. It produces a string formatted as a
// standard UUID, which avoids accidentally turning Ember-specific
// implementation details into an intimate API.
// implementation details into an intimate API. It also ensures that the UUID
// always starts with a letter, to avoid creating invalid IDs with a numeric
// digit at the start.
function uniqueId() {
// @ts-expect-error this one-liner abuses weird JavaScript semantics that
// TypeScript (legitimately) doesn't like, but they're nonetheless valid and
// specced.
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (a) =>
(a ^ ((Math.random() * 16) >> (a / 4))).toString(16)
return ([3e7] + -1e3 + -4e3 + -2e3 + -1e11).replace(/[0-3]/g, (a) =>
((a * 4) ^ ((Math.random() * 16) >> (a & 2))).toString(16)
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,24 @@ if (EMBER_UNIQUE_ID_HELPER) {
});
}

['@test it only generates valid selectors']() {
let iterations = 1000;
let reNumericStart = /^\d/;

let template = '<p>{{unique-id}}</p>'.repeat(iterations);
super.render(template);

for (let i = 0; i < iterations; i++) {
let textNode = this.nthChild(i).firstChild;
let text = textNode.data;

this.assert.false(
reNumericStart.test(text),
`{{unique-id}} should produce valid selectors` + text
);
}
}

render(template, ...rest) {
// If there are three parameters to `render`, the second parameter is the
// template's arguments.
Expand Down

0 comments on commit d145ab2

Please sign in to comment.