mirror of
https://github.com/iflytek/skillhub.git
synced 2026-08-28 11:25:00 +00:00
Merge pull request #414 from iflytek/fix/web-js-compat
fix(web): restore compatibility with Chromium 83 (Debian 10)
This commit is contained in:
commit
ab6fd07530
4 changed files with 104 additions and 8 deletions
4
web/.browserslistrc
Normal file
4
web/.browserslistrc
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
Chrome >= 83
|
||||
Edge >= 83
|
||||
Firefox >= 78
|
||||
Safari >= 14
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
* Deployments inject `/runtime-config.js` at startup, and this file guarantees the app sees either
|
||||
* that config or a safe fallback object before importing the main entry.
|
||||
*/
|
||||
import './legacy-polyfills'
|
||||
async function loadRuntimeConfig() {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const script = document.createElement('script')
|
||||
|
|
@ -16,14 +17,16 @@ async function loadRuntimeConfig() {
|
|||
}
|
||||
|
||||
function ensureRuntimeConfigFallback() {
|
||||
window.__SKILLHUB_RUNTIME_CONFIG__ ??= {
|
||||
apiBaseUrl: '',
|
||||
appBaseUrl: '',
|
||||
authDirectEnabled: 'false',
|
||||
authDirectProvider: '',
|
||||
authSessionBootstrapEnabled: 'false',
|
||||
authSessionBootstrapProvider: '',
|
||||
authSessionBootstrapAuto: 'false',
|
||||
if (!window.__SKILLHUB_RUNTIME_CONFIG__) {
|
||||
window.__SKILLHUB_RUNTIME_CONFIG__ = {
|
||||
apiBaseUrl: '',
|
||||
appBaseUrl: '',
|
||||
authDirectEnabled: 'false',
|
||||
authDirectProvider: '',
|
||||
authSessionBootstrapEnabled: 'false',
|
||||
authSessionBootstrapProvider: '',
|
||||
authSessionBootstrapAuto: 'false',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
78
web/src/legacy-polyfills.ts
Normal file
78
web/src/legacy-polyfills.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* Polyfills for older browsers (e.g. Chromium 83 on Debian 10) that lack a few
|
||||
* ES2021+ runtime methods used by bundled dependencies. esbuild only transpiles
|
||||
* syntax, not runtime APIs, so we patch the prototypes here before any other
|
||||
* module runs.
|
||||
*
|
||||
* TypeScript's lib target is ES2020, so the methods we patch are referenced via
|
||||
* string keys / loose casts to avoid compile-time type errors.
|
||||
*/
|
||||
|
||||
type AnyStringReplacer = (substring: string, ...args: unknown[]) => string
|
||||
|
||||
const StringProto = String.prototype as unknown as Record<string, unknown>
|
||||
const ArrayProto = Array.prototype as unknown as Record<string, unknown>
|
||||
const ObjectCtor = Object as unknown as Record<string, unknown>
|
||||
|
||||
if (typeof StringProto.replaceAll !== 'function') {
|
||||
Object.defineProperty(String.prototype, 'replaceAll', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: function replaceAll(
|
||||
this: string,
|
||||
search: string | RegExp,
|
||||
replacement: string | AnyStringReplacer,
|
||||
): string {
|
||||
if (search instanceof RegExp) {
|
||||
if (!search.flags.includes('g')) {
|
||||
throw new TypeError('String.prototype.replaceAll called with a non-global RegExp argument')
|
||||
}
|
||||
return this.replace(search, replacement as string)
|
||||
}
|
||||
const needle = String(search)
|
||||
if (needle === '') {
|
||||
return this.replace(new RegExp('', 'g'), replacement as string)
|
||||
}
|
||||
const escaped = needle.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&')
|
||||
return this.replace(new RegExp(escaped, 'g'), replacement as string)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof ArrayProto.at !== 'function') {
|
||||
Object.defineProperty(Array.prototype, 'at', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: function at(this: unknown[], index: number) {
|
||||
const len = this.length
|
||||
const i = Math.trunc(index) || 0
|
||||
const resolved = i < 0 ? len + i : i
|
||||
if (resolved < 0 || resolved >= len) return undefined
|
||||
return this[resolved]
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof StringProto.at !== 'function') {
|
||||
Object.defineProperty(String.prototype, 'at', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: function at(this: string, index: number) {
|
||||
const len = this.length
|
||||
const i = Math.trunc(index) || 0
|
||||
const resolved = i < 0 ? len + i : i
|
||||
if (resolved < 0 || resolved >= len) return undefined
|
||||
return this.charAt(resolved)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof ObjectCtor.hasOwn !== 'function') {
|
||||
Object.defineProperty(Object, 'hasOwn', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: function hasOwn(target: object, property: PropertyKey) {
|
||||
return Object.prototype.hasOwnProperty.call(target, property)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ import { defineConfig } from 'vite'
|
|||
import react from '@vitejs/plugin-react'
|
||||
import path from 'path'
|
||||
|
||||
const LEGACY_BROWSER_TARGETS = ['chrome83', 'edge83', 'firefox78', 'safari14']
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
resolve: {
|
||||
|
|
@ -9,6 +11,15 @@ export default defineConfig({
|
|||
'@': path.resolve(__dirname, './src'),
|
||||
},
|
||||
},
|
||||
build: {
|
||||
target: LEGACY_BROWSER_TARGETS,
|
||||
cssTarget: LEGACY_BROWSER_TARGETS,
|
||||
},
|
||||
optimizeDeps: {
|
||||
esbuildOptions: {
|
||||
target: LEGACY_BROWSER_TARGETS,
|
||||
},
|
||||
},
|
||||
test: {
|
||||
exclude: ['**/node_modules/**', '**/e2e/**'],
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue