From df81b8275d5e95a20cd6462760fb73edfd614938 Mon Sep 17 00:00:00 2001 From: wukunyu264 Date: Fri, 15 Aug 2025 12:50:54 +0800 Subject: [PATCH 1/9] Create carousel-href.spec.js --- .../lib/bootstrap/test/carousel-href.spec.js | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.spec.js diff --git a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.spec.js b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.spec.js new file mode 100644 index 000000000000..5537ae5b35d5 --- /dev/null +++ b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.spec.js @@ -0,0 +1,52 @@ +// Node built-in test (no mocha) – Carousel data-api +const test = require('node:test'); +const assert = require('node:assert/strict'); + +// 设 EXPECT_FAST=1 时启用“<1000ms”断言;未修复时默认只打印时间 +const EXPECT_FAST = process.env.EXPECT_FAST === '1'; + +test('Carousel data-api href sanitize timing', () => { + // 极简 jQuery stub:按事件名记录 handler + const handlers = Object.create(null); + function wrap(raw) { + return { + on(eventName, selectorOrHandler, maybeHandler) { + const h = typeof maybeHandler === 'function' ? maybeHandler + : (typeof selectorOrHandler === 'function' ? selectorOrHandler : null); + if (eventName && h) handlers[eventName] = h; + return this; + }, + find() { return { hasClass: () => false }; }, + data() { return {}; }, + attr(name) { return raw && name === 'href' ? raw._href : null; } + }; + } + function $(x) { return wrap(x); } + $.fn = { jquery: '3.4.1' }; + $.extend = Object.assign; + global.window = global; + global.document = {}; + global.jQuery = global.$ = $; + + // 载入“本地(未修复/修复后)”的 bootstrap.js + require('../dist/js/bootstrap.js'); + + const click = handlers['click.bs.carousel.data-api'] || handlers['click.bs.carousel']; + assert.equal(typeof click, 'function', 'failed to capture carousel handler'); + + const N = 100000; + const cases = [ + { name: 'nul', s: '\u0000'.repeat(N) + '\u0000' }, + { name: 'digits\\n@', s: '1'.repeat(N) + '\n@' }, + //{ name: '=#...@\\r', s: '=' + '#'.repeat(N) + '@\r' }, + //{ name: '=#*@\\r', s: '=#'.repeat(N) + '@\r' }, + ]; + + for (const { name, s } of cases) { + const t0 = Date.now(); + try { click.call({ _href: s }, { preventDefault(){} }); } catch {} + const ms = Date.now() - t0; + console.log(`[carousel] ${name.padEnd(9)} len=${s.length} -> ${ms} ms`); + if (EXPECT_FAST) assert.ok(ms < 2000, `too slow: ${ms}ms`); + } +}); From e3e312309c2841768528d8190b994f3f1f1588a8 Mon Sep 17 00:00:00 2001 From: wukunyu264 Date: Fri, 15 Aug 2025 12:51:21 +0800 Subject: [PATCH 2/9] Create collapse-href.spec.js --- .../lib/bootstrap/test/collapse-href.spec.js | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/collapse-href.spec.js diff --git a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/collapse-href.spec.js b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/collapse-href.spec.js new file mode 100644 index 000000000000..40ff3111ce99 --- /dev/null +++ b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/collapse-href.spec.js @@ -0,0 +1,55 @@ +// Node built-in test (no mocha) – Collapse data-api +const test = require('node:test'); +const assert = require('node:assert/strict'); + +const EXPECT_FAST = process.env.EXPECT_FAST === '1'; + +test('Collapse data-api href sanitize timing', () => { + const handlers = Object.create(null); + function wrap(raw) { + return { + on(eventName, selectorOrHandler, maybeHandler) { + const h = typeof maybeHandler === 'function' ? maybeHandler + : (typeof selectorOrHandler === 'function' ? selectorOrHandler : null); + if (eventName && h) handlers[eventName] = h; + return this; + }, + each() { return this; }, // 避免深入插件逻辑 + data() { return {}; }, + attr(name) { + if (!raw) return null; + if (name === 'href') return raw._href || null; + if (name === 'data-target') return raw._dt || null; + return null; + }, + find() { return { hasClass: () => false }; } + }; + } + function $(x) { return wrap(x); } + $.fn = { jquery: '3.4.1' }; + $.extend = Object.assign; + global.window = global; + global.document = {}; + global.jQuery = global.$ = $; + + require('../dist/js/bootstrap.js'); + + const click = handlers['click.bs.collapse.data-api'] || handlers['click.bs.collapse']; + assert.equal(typeof click, 'function', 'failed to capture collapse handler'); + + const N = 100000; + const cases = [ + { name: 'nul', s: '\u0000'.repeat(N) + '\u0000' }, + { name: 'digits\\n@', s: '1'.repeat(N) + '\n@' }, + //{ name: '=#...@\\r', s: '=' + '#'.repeat(N) + '@\r' }, + //{ name: '=#*@\\r', s: '=#'.repeat(N) + '@\r' }, + ]; + + for (const { name, s } of cases) { + const t0 = Date.now(); + try { click.call({ _href: s, _dt: null }, { preventDefault(){} }); } catch {} + const ms = Date.now() - t0; + console.log(`[collapse] ${name.padEnd(9)} len=${s.length} -> ${ms} ms`); + if (EXPECT_FAST) assert.ok(ms < 2000, `too slow: ${ms}ms`); + } +}); From 282af7cfac5bcd027be185e79549a7bfa3a19613 Mon Sep 17 00:00:00 2001 From: wukunyu264 Date: Fri, 15 Aug 2025 12:52:40 +0800 Subject: [PATCH 3/9] Create package.json --- .../wwwroot/lib/bootstrap/package.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/package.json diff --git a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/package.json b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/package.json new file mode 100644 index 000000000000..d5abde6da3a8 --- /dev/null +++ b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/package.json @@ -0,0 +1,8 @@ +{ + "name": "bootstrap-sample-tests", + "private": true, + "type": "commonjs", + "scripts": { + "test": "node --test ./test/carousel-href.spec.js ./test/collapse-href.spec.js" + } +} From 309db13087736b27d71b571284b4b058644815da Mon Sep 17 00:00:00 2001 From: wukunyu264 Date: Fri, 15 Aug 2025 13:02:40 +0800 Subject: [PATCH 4/9] Update bootstrap.js --- .../wwwroot/lib/bootstrap/dist/js/bootstrap.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/dist/js/bootstrap.js b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/dist/js/bootstrap.js index 170bd608f7fd..5954cb9a3abf 100644 --- a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/dist/js/bootstrap.js +++ b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/dist/js/bootstrap.js @@ -511,7 +511,7 @@ if (typeof jQuery === 'undefined') { var $this = $(this) var href = $this.attr('href') if (href) { - href = href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 + href = href && href.indexOf('#') !== -1 ? href.slice(href.lastIndexOf('#')) : href } var target = $this.attr('data-target') || href @@ -705,7 +705,7 @@ if (typeof jQuery === 'undefined') { function getTargetFromTrigger($trigger) { var href var target = $trigger.attr('data-target') - || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 + || ((href = $trigger.attr('href')) && (href.indexOf('#') !== -1 ? href.slice(href.lastIndexOf('#')) : href)) // strip for ie7 (safe) return $(document).find(target) } From e57206ed457f28d81a6170e90d0f5c85ed2a5b68 Mon Sep 17 00:00:00 2001 From: wukunyu264 Date: Sun, 24 Aug 2025 22:22:27 +0800 Subject: [PATCH 5/9] Update carousel-href.spec.js --- .../lib/bootstrap/test/carousel-href.spec.js | 57 ++++++++++++------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.spec.js b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.spec.js index 5537ae5b35d5..c210cd22e1ce 100644 --- a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.spec.js +++ b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.spec.js @@ -1,52 +1,65 @@ -// Node built-in test (no mocha) – Carousel data-api -const test = require('node:test'); +// Node built-in test – Collapse data-api href sanitize timing (fail if > LIMIT ms) +const test = require('node:test'); const assert = require('node:assert/strict'); +const path = require('node:path'); -// 设 EXPECT_FAST=1 时启用“<1000ms”断言;未修复时默认只打印时间 -const EXPECT_FAST = process.env.EXPECT_FAST === '1'; +const BOOTSTRAP_PATH = + process.env.BOOTSTRAP_PATH || + path.resolve(__dirname, '../dist/js/bootstrap.js'); -test('Carousel data-api href sanitize timing', () => { - // 极简 jQuery stub:按事件名记录 handler +const N = parseInt(process.env.LENGTH || '100000', 10); +const LIMIT = parseInt(process.env.LIMIT || '2000', 10); // 超过就失败 + +test('Collapse data-api href sanitize timing', () => { + // 极简 jQuery stub:按事件名存 handler const handlers = Object.create(null); + function wrap(raw) { return { - on(eventName, selectorOrHandler, maybeHandler) { - const h = typeof maybeHandler === 'function' ? maybeHandler - : (typeof selectorOrHandler === 'function' ? selectorOrHandler : null); - if (eventName && h) handlers[eventName] = h; + on(event, selectorOrHandler, maybeHandler) { + const h = typeof maybeHandler === 'function' + ? maybeHandler + : (typeof selectorOrHandler === 'function' ? selectorOrHandler : null); + if (event && h) handlers[event] = h; return this; }, - find() { return { hasClass: () => false }; }, + find() { return { hasClass: () => false, data() { return {}; } }; }, data() { return {}; }, - attr(name) { return raw && name === 'href' ? raw._href : null; } + attr(name) { return raw && name === 'href' ? raw._href : null; }, }; } function $(x) { return wrap(x); } $.fn = { jquery: '3.4.1' }; $.extend = Object.assign; + global.window = global; global.document = {}; global.jQuery = global.$ = $; - // 载入“本地(未修复/修复后)”的 bootstrap.js - require('../dist/js/bootstrap.js'); + require(BOOTSTRAP_PATH); - const click = handlers['click.bs.carousel.data-api'] || handlers['click.bs.carousel']; - assert.equal(typeof click, 'function', 'failed to capture carousel handler'); + const click = + handlers['click.bs.collapse.data-api'] || + handlers['click.bs.collapse']; + assert.equal(typeof click, 'function', 'failed to capture collapse handler'); - const N = 100000; const cases = [ { name: 'nul', s: '\u0000'.repeat(N) + '\u0000' }, - { name: 'digits\\n@', s: '1'.repeat(N) + '\n@' }, - //{ name: '=#...@\\r', s: '=' + '#'.repeat(N) + '@\r' }, - //{ name: '=#*@\\r', s: '=#'.repeat(N) + '@\r' }, + { name: 'digits\\n@', s: '1'.repeat(N) + '\n@' }, ]; + let worst = 0; for (const { name, s } of cases) { const t0 = Date.now(); try { click.call({ _href: s }, { preventDefault(){} }); } catch {} const ms = Date.now() - t0; - console.log(`[carousel] ${name.padEnd(9)} len=${s.length} -> ${ms} ms`); - if (EXPECT_FAST) assert.ok(ms < 2000, `too slow: ${ms}ms`); + worst = Math.max(worst, ms); + console.log(`[collapse] ${name.padEnd(10)} len=${s.length} -> ${ms} ms`); + } + console.log(`[collapse] worst = ${worst} ms (limit=${LIMIT})`); + + // 关键:超过 LIMIT 就判失败(红色 ✗) + if (worst > LIMIT) { + assert.fail(`too slow: ${worst}ms (> ${LIMIT}ms)`); } }); From 0e61abddd62a98351b274bf1c17e8dfa0d85ee23 Mon Sep 17 00:00:00 2001 From: wukunyu264 Date: Sun, 24 Aug 2025 22:23:05 +0800 Subject: [PATCH 6/9] Update collapse-href.spec.js --- .../lib/bootstrap/test/collapse-href.spec.js | 58 +++++++++++-------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/collapse-href.spec.js b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/collapse-href.spec.js index 40ff3111ce99..c210cd22e1ce 100644 --- a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/collapse-href.spec.js +++ b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/collapse-href.spec.js @@ -1,55 +1,65 @@ -// Node built-in test (no mocha) – Collapse data-api -const test = require('node:test'); +// Node built-in test – Collapse data-api href sanitize timing (fail if > LIMIT ms) +const test = require('node:test'); const assert = require('node:assert/strict'); +const path = require('node:path'); -const EXPECT_FAST = process.env.EXPECT_FAST === '1'; +const BOOTSTRAP_PATH = + process.env.BOOTSTRAP_PATH || + path.resolve(__dirname, '../dist/js/bootstrap.js'); + +const N = parseInt(process.env.LENGTH || '100000', 10); +const LIMIT = parseInt(process.env.LIMIT || '2000', 10); // 超过就失败 test('Collapse data-api href sanitize timing', () => { + // 极简 jQuery stub:按事件名存 handler const handlers = Object.create(null); + function wrap(raw) { return { - on(eventName, selectorOrHandler, maybeHandler) { - const h = typeof maybeHandler === 'function' ? maybeHandler - : (typeof selectorOrHandler === 'function' ? selectorOrHandler : null); - if (eventName && h) handlers[eventName] = h; + on(event, selectorOrHandler, maybeHandler) { + const h = typeof maybeHandler === 'function' + ? maybeHandler + : (typeof selectorOrHandler === 'function' ? selectorOrHandler : null); + if (event && h) handlers[event] = h; return this; }, - each() { return this; }, // 避免深入插件逻辑 + find() { return { hasClass: () => false, data() { return {}; } }; }, data() { return {}; }, - attr(name) { - if (!raw) return null; - if (name === 'href') return raw._href || null; - if (name === 'data-target') return raw._dt || null; - return null; - }, - find() { return { hasClass: () => false }; } + attr(name) { return raw && name === 'href' ? raw._href : null; }, }; } function $(x) { return wrap(x); } $.fn = { jquery: '3.4.1' }; $.extend = Object.assign; + global.window = global; global.document = {}; global.jQuery = global.$ = $; - require('../dist/js/bootstrap.js'); + require(BOOTSTRAP_PATH); - const click = handlers['click.bs.collapse.data-api'] || handlers['click.bs.collapse']; + const click = + handlers['click.bs.collapse.data-api'] || + handlers['click.bs.collapse']; assert.equal(typeof click, 'function', 'failed to capture collapse handler'); - const N = 100000; const cases = [ { name: 'nul', s: '\u0000'.repeat(N) + '\u0000' }, - { name: 'digits\\n@', s: '1'.repeat(N) + '\n@' }, - //{ name: '=#...@\\r', s: '=' + '#'.repeat(N) + '@\r' }, - //{ name: '=#*@\\r', s: '=#'.repeat(N) + '@\r' }, + { name: 'digits\\n@', s: '1'.repeat(N) + '\n@' }, ]; + let worst = 0; for (const { name, s } of cases) { const t0 = Date.now(); - try { click.call({ _href: s, _dt: null }, { preventDefault(){} }); } catch {} + try { click.call({ _href: s }, { preventDefault(){} }); } catch {} const ms = Date.now() - t0; - console.log(`[collapse] ${name.padEnd(9)} len=${s.length} -> ${ms} ms`); - if (EXPECT_FAST) assert.ok(ms < 2000, `too slow: ${ms}ms`); + worst = Math.max(worst, ms); + console.log(`[collapse] ${name.padEnd(10)} len=${s.length} -> ${ms} ms`); + } + console.log(`[collapse] worst = ${worst} ms (limit=${LIMIT})`); + + // 关键:超过 LIMIT 就判失败(红色 ✗) + if (worst > LIMIT) { + assert.fail(`too slow: ${worst}ms (> ${LIMIT}ms)`); } }); From 17ebc99a7016692d0b0a1550da31e76dd310a003 Mon Sep 17 00:00:00 2001 From: wukunyu264 Date: Sun, 24 Aug 2025 22:23:48 +0800 Subject: [PATCH 7/9] Update carousel-href.spec.js --- .../lib/bootstrap/test/carousel-href.spec.js | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.spec.js b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.spec.js index c210cd22e1ce..db23515167c7 100644 --- a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.spec.js +++ b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.spec.js @@ -1,4 +1,4 @@ -// Node built-in test – Collapse data-api href sanitize timing (fail if > LIMIT ms) +// Node built-in test – Carousel data-api href sanitize timing (fail if > LIMIT) const test = require('node:test'); const assert = require('node:assert/strict'); const path = require('node:path'); @@ -7,11 +7,11 @@ const BOOTSTRAP_PATH = process.env.BOOTSTRAP_PATH || path.resolve(__dirname, '../dist/js/bootstrap.js'); -const N = parseInt(process.env.LENGTH || '100000', 10); -const LIMIT = parseInt(process.env.LIMIT || '2000', 10); // 超过就失败 +const N = parseInt(process.env.LENGTH || '100000', 10); +const LIMIT = parseInt(process.env.LIMIT || '2000', 10); // 超过即失败 -test('Collapse data-api href sanitize timing', () => { - // 极简 jQuery stub:按事件名存 handler +test('Carousel data-api href sanitize timing (fail if > LIMIT)', () => { + // 极简 jQuery stub:按事件名保存 handler const handlers = Object.create(null); function wrap(raw) { @@ -21,7 +21,7 @@ test('Collapse data-api href sanitize timing', () => { ? maybeHandler : (typeof selectorOrHandler === 'function' ? selectorOrHandler : null); if (event && h) handlers[event] = h; - return this; + return this; // 链式 .on().on() }, find() { return { hasClass: () => false, data() { return {}; } }; }, data() { return {}; }, @@ -32,20 +32,23 @@ test('Collapse data-api href sanitize timing', () => { $.fn = { jquery: '3.4.1' }; $.extend = Object.assign; + // 满足 bootstrap 自检 global.window = global; global.document = {}; global.jQuery = global.$ = $; + // 载入本地 bootstrap(未修复/修复后的都可以) require(BOOTSTRAP_PATH); + // 精确拿到 Carousel 的 data-api 处理器 const click = - handlers['click.bs.collapse.data-api'] || - handlers['click.bs.collapse']; - assert.equal(typeof click, 'function', 'failed to capture collapse handler'); + handlers['click.bs.carousel.data-api'] || + handlers['click.bs.carousel']; + assert.equal(typeof click, 'function', 'failed to capture carousel handler'); const cases = [ { name: 'nul', s: '\u0000'.repeat(N) + '\u0000' }, - { name: 'digits\\n@', s: '1'.repeat(N) + '\n@' }, + { name: 'digits\\n@', s: '1'.repeat(N) + '\n@' }, ]; let worst = 0; @@ -54,9 +57,9 @@ test('Collapse data-api href sanitize timing', () => { try { click.call({ _href: s }, { preventDefault(){} }); } catch {} const ms = Date.now() - t0; worst = Math.max(worst, ms); - console.log(`[collapse] ${name.padEnd(10)} len=${s.length} -> ${ms} ms`); + console.log(`[carousel] ${name.padEnd(10)} len=${s.length} -> ${ms} ms`); } - console.log(`[collapse] worst = ${worst} ms (limit=${LIMIT})`); + console.log(`[carousel] worst = ${worst} ms (limit=${LIMIT})`); // 关键:超过 LIMIT 就判失败(红色 ✗) if (worst > LIMIT) { From a69fa21da9b594f801e3aac0d2bc01952c7781ae Mon Sep 17 00:00:00 2001 From: wukunyu264 Date: Sun, 24 Aug 2025 22:27:25 +0800 Subject: [PATCH 8/9] Add files via upload --- .../lib/bootstrap/test/carousel-href.test.js | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.test.js diff --git a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.test.js b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.test.js new file mode 100644 index 000000000000..84c324452652 --- /dev/null +++ b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/test/carousel-href.test.js @@ -0,0 +1,62 @@ +// Node built-in test – Carousel data-api href sanitize timing (pass if < LIMIT) +const test = require('node:test'); +const assert = require('node:assert/strict'); +const path = require('node:path'); + +const BOOTSTRAP_PATH = + process.env.BOOTSTRAP_PATH || + path.resolve(__dirname, '../dist/js/bootstrap.js'); + +const N = parseInt(process.env.LENGTH || '100000', 10); +const LIMIT = parseInt(process.env.LIMIT || '2000', 10); + +test('Carousel data-api href sanitize timing (pass if < LIMIT)', () => { + const handlers = Object.create(null); + + function wrap(raw) { + return { + on(event, selectorOrHandler, maybeHandler) { + const h = typeof maybeHandler === 'function' + ? maybeHandler + : (typeof selectorOrHandler === 'function' ? selectorOrHandler : null); + if (event && h) handlers[event] = h; + return this; + }, + find() { return { hasClass: () => false, data() { return {}; } }; }, + data() { return {}; }, + attr(name) { return raw && name === 'href' ? raw._href : null; }, + }; + } + function $(x) { return wrap(x); } + $.fn = { jquery: '3.4.1' }; + $.extend = Object.assign; + + global.window = global; + global.document = {}; + global.jQuery = global.$ = $; + + require(BOOTSTRAP_PATH); + + const click = + handlers['click.bs.carousel.data-api'] || + handlers['click.bs.carousel']; + assert.equal(typeof click, 'function', 'failed to capture carousel handler'); + + const cases = [ + { name: 'nul', s: '\u0000'.repeat(N) + '\u0000' }, + { name: 'digits\\n@', s: '1'.repeat(N) + '\n@' }, + ]; + + let worst = 0; + for (const { name, s } of cases) { + const t0 = Date.now(); + try { click.call({ _href: s }, { preventDefault(){} }); } catch {} + const ms = Date.now() - t0; + worst = Math.max(worst, ms); + console.log(`[carousel] ${name.padEnd(10)} len=${s.length} -> ${ms} ms`); + } + console.log(`[carousel] worst = ${worst} ms (limit=${LIMIT})`); + + // 修复后应当 < LIMIT;否则失败 + assert.ok(worst < LIMIT, `too slow: ${worst}ms (>= ${LIMIT}ms)`); +}); From 088267eae95307a6eed51142860e414c3fcca4cf Mon Sep 17 00:00:00 2001 From: wukunyu264 Date: Sun, 24 Aug 2025 22:30:08 +0800 Subject: [PATCH 9/9] Update bootstrap.js --- .../wwwroot/lib/bootstrap/dist/js/bootstrap.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/dist/js/bootstrap.js b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/dist/js/bootstrap.js index 5954cb9a3abf..c6f9020438cf 100644 --- a/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/dist/js/bootstrap.js +++ b/src/Security/samples/ClaimsTransformation/wwwroot/lib/bootstrap/dist/js/bootstrap.js @@ -1265,7 +1265,8 @@ if (typeof jQuery === 'undefined') { var $this = $(this) var href = $this.attr('href') var target = $this.attr('data-target') || - (href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 + //(href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 + (href && href.replace(/^[^#]*(?=#\S+$)/, '')) // strip for ie7 - safe var $target = $(document).find(target) var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())