From 2ffa93deaf5819d1709a78b1363e1e4d6c35909f Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Tue, 14 Jun 2022 12:31:09 +0200 Subject: [PATCH] unique-id: Adjust `uniqueId()` implementation to only generate 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. --- .../glimmer/lib/helpers/unique-id.ts | 8 +++++--- .../integration/helpers/unique-id-test.js | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/@ember/-internals/glimmer/lib/helpers/unique-id.ts b/packages/@ember/-internals/glimmer/lib/helpers/unique-id.ts index 831926c75af..bf503bec73c 100644 --- a/packages/@ember/-internals/glimmer/lib/helpers/unique-id.ts +++ b/packages/@ember/-internals/glimmer/lib/helpers/unique-id.ts @@ -37,12 +37,14 @@ export default internalHelper((): Reference => { // 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) ); } diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/unique-id-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/unique-id-test.js index 763722f49ed..e4f4b2b5942 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/unique-id-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/unique-id-test.js @@ -102,6 +102,24 @@ if (EMBER_UNIQUE_ID_HELPER) { }); } + ['@test it only generates valid selectors']() { + let iterations = 1000; + let reNumericStart = /^\d/; + + let template = '

{{unique-id}}

'.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.