kn-es-features 1.0.0 → 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 (34) hide show
  1. package/dist/esfeatures.iife.js +11 -14
  2. package/dist/esfeatures.js +1592 -2278
  3. package/dist/esfeatures.umd.cjs +11 -14
  4. package/dist/polyfills.iife.js +7 -7
  5. package/package.json +7 -3
  6. package/src/features/es2015/01-let-const.js +0 -33
  7. package/src/features/es2015/02-arrow-functions.js +0 -56
  8. package/src/features/es2015/03-template-literals.js +0 -38
  9. package/src/features/es2015/04-destructuring.js +0 -51
  10. package/src/features/es2015/05-default-rest-spread.js +0 -74
  11. package/src/features/es2015/08-symbols.js +0 -71
  12. package/src/features/es2015/09-iterators-generators.js +0 -71
  13. package/src/features/es2015/10-map-set.js +1 -86
  14. package/src/features/es2015/11-proxy-reflect.js +1 -84
  15. package/src/features/es2015/12-enhanced-objects.js +0 -80
  16. package/src/features/es2015/16-for-of.js +0 -33
  17. package/src/features/es2015/17-map.js +0 -46
  18. package/src/features/es2022/06-regexp-d-flag.js +4 -0
  19. package/src/features/es2022/07-top-level-await.js +6 -6
  20. package/src/features/es2025/01-iterator-helpers.js +4 -0
  21. package/src/features/es2025/02-set-methods.js +5 -1
  22. package/src/features/es2025/03-promise-try.js +15 -7
  23. package/src/features/es2025/04-regexp-duplicate-groups.js +4 -0
  24. package/src/features/es2025/05-uint8array-base64-hex.js +4 -0
  25. package/src/features/es2025/06-json-parse-source.js +4 -0
  26. package/src/features/es2025/07-error-is-error.js +4 -0
  27. package/src/features/es2025/08-float16array.js +4 -8
  28. package/src/features/es2026/01-math-sum-precise.js +4 -0
  29. package/src/features/es2026/02-regexp-escape.js +10 -6
  30. package/src/features/es2026/03-explicit-resource-management.js +5 -1
  31. package/src/features/es2026/04-atomics-pause.js +4 -0
  32. package/src/features/es2026/05-import-attributes.js +11 -4
  33. package/src/polyfills.js +1 -1
  34. package/src/validate-main.js +223 -0
