kn-es-features 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/esfeatures.iife.js +11 -14
  2. package/dist/esfeatures.js +1596 -2282
  3. package/dist/esfeatures.umd.cjs +11 -14
  4. package/package.json +2 -2
  5. package/src/features/es2015/01-let-const.js +0 -33
  6. package/src/features/es2015/02-arrow-functions.js +0 -56
  7. package/src/features/es2015/03-template-literals.js +0 -38
  8. package/src/features/es2015/04-destructuring.js +0 -51
  9. package/src/features/es2015/05-default-rest-spread.js +0 -74
  10. package/src/features/es2015/08-symbols.js +0 -71
  11. package/src/features/es2015/09-iterators-generators.js +0 -71
  12. package/src/features/es2015/10-map-set.js +1 -86
  13. package/src/features/es2015/11-proxy-reflect.js +1 -84
  14. package/src/features/es2015/12-enhanced-objects.js +0 -80
  15. package/src/features/es2015/16-for-of.js +0 -33
  16. package/src/features/es2015/17-map.js +0 -46
  17. package/src/features/es2022/06-regexp-d-flag.js +4 -0
  18. package/src/features/es2022/07-top-level-await.js +6 -6
  19. package/src/features/es2025/01-iterator-helpers.js +4 -0
  20. package/src/features/es2025/02-set-methods.js +5 -1
  21. package/src/features/es2025/03-promise-try.js +15 -7
  22. package/src/features/es2025/04-regexp-duplicate-groups.js +4 -0
  23. package/src/features/es2025/05-uint8array-base64-hex.js +4 -0
  24. package/src/features/es2025/06-json-parse-source.js +4 -0
  25. package/src/features/es2025/07-error-is-error.js +4 -0
  26. package/src/features/es2025/08-float16array.js +4 -8
  27. package/src/features/es2026/01-math-sum-precise.js +4 -0
  28. package/src/features/es2026/02-regexp-escape.js +10 -6
  29. package/src/features/es2026/03-explicit-resource-management.js +5 -1
  30. package/src/features/es2026/04-atomics-pause.js +4 -0
  31. package/src/features/es2026/05-import-attributes.js +5 -1
  32. package/src/polyfills.js +1 -1
  33. package/src/validate-main.js +5 -5
@@ -17,85 +17,5 @@ export function testEnhancedObjects() {
17
17
  assert(obj.greet('Bob') === 'Hello, Bob!', '方法简写')
18
18
  })
19
19
 
20
- test('计算属性名', () => {
21
- const prefix = 'prop'
22
- const obj = {
23
- [`${prefix}1`]: 'value1',
24
- [`${prefix}2`]: 'value2',
25
- [Symbol.iterator]: function* () { yield 1 }
26
- }
27
- assert(obj.prop1 === 'value1' && obj.prop2 === 'value2', '计算属性名')
28
- })
29
-
30
- test('__proto__ 设置原型', () => {
31
- const proto = { greet() { return 'hi' } }
32
- const obj = { __proto__: proto }
33
- assert(obj.greet() === 'hi', '__proto__ 设置原型')
34
- assert(Object.getPrototypeOf(obj) === proto, '原型链正确')
35
- })
36
-
37
- test('super 在对象方法中使用', () => {
38
- const base = {
39
- toString() { return 'base' }
40
- }
41
- const derived = {
42
- __proto__: base,
43
- toString() { return super.toString() + '+derived' }
44
- }
45
- assert(derived.toString() === 'base+derived', 'super 在对象方法中')
46
- })
47
-
48
- test('Object.assign 合并对象', () => {
49
- const target = { a: 1 }
50
- const source = { b: 2, c: 3 }
51
- Object.assign(target, source)
52
- assert(target.a === 1 && target.b === 2 && target.c === 3, 'Object.assign 合并')
53
- })
54
-
55
- test('Object.keys / values / entries', () => {
56
- const obj = { a: 1, b: 2, c: 3 }
57
- assert(Object.keys(obj).join(',') === 'a,b,c', 'Object.keys')
58
- assert(Object.values(obj).join(',') === '1,2,3', 'Object.values')
59
- const entries = Object.entries(obj)
60
- assert(entries[0][0] === 'a' && entries[0][1] === 1, 'Object.entries')
61
- })
62
-
63
- test('Object.freeze 冻结对象', () => {
64
- const obj = Object.freeze({ x: 1 })
65
- try {
66
- obj.x = 999
67
- // 非严格模式下静默失败,严格模式(ES模块)下抛出 TypeError
68
- } catch (e) {
69
- assert(e instanceof TypeError, '严格模式下修改冻结属性应抛出 TypeError')
70
- }
71
- assert(obj.x === 1, 'Object.freeze 冻结后属性值不变')
72
- })
73
-
74
- test('Object.create 自定义原型', () => {
75
- const proto = {
76
- greet() { return `Hello, I'm ${this.name}` }
77
- }
78
- const obj = Object.create(proto)
79
- obj.name = 'World'
80
- assert(obj.greet() === "Hello, I'm World", 'Object.create 自定义原型')
81
- })
82
-
83
- test('属性描述符 Object.defineProperty', () => {
84
- const obj = {}
85
- Object.defineProperty(obj, 'readonly', {
86
- value: 42,
87
- writable: false,
88
- enumerable: true,
89
- configurable: false
90
- })
91
- try {
92
- obj.readonly = 999
93
- // 非严格模式下静默失败,严格模式(ES模块)下抛出 TypeError
94
- } catch (e) {
95
- assert(e instanceof TypeError, '严格模式下赋值只读属性应抛出 TypeError')
96
- }
97
- assert(obj.readonly === 42, 'defineProperty 只读属性值不变')
98
- })
99
-
100
20
  return getResults()
101
21
  }
@@ -38,38 +38,5 @@ export function testForOf() {
38
38
  assert(fn(1, 2, 3).join(',') === '1,2,3', 'for...of 迭代 arguments')
39
39
  })
40
40
 
41
- test('for...of 与 break / continue', () => {
42
- const result = []
43
- for (const x of [1, 2, 3, 4, 5]) {
44
- if (x === 3) continue
45
- if (x === 5) break
46
- result.push(x)
47
- }
48
- assert(result.join(',') === '1,2,4', 'for...of 支持 break 和 continue')
49
- })
50
-
51
- test('for...of 迭代 NodeList(DOM 环境跳过)', () => {
52
- // 非 DOM 环境,仅验证迭代协议通用性
53
- const iterable = {
54
- [Symbol.iterator]() {
55
- let n = 0
56
- return { next() { return n < 3 ? { value: n++, done: false } : { done: true } } }
57
- }
58
- }
59
- const result = []
60
- for (const x of iterable) result.push(x)
61
- assert(result.join(',') === '0,1,2', '自定义可迭代对象')
62
- })
63
-
64
- test('Array entries / keys / values 迭代', () => {
65
- const arr = ['a', 'b', 'c']
66
- const entries = [...arr.entries()]
67
- const keys = [...arr.keys()]
68
- const values = [...arr.values()]
69
- assert(entries[1][0] === 1 && entries[1][1] === 'b', 'entries 迭代')
70
- assert(keys.join(',') === '0,1,2', 'keys 迭代')
71
- assert(values.join(',') === 'a,b,c', 'values 迭代')
72
- })
73
-
74
41
  return getResults()
75
42
  }
@@ -28,53 +28,7 @@ export function testMapGetOrInsert() {
28
28
  assert(result === 'foo', 'key 已存在应返回原值 foo')
29
29
  })
30
30
 
31
- test('getOrInsert - key 不存在时插入默认值', () => {
32
- const map = new Map()
33
- const result = map.getOrInsert('newKey', 42)
34
- assert(result === 42, '应返回插入的默认值 42')
35
- assert(map.get('newKey') === 42, 'key 已被写入 map')
36
- })
37
-
38
- test('getOrInsert - 不覆盖已有值', () => {
39
- const map = new Map([['x', 100]])
40
- map.getOrInsert('x', 999)
41
- assert(map.get('x') === 100, '已有值不应被覆盖')
42
- })
43
-
44
- test('getOrInsert - 词频统计经典用法', () => {
45
- const words = ['apple', 'banana', 'apple', 'apple', 'banana']
46
- const freq = new Map()
47
- for (const w of words) {
48
- freq.getOrInsert(w, 0)
49
- freq.set(w, freq.get(w) + 1)
50
- }
51
- assert(freq.get('apple') === 3, 'apple 出现 3 次')
52
- assert(freq.get('banana') === 2, 'banana 出现 2 次')
53
- })
54
31
 
55
- test('getOrInsertComputed - key 不存在时用回调计算', () => {
56
- const map = new Map()
57
- const result = map.getOrInsertComputed('user:1', (k) => ({ id: k, score: 0 }))
58
- assert(result.id === 'user:1' && result.score === 0, '回调以 key 为参数生成默认值')
59
- })
60
-
61
- test('getOrInsertComputed - key 已存在时不调用回调', () => {
62
- const map = new Map([['x', 'original']])
63
- let called = false
64
- const result = map.getOrInsertComputed('x', () => { called = true; return 'new' })
65
- assert(!called, 'key 已存在,回调不应被调用')
66
- assert(result === 'original', '应返回原有值')
67
- })
68
-
69
- test('getOrInsertComputed - 构建邻接表', () => {
70
- const edges = [[1, 2], [1, 3], [2, 3]]
71
- const graph = new Map()
72
- for (const [from, to] of edges) {
73
- graph.getOrInsertComputed(from, () => []).push(to)
74
- }
75
- assert(graph.get(1).join(',') === '2,3', '节点 1 的邻居为 [2,3]')
76
- assert(graph.get(2).join(',') === '3', '节点 2 的邻居为 [3]')
77
- })
78
32
 
79
33
  return getResults()
80
34
  }
@@ -17,6 +17,10 @@ export function testRegExpDFlag() {
17
17
  try { return new RegExp('x', 'd').hasIndices === true } catch { return false }
18
18
  })()
19
19
 
20
+ test('环境支持检测', () => {
21
+ assert(supported, '环境不支持 RegExp /d 标志')
22
+ })
23
+
20
24
  test('hasIndices 属性标识是否启用 /d 标志', () => {
21
25
  if (!supported) { assert(true, '(跳过:环境不支持 /d 标志)'); return }
22
26
  assert(new RegExp('x', 'd').hasIndices === true, '/d 标志应使 hasIndices 为 true')
@@ -16,14 +16,14 @@ import { createSuite } from '../../utils/runner.js'
16
16
  export async function testTopLevelAwait() {
17
17
  const { test, assert, getResults } = createSuite('Top-level await (ES2022)')
18
18
 
19
- test('async 函数内的 await 是等价基础能力', async () => {
19
+ await test('async 函数内的 await 是等价基础能力', async () => {
20
20
  // top-level await 本质上是将整个模块包装为隐式 async 函数
21
21
  // 在 async 函数顶层 await 等同于模块顶层 await
22
22
  const value = await Promise.resolve(42)
23
23
  assert(value === 42, 'await 在 async 函数顶层应正常工作')
24
24
  })
25
25
 
26
- test('await 可以等待动态 import()', async () => {
26
+ await test('await 可以等待动态 import()', async () => {
27
27
  // 动态 import 是 top-level await 最常见的使用场景
28
28
  // 由于测试环境限制,用 Promise 模拟等价行为
29
29
  const fakeImport = () => Promise.resolve({ default: 'module-content', util: () => 'ok' })
@@ -32,7 +32,7 @@ export async function testTopLevelAwait() {
32
32
  assert(mod.util() === 'ok', '模块导出的函数应可调用')
33
33
  })
34
34
 
35
- test('await 保序 —— 导入方等待模块初始化完成', async () => {
35
+ await test('await 保序 —— 导入方等待模块初始化完成', async () => {
36
36
  // top-level await 会阻塞依赖该模块的其他模块
37
37
  // 模拟:模块 A 需要等待异步初始化,模块 B 导入 A 后才能使用其导出值
38
38
  const log = []
@@ -47,7 +47,7 @@ export async function testTopLevelAwait() {
47
47
  assert(log.join(',') === 'A:start,A:ready,B:use', '执行顺序应严格保序')
48
48
  })
49
49
 
50
- test('await 与条件导入模拟', async () => {
50
+ await test('await 与条件导入模拟', async () => {
51
51
  // top-level await 常用于条件加载不同平台的模块
52
52
  const isBrowser = typeof window !== 'undefined'
53
53
  const platform = await Promise.resolve(isBrowser ? 'browser' : 'node')
@@ -55,7 +55,7 @@ export async function testTopLevelAwait() {
55
55
  assert(platform === 'browser' || platform === 'node', '平台标识应为 browser 或 node')
56
56
  })
57
57
 
58
- test('await 错误应在模块加载阶段被捕获', async () => {
58
+ await test('await 错误应在模块加载阶段被捕获', async () => {
59
59
  // top-level await 抛出的错误会导致整个模块加载失败
60
60
  // 等价测试:async 顶层 await 的错误传播
61
61
  let caught = null
@@ -68,7 +68,7 @@ export async function testTopLevelAwait() {
68
68
  assert(caught.message === '模块初始化失败', '错误消息应正确传递')
69
69
  })
70
70
 
71
- test('await 不阻塞无依赖的兄弟模块(并行加载)', async () => {
71
+ await test('await 不阻塞无依赖的兄弟模块(并行加载)', async () => {
72
72
  // 两个相互独立的异步模块可以并行初始化
73
73
  const t0 = Date.now()
74
74
  const [a, b] = await Promise.all([
@@ -13,6 +13,10 @@ export function testIteratorHelpers() {
13
13
  // 检测环境是否支持
14
14
  const supported = typeof Iterator !== 'undefined' && typeof Iterator.from === 'function'
15
15
 
16
+ test('环境支持检测', () => {
17
+ assert(supported, '环境不支持 Iterator Helpers')
18
+ })
19
+
16
20
  test('Iterator.from() 将可迭代对象转为迭代器', () => {
17
21
  if (!supported) { assert(true, '(跳过:环境不支持 Iterator.from)'); return }
18
22
  const iter = Iterator.from([1, 2, 3])
@@ -12,6 +12,10 @@ export function testSetMethods() {
12
12
 
13
13
  const supported = typeof Set.prototype.union === 'function'
14
14
 
15
+ test('环境支持检测', () => {
16
+ assert(supported, '环境不支持 Set 新方法(union/intersection 等)')
17
+ })
18
+
15
19
  test('union() —— 并集', () => {
16
20
  if (!supported) { assert(true, '(跳过:环境不支持 Set.prototype.union)'); return }
17
21
  const a = new Set([1, 2, 3])
@@ -84,7 +88,7 @@ export function testSetMethods() {
84
88
  if (!supported) { assert(true, '(跳过)'); return }
85
89
  const a = new Set([1, 2, 3])
86
90
  // 传入数组
87
- const result = a.intersection([2, 3, 4])
91
+ const result = a.intersection(new Set([2, 3, 4]))
88
92
  assert(result.size === 2 && result.has(2) && result.has(3), '应支持传入普通数组')
89
93
  })
90
94
 
@@ -15,20 +15,28 @@ export async function testPromiseTry() {
15
15
 
16
16
  const supported = typeof Promise.try === 'function'
17
17
 
18
- test('同步函数 —— 返回值转为 resolved', async () => {
18
+ await test('环境支持检测', async () => {
19
+ if (!supported) {
20
+ assert(false, '(环境不支持 Promise.try)'); return
21
+ }
22
+ assert(true, '环境支持 Promise.try')
23
+ })
24
+
25
+
26
+ await test('同步函数 —— 返回值转为 resolved', async () => {
19
27
  if (!supported) { assert(true, '(跳过:环境不支持 Promise.try)'); return }
20
28
  const result = await Promise.try(() => 42)
21
29
  assert(result === 42, '同步返回值应被 resolve 为 42')
22
30
  })
23
31
 
24
- test('同步函数 —— 抛出异常转为 rejected', async () => {
32
+ await test('同步函数 —— 抛出异常转为 rejected', async () => {
25
33
  if (!supported) { assert(true, '(跳过)'); return }
26
34
  let caught = null
27
35
  await Promise.try(() => { throw new Error('同步错误') }).catch(e => { caught = e })
28
36
  assert(caught instanceof Error && caught.message === '同步错误', '同步异常应转为 rejected')
29
37
  })
30
38
 
31
- test('异步函数 —— resolved 正常透传', async () => {
39
+ await test('异步函数 —— resolved 正常透传', async () => {
32
40
  if (!supported) { assert(true, '(跳过)'); return }
33
41
  const result = await Promise.try(async () => {
34
42
  return 'async result'
@@ -36,7 +44,7 @@ export async function testPromiseTry() {
36
44
  assert(result === 'async result', '异步 resolved 值应透传')
37
45
  })
38
46
 
39
- test('异步函数 —— rejected 正常透传', async () => {
47
+ await test('异步函数 —— rejected 正常透传', async () => {
40
48
  if (!supported) { assert(true, '(跳过)'); return }
41
49
  let caught = null
42
50
  await Promise.try(async () => {
@@ -45,20 +53,20 @@ export async function testPromiseTry() {
45
53
  assert(caught instanceof Error && caught.message === '异步错误', '异步 rejected 应透传')
46
54
  })
47
55
 
48
- test('返回已有 Promise —— 直接透传', async () => {
56
+ await test('返回已有 Promise —— 直接透传', async () => {
49
57
  if (!supported) { assert(true, '(跳过)'); return }
50
58
  const original = Promise.resolve('original')
51
59
  const result = await Promise.try(() => original)
52
60
  assert(result === 'original', '返回已有 Promise 的值应直接透传')
53
61
  })
54
62
 
55
- test('传递参数给回调函数', async () => {
63
+ await test('传递参数给回调函数', async () => {
56
64
  if (!supported) { assert(true, '(跳过)'); return }
57
65
  const result = await Promise.try((a, b) => a + b, 10, 20)
58
66
  assert(result === 30, '应能向回调函数传递参数')
59
67
  })
60
68
 
61
- test('对比 new Promise —— 捕获同步异常的等价写法', async () => {
69
+ await test('对比 new Promise —— 捕获同步异常的等价写法', async () => {
62
70
  if (!supported) { assert(true, '(跳过)'); return }
63
71
  // 旧写法:若 fn 同步抛出,需要用 try/catch 包裹才能转为 rejected
64
72
  // Promise.try 自动处理,以下两种写法等价:
@@ -20,6 +20,10 @@ export function testRegExpDuplicateGroups() {
20
20
  supported = false
21
21
  }
22
22
 
23
+ test('环境支持检测', () => {
24
+ assert(supported, '环境不支持重复命名捕获组')
25
+ })
26
+
23
27
  test('同一命名组在不同分支中可重复使用', () => {
24
28
  if (!supported) { assert(true, '(跳过:环境不支持重复命名捕获组)'); return }
25
29
  // 匹配两种日期格式:YYYY-MM-DD 或 DD/MM/YYYY
@@ -14,6 +14,10 @@ export function testUint8ArrayBase64Hex() {
14
14
 
15
15
  const supported = typeof Uint8Array.prototype.toBase64 === 'function'
16
16
 
17
+ test('环境支持检测', () => {
18
+ assert(supported, '环境不支持 Uint8Array Base64/Hex 方法')
19
+ })
20
+
17
21
  test('toBase64() —— Uint8Array 转 Base64 字符串', () => {
18
22
  if (!supported) { assert(true, '(跳过:环境不支持 Uint8Array.toBase64)'); return }
19
23
  // "Hello" → ASCII [72,101,108,108,111]
@@ -23,6 +23,10 @@ export function testJsonParseSource() {
23
23
  })
24
24
  } catch (e) { /* ignore */ }
25
25
 
26
+ test('环境支持检测', () => {
27
+ assert(supported, '环境不支持 JSON.parse source text access')
28
+ })
29
+
26
30
  test('reviver 接收第三个参数 context', () => {
27
31
  if (!supported) { assert(true, '(跳过:环境不支持 JSON.parse source text access)'); return }
28
32
  let receivedContext = null
@@ -15,6 +15,10 @@ export function testErrorIsError() {
15
15
 
16
16
  const supported = typeof Error.isError === 'function'
17
17
 
18
+ test('环境支持检测', () => {
19
+ assert(supported, '环境不支持 Error.isError')
20
+ })
21
+
18
22
  test('原生 Error 实例返回 true', () => {
19
23
  if (!supported) { assert(true, '(跳过:环境不支持 Error.isError)'); return }
20
24
  assert(Error.isError(new Error('test')) === true, 'new Error() 应返回 true')
@@ -15,6 +15,10 @@ export function testFloat16Array() {
15
15
 
16
16
  const supported = typeof Float16Array !== 'undefined'
17
17
 
18
+ test('环境支持检测', () => {
19
+ assert(supported, '环境不支持 Float16Array')
20
+ })
21
+
18
22
  test('Float16Array 可正常创建', () => {
19
23
  if (!supported) { assert(true, '(跳过:环境不支持 Float16Array)'); return }
20
24
  const arr = new Float16Array(4)
@@ -31,14 +35,6 @@ export function testFloat16Array() {
31
35
  assert(arr[3] === 0.0, 'arr[3] 应为 0.0')
32
36
  })
33
37
 
34
- test('精度低于 Float32(半精度特性)', () => {
35
- if (!supported) { assert(true, '(跳过)'); return }
36
- const arr = new Float16Array([Math.PI])
37
- // Float16 只有约 3.3 位十进制精度,Math.PI ≈ 3.140625(最近 float16 值)
38
- assert(Math.abs(arr[0] - Math.PI) > 0.001, 'Float16 精度应低于 Float64 的 Math.PI')
39
- assert(Math.abs(arr[0] - Math.PI) < 0.01, 'Float16 近似误差应在合理范围内')
40
- })
41
-
42
38
  test('Math.f16round() 舍入到最近 float16 值', () => {
43
39
  if (typeof Math.f16round !== 'function') { assert(true, '(跳过:环境不支持 Math.f16round)'); return }
44
40
  // 1.337 → float16 最近值约为 1.3369140625
@@ -15,6 +15,10 @@ export function testMathSumPrecise() {
15
15
 
16
16
  const supported = typeof Math.sumPrecise === 'function'
17
17
 
18
+ test('环境支持检测', () => {
19
+ assert(supported, '环境不支持 Math.sumPrecise')
20
+ })
21
+
18
22
  test('基本求和 —— 整数', () => {
19
23
  if (!supported) { assert(true, '(跳过:环境不支持 Math.sumPrecise)'); return }
20
24
  assert(Math.sumPrecise([1, 2, 3, 4, 5]) === 15, '整数求和应为 15')
@@ -16,6 +16,10 @@ export function testRegExpEscape() {
16
16
 
17
17
  const supported = typeof RegExp.escape === 'function'
18
18
 
19
+ test('环境支持检测', () => {
20
+ assert(supported, '环境不支持 RegExp.escape')
21
+ })
22
+
19
23
  test('转义正则特殊字符', () => {
20
24
  if (!supported) { assert(true, '(跳过:环境不支持 RegExp.escape)'); return }
21
25
  const special = '^$.*+?()[]{}|\\'
@@ -28,12 +32,12 @@ export function testRegExpEscape() {
28
32
  assert(escaped.includes('\\*'), '* 应被转义')
29
33
  })
30
34
 
31
- test('普通字符不被转义', () => {
32
- if (!supported) { assert(true, '(跳过)'); return }
33
- assert(RegExp.escape('hello') === 'hello', '纯字母不应被转义')
34
- assert(RegExp.escape('12345') === '12345', '纯数字不应被转义')
35
- assert(RegExp.escape('hello world') === 'hello world', '空格不应被转义')
36
- })
35
+ // test('普通字符不被转义', () => {
36
+ // if (!supported) { assert(true, '(跳过)'); return }
37
+ // assert(RegExp.escape('hello') === 'hello', '纯字母不应被转义')
38
+ // assert(RegExp.escape('12345') === '12345', '纯数字不应被转义')
39
+ // assert(RegExp.escape('hello world') === 'hello world', '空格不应被转义')
40
+ // })
37
41
 
38
42
  test('转义结果可安全构造正则', () => {
39
43
  if (!supported) { assert(true, '(跳过)'); return }
@@ -27,6 +27,10 @@ export async function testExplicitResourceManagement() {
27
27
  } catch { return false }
28
28
  })()
29
29
 
30
+ test('环境支持检测', () => {
31
+ assert(supported, '环境不支持 using / await using 语法')
32
+ })
33
+
30
34
  test('Symbol.dispose 已定义', () => {
31
35
  assert(typeof Symbol.dispose === 'symbol', 'Symbol.dispose 应是 symbol 类型')
32
36
  })
@@ -80,7 +84,7 @@ export async function testExplicitResourceManagement() {
80
84
  assert(order.join(',') === 'C,B,A', '多资源应按 LIFO(后进先出)顺序释放')
81
85
  })
82
86
 
83
- test('await using —— 异步 dispose', async () => {
87
+ await test('await using —— 异步 dispose', async () => {
84
88
  if (!supported) { assert(true, '(跳过)'); return }
85
89
  const log = []
86
90
  const fn = new Function('log', 'Symbol', `
@@ -16,6 +16,10 @@ export function testAtomicsPause() {
16
16
 
17
17
  const supported = typeof Atomics.pause === 'function'
18
18
 
19
+ test('环境支持检测', () => {
20
+ assert(supported, '环境不支持 Atomics.pause')
21
+ })
22
+
19
23
  test('Atomics.pause 函数存在', () => {
20
24
  if (!supported) { assert(true, '(跳过:环境不支持 Atomics.pause)'); return }
21
25
  assert(typeof Atomics.pause === 'function', 'Atomics.pause 应为函数')
@@ -26,7 +26,11 @@ export async function testImportAttributes() {
26
26
  } catch { return false }
27
27
  })()
28
28
 
29
- test('动态 import() 支持 with 选项对象', async () => {
29
+ test('环境支持检测', () => {
30
+ assert(syntaxSupported, '环境不支持 import with 语法')
31
+ })
32
+
33
+ await test('动态 import() 支持 with 选项对象', async () => {
30
34
  if (!syntaxSupported) { assert(true, '(跳过:环境不支持 import with 语法)'); return }
31
35
  // 使用 data: URL + type: javascript 测试动态导入属性
32
36
  let result = null
package/src/polyfills.js CHANGED
@@ -3,4 +3,4 @@
3
3
 
4
4
  // 引入完整的现代特性补丁(涵盖 ES2015 到最新的特性)
5
5
  import 'core-js/stable';
6
- import 'regenerator-runtime/runtime'; // 如果需要兼容生成器函数
6
+ import 'regenerator-runtime/runtime'; // 如果需要兼容生成器函数
@@ -8,8 +8,8 @@
8
8
  */
9
9
 
10
10
 
11
- // import 'kn-es-features/polyfills' // 运行时 API 补丁(如 Promise、Symbol)由消费方引入
12
- import { runAll2015, runAll2022, runAll2025, runAll2026 } from 'kn-es-features'
11
+ import 'kn-es-features/polyfills' // 运行时 API 补丁(如 Promise、Symbol)由消费方引入
12
+ import { runAll2015, runAll2022, runAll2025, runAll2026 } from 'kn-es-features/src'
13
13
 
14
14
  /* ── 版本配置 ───────────────────────────────────────────────────── */
15
15
  const VERSIONS = [
@@ -93,7 +93,7 @@ function renderCase(c) {
93
93
  return li
94
94
  }
95
95
 
96
- function renderSuite(suite) {
96
+ function renderSuite(suite, index) {
97
97
  let pass = 0, fail = 0
98
98
  suite.cases.forEach(c => c.status === 'pass' ? pass++ : fail++)
99
99
  const stateKey = fail === 0 ? 'pass' : 'fail'
@@ -106,7 +106,7 @@ function renderSuite(suite) {
106
106
  header.innerHTML =
107
107
  '<div class="suite__header-left">' +
108
108
  '<span class="suite__indicator suite__indicator--' + stateKey + '"></span>' +
109
- '<span class="suite__name">' + escape(suite.name) + '</span>' +
109
+ '<span class="suite__name">' + (index + 1) + ' - ' + escape(suite.name) + '</span>' +
110
110
  '</div>' +
111
111
  '<div class="suite__header-right">' +
112
112
  '<span class="suite__stat suite__stat--' + stateKey + '">' +
@@ -145,7 +145,7 @@ function renderPanel(panel, results) {
145
145
  return
146
146
  }
147
147
  const frag = document.createDocumentFragment()
148
- groupBySuite(results).forEach(s => frag.appendChild(renderSuite(s)))
148
+ groupBySuite(results).forEach((s,index) => frag.appendChild(renderSuite(s,index)))
149
149
  panel.appendChild(frag)
150
150
  }
151
151