@@ -0,0 +1,223 @@
1
+ /**
2
+ * validate-main.js —— npm 包校验入口
3
+ *
4
+ * 通过 ESM 命名导入使用 kn-es-features,校验以下内容:
5
+ * 1. 包的 ESM 导出路径可正常解析
6
+ * 2. runAll2015 / runAll2022 / runAll2025 / runAll2026 函数均可调用
7
+ * 3. 返回结果符合预期格式 [{ suite, case, status, error? }]
8
+ */
9
+
10
+
11
+ import 'kn-es-features/polyfills' // 运行时 API 补丁(如 Promise、Symbol)由消费方引入
12
+ import { runAll2015, runAll2022, runAll2025, runAll2026 } from 'kn-es-features/src'
13
+
14
+ /* ── 版本配置 ───────────────────────────────────────────────────── */
15
+ const VERSIONS = [
16
+ { key: '2015', run: () => runAll2015() },
17
+ { key: '2022', run: () => runAll2022() },
18
+ { key: '2025', run: () => runAll2025() },
19
+ { key: '2026', run: () => runAll2026() },
20
+ ]
21
+
22
+ /* ── DOM 引用 ────────────────────────────────────────────────────── */
23
+ const btnRun = document.getElementById('btn-run')
24
+ const tabs = document.querySelectorAll('.tab')
25
+
26
+ /* ── Tab 切换 ────────────────────────────────────────────────────── */
27
+ tabs.forEach(tab => {
28
+ tab.addEventListener('click', () => {
29
+ tabs.forEach(t => t.classList.remove('tab--active'))
30
+ tab.classList.add('tab--active')
31
+ document.querySelectorAll('.panel').forEach(p => p.classList.remove('panel--active'))
32
+ document.getElementById(tab.dataset.panel).classList.add('panel--active')
33
+ })
34
+ })
35
+
36
+ /* ── 工具函数 ────────────────────────────────────────────────────── */
37
+
38
+ function escape(str) {
39
+ return String(str)
40
+ .replace(/&/g, '&')
41
+ .replace(/</g, '&lt;')
42
+ .replace(/>/g, '&gt;')
43
+ .replace(/"/g, '&quot;')
44
+ }
45
+
46
+ function groupBySuite(results) {
47
+ const suites = []
48
+ const map = Object.create(null)
49
+ results.forEach(r => {
50
+ if (!map[r.suite]) {
51
+ const s = { name: r.suite, cases: [] }
52
+ map[r.suite] = s
53
+ suites.push(s)
54
+ }
55
+ map[r.suite].cases.push(r)
56
+ })
57
+ return suites
58
+ }
59
+
60
+ function calcStats(results) {
61
+ let pass = 0, fail = 0
62
+ results.forEach(r => r.status === 'pass' ? pass++ : fail++)
63
+ return { pass, fail, total: results.length }
64
+ }
65
+
66
+ /* ── 渲染函数 ────────────────────────────────────────────────────── */
67
+
68
+ function renderCase(c) {
69
+ const li = document.createElement('li')
70
+ li.className = 'case case--' + c.status
71
+
72
+ const icon = document.createElement('span')
73
+ icon.className = 'case__icon'
74
+ icon.textContent = c.status === 'pass' ? '✓' : '✗'
75
+
76
+ const body = document.createElement('span')
77
+ body.className = 'case__body'
78
+
79
+ const name = document.createElement('span')
80
+ name.className = 'case__name'
81
+ name.textContent = c.case
82
+ body.appendChild(name)
83
+
84
+ if (c.error) {
85
+ const err = document.createElement('span')
86
+ err.className = 'case__error'
87
+ err.textContent = c.error
88
+ body.appendChild(err)
89
+ }
90
+
91
+ li.appendChild(icon)
92
+ li.appendChild(body)
93
+ return li
94
+ }
95
+
96
+ function renderSuite(suite, index) {
97
+ let pass = 0, fail = 0
98
+ suite.cases.forEach(c => c.status === 'pass' ? pass++ : fail++)
99
+ const stateKey = fail === 0 ? 'pass' : 'fail'
100
+
101
+ const card = document.createElement('div')
102
+ card.className = 'suite'
103
+
104
+ const header = document.createElement('div')
105
+ header.className = 'suite__header'
106
+ header.innerHTML =
107
+ '<div class="suite__header-left">' +
108
+ '<span class="suite__indicator suite__indicator--' + stateKey + '"></span>' +
109
+ '<span class="suite__name">' + (index + 1) + ' - ' + escape(suite.name) + '</span>' +
110
+ '</div>' +
111
+ '<div class="suite__header-right">' +
112
+ '<span class="suite__stat suite__stat--' + stateKey + '">' +
113
+ pass + ' / ' + suite.cases.length +
114
+ '</span>' +
115
+ '<span class="suite__chevron">▾</span>' +
116
+ '</div>'
117
+
118
+ header.addEventListener('click', () => card.classList.toggle('suite--collapsed'))
119
+
120
+ const ul = document.createElement('ul')
121
+ ul.className = 'suite__cases'
122
+ suite.cases.forEach(c => ul.appendChild(renderCase(c)))
123
+
124
+ card.appendChild(header)
125
+ card.appendChild(ul)
126
+ return card
127
+ }
128
+
129
+ function showLoader(panel) {
130
+ panel.innerHTML =
131
+ '<div class="loader">' +
132
+ '<span class="loader__spinner"></span>' +
133
+ '<span>正在运行测试…</span>' +
134
+ '</div>'
135
+ }
136
+
137
+ function renderPanel(panel, results) {
138
+ panel.innerHTML = ''
139
+ if (!results || results.length === 0) {
140
+ panel.innerHTML =
141
+ '<div class="placeholder">' +
142
+ '<span class="placeholder__icon">📭</span>' +
143
+ '<p class="placeholder__text">暂无测试结果</p>' +
144
+ '</div>'
145
+ return
146
+ }
147
+ const frag = document.createDocumentFragment()
148
+ groupBySuite(results).forEach((s,index) => frag.appendChild(renderSuite(s,index)))
149
+ panel.appendChild(frag)
150
+ }
151
+
152
+ function updateSummaryValue(id, stats) {
153
+ const el = document.getElementById('val-' + id)
154
+ if (!el) return
155
+ if (!stats) { el.textContent = '—'; el.className = 'summary__value'; return }
156
+ el.textContent = stats.pass + ' / ' + stats.total
157
+ el.className = 'summary__value summary__value--' + (stats.fail === 0 ? 'pass' : 'fail')
158
+ }
159
+
160
+ function updateTabBadge(id, stats) {
161
+ const el = document.getElementById('badge-' + id)
162
+ if (!el) return
163
+ if (!stats) { el.textContent = ''; el.className = 'tab__badge'; return }
164
+ if (stats.fail === 0) {
165
+ el.textContent = '全部通过'
166
+ el.className = 'tab__badge tab__badge--pass'
167
+ } else {
168
+ el.textContent = stats.fail + ' 失败'
169
+ el.className = 'tab__badge tab__badge--fail'
170
+ }
171
+ }
172
+
173
+ /* ── 主运行流程 ──────────────────────────────────────────────────── */
174
+ async function runTests() {
175
+ btnRun.disabled = true
176
+ btnRun.classList.add('btn-run--running')
177
+ btnRun.querySelector('.btn-run__label').textContent = '运行中…'
178
+
179
+ VERSIONS.forEach(v => {
180
+ updateSummaryValue(v.key, null)
181
+ updateTabBadge(v.key, null)
182
+ showLoader(document.getElementById('panel-' + v.key))
183
+ })
184
+ updateSummaryValue('total', null)
185
+
186
+ try {
187
+ const resultSets = await Promise.all(VERSIONS.map(v => v.run()))
188
+
189
+ let totalPass = 0, totalFail = 0, totalCount = 0
190
+
191
+ VERSIONS.forEach((v, i) => {
192
+ const results = resultSets[i]
193
+ const stats = calcStats(results)
194
+ renderPanel(document.getElementById('panel-' + v.key), results)
195
+ updateSummaryValue(v.key, stats)
196
+ updateTabBadge(v.key, stats)
197
+ totalPass += stats.pass
198
+ totalFail += stats.fail
199
+ totalCount += stats.total
200
+ })
201
+
202
+ updateSummaryValue('total', { pass: totalPass, fail: totalFail, total: totalCount })
203
+
204
+ } catch (err) {
205
+ VERSIONS.forEach(v => {
206
+ const panel = document.getElementById('panel-' + v.key)
207
+ if (panel) {
208
+ panel.innerHTML =
209
+ '<div class="placeholder">' +
210
+ '<span class="placeholder__icon">⚠️</span>' +
211
+ '<p class="placeholder__text">运行出错:' + escape(err.message) + '</p>' +
212
+ '</div>'
213
+ }
214
+ })
215
+ console.error('[kn-es-features 校验]', err)
216
+ }
217
+
218
+ btnRun.disabled = false
219
+ btnRun.classList.remove('btn-run--running')
220
+ btnRun.querySelector('.btn-run__label').textContent = '重新运行'
221
+ }
222
+
223
+ btnRun.addEventListener('click', runTests)