mirror of
https://github.com/ikun0014/lx-music-mobile.git
synced 2025-07-04 23:48:54 +08:00
冻结运行环境内置的对象
This commit is contained in:
parent
44a3a37e0d
commit
1c99f40248
@ -1,3 +1,4 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
globalThis.lx_setup = (key, id, name, description, rawScript) => {
|
globalThis.lx_setup = (key, id, name, description, rawScript) => {
|
||||||
delete globalThis.setup
|
delete globalThis.setup
|
||||||
@ -37,7 +38,7 @@ globalThis.lx_setup = (key, id, name, description, rawScript) => {
|
|||||||
|
|
||||||
const callbacks = new Map()
|
const callbacks = new Map()
|
||||||
let timeoutId = 0
|
let timeoutId = 0
|
||||||
const setTimeout = (callback, timeout = 0, ...params) => {
|
const _setTimeout = (callback, timeout = 0, ...params) => {
|
||||||
if (typeof timeout !== 'number' || timeout < 0) throw new Error('timeout required number')
|
if (typeof timeout !== 'number' || timeout < 0) throw new Error('timeout required number')
|
||||||
if (timeoutId > 90000000000) throw new Error('max timeout')
|
if (timeoutId > 90000000000) throw new Error('max timeout')
|
||||||
const id = timeoutId++
|
const id = timeoutId++
|
||||||
@ -48,7 +49,7 @@ globalThis.lx_setup = (key, id, name, description, rawScript) => {
|
|||||||
set_timeout(id, parseInt(timeout))
|
set_timeout(id, parseInt(timeout))
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
const clearTimeout = (id) => {
|
const _clearTimeout = (id) => {
|
||||||
const tagret = callbacks.get(id)
|
const tagret = callbacks.get(id)
|
||||||
if (!tagret) return
|
if (!tagret) return
|
||||||
callbacks.delete(id)
|
callbacks.delete(id)
|
||||||
@ -113,11 +114,11 @@ globalThis.lx_setup = (key, id, name, description, rawScript) => {
|
|||||||
// 'utils.zlib.inflate': 'utils.zlib.inflate',
|
// 'utils.zlib.inflate': 'utils.zlib.inflate',
|
||||||
// 'utils.zlib.deflate': 'utils.zlib.deflate',
|
// 'utils.zlib.deflate': 'utils.zlib.deflate',
|
||||||
}
|
}
|
||||||
const EVENT_NAMES = Object.freeze({
|
const EVENT_NAMES = {
|
||||||
request: 'request',
|
request: 'request',
|
||||||
inited: 'inited',
|
inited: 'inited',
|
||||||
updateAlert: 'updateAlert',
|
updateAlert: 'updateAlert',
|
||||||
})
|
}
|
||||||
const eventNames = Object.values(EVENT_NAMES)
|
const eventNames = Object.values(EVENT_NAMES)
|
||||||
const events = {
|
const events = {
|
||||||
request: null,
|
request: null,
|
||||||
@ -299,7 +300,7 @@ globalThis.lx_setup = (key, id, name, description, rawScript) => {
|
|||||||
else if (Array.isArray(data) || ArrayBuffer.isView(data)) return utils.buffer.bufToString(data, 'base64')
|
else if (Array.isArray(data) || ArrayBuffer.isView(data)) return utils.buffer.bufToString(data, 'base64')
|
||||||
throw new Error('data type error: ' + typeof data + ' raw data: ' + data)
|
throw new Error('data type error: ' + typeof data + ' raw data: ' + data)
|
||||||
}
|
}
|
||||||
const utils = Object.freeze({
|
const utils = {
|
||||||
crypto: {
|
crypto: {
|
||||||
aesEncrypt(buffer, mode, key, iv) {
|
aesEncrypt(buffer, mode, key, iv) {
|
||||||
// console.log('aesEncrypt', buffer, mode, key, iv)
|
// console.log('aesEncrypt', buffer, mode, key, iv)
|
||||||
@ -391,117 +392,130 @@ globalThis.lx_setup = (key, id, name, description, rawScript) => {
|
|||||||
// })
|
// })
|
||||||
// })
|
// })
|
||||||
// },
|
// },
|
||||||
// },
|
// }),
|
||||||
})
|
}
|
||||||
Object.defineProperty(globalThis, 'lx', {
|
|
||||||
configurable: false,
|
|
||||||
writable: false,
|
|
||||||
value: Object.freeze({
|
|
||||||
EVENT_NAMES,
|
|
||||||
request(url, { method = 'get', timeout, headers, body, form, formData, binary }, callback) {
|
|
||||||
let options = { headers, binary: binary === true }
|
|
||||||
// let data
|
|
||||||
// if (body) {
|
|
||||||
// data = body
|
|
||||||
// } else if (form) {
|
|
||||||
// data = form
|
|
||||||
// // data.content_type = 'application/x-www-form-urlencoded'
|
|
||||||
// options.json = false
|
|
||||||
// } else if (formData) {
|
|
||||||
// data = formData
|
|
||||||
// // data.content_type = 'multipart/form-data'
|
|
||||||
// options.json = false
|
|
||||||
// }
|
|
||||||
if (timeout && typeof timeout == 'number') options.timeout = Math.min(options.timeout, 60_000)
|
|
||||||
|
|
||||||
let request = sendNativeRequest(url, { method, body, form, formData, ...options }, (err, resp) => {
|
globalThis.lx = {
|
||||||
callback(err, {
|
EVENT_NAMES,
|
||||||
statusCode: resp.statusCode,
|
request(url, { method = 'get', timeout, headers, body, form, formData, binary }, callback) {
|
||||||
statusMessage: resp.statusMessage,
|
let options = { headers, binary: binary === true }
|
||||||
headers: resp.headers,
|
// let data
|
||||||
// bytes: resp.bytes,
|
// if (body) {
|
||||||
// raw: resp.raw,
|
// data = body
|
||||||
body: resp.body,
|
// } else if (form) {
|
||||||
}, resp.body)
|
// data = form
|
||||||
})
|
// // data.content_type = 'application/x-www-form-urlencoded'
|
||||||
|
// options.json = false
|
||||||
|
// } else if (formData) {
|
||||||
|
// data = formData
|
||||||
|
// // data.content_type = 'multipart/form-data'
|
||||||
|
// options.json = false
|
||||||
|
// }
|
||||||
|
if (timeout && typeof timeout == 'number') options.timeout = Math.min(options.timeout, 60_000)
|
||||||
|
|
||||||
return () => {
|
let request = sendNativeRequest(url, { method, body, form, formData, ...options }, (err, resp) => {
|
||||||
if (!request.aborted) request.abort()
|
callback(err, {
|
||||||
request = null
|
statusCode: resp.statusCode,
|
||||||
}
|
statusMessage: resp.statusMessage,
|
||||||
},
|
headers: resp.headers,
|
||||||
send(eventName, data) {
|
// bytes: resp.bytes,
|
||||||
return new Promise((resolve, reject) => {
|
// raw: resp.raw,
|
||||||
if (!eventNames.includes(eventName)) return reject(new Error('The event is not supported: ' + eventName))
|
body: resp.body,
|
||||||
switch (eventName) {
|
}, resp.body)
|
||||||
case EVENT_NAMES.inited:
|
})
|
||||||
if (isInitedApi) return reject(new Error('Script is inited'))
|
|
||||||
isInitedApi = true
|
return () => {
|
||||||
handleInit(data)
|
if (!request.aborted) request.abort()
|
||||||
resolve()
|
request = null
|
||||||
break
|
}
|
||||||
case EVENT_NAMES.updateAlert:
|
},
|
||||||
if (isShowedUpdateAlert) return reject(new Error('The update alert can only be called once.'))
|
send(eventName, data) {
|
||||||
isShowedUpdateAlert = true
|
return new Promise((resolve, reject) => {
|
||||||
handleShowUpdateAlert(data, resolve, reject)
|
if (!eventNames.includes(eventName)) return reject(new Error('The event is not supported: ' + eventName))
|
||||||
break
|
|
||||||
default:
|
|
||||||
reject(new Error('Unknown event name: ' + eventName))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
on(eventName, handler) {
|
|
||||||
if (!eventNames.includes(eventName)) return Promise.reject(new Error('The event is not supported: ' + eventName))
|
|
||||||
switch (eventName) {
|
switch (eventName) {
|
||||||
case EVENT_NAMES.request:
|
case EVENT_NAMES.inited:
|
||||||
events.request = handler
|
if (isInitedApi) return reject(new Error('Script is inited'))
|
||||||
|
isInitedApi = true
|
||||||
|
handleInit(data)
|
||||||
|
resolve()
|
||||||
break
|
break
|
||||||
default: return Promise.reject(new Error('The event is not supported: ' + eventName))
|
case EVENT_NAMES.updateAlert:
|
||||||
|
if (isShowedUpdateAlert) return reject(new Error('The update alert can only be called once.'))
|
||||||
|
isShowedUpdateAlert = true
|
||||||
|
handleShowUpdateAlert(data, resolve, reject)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
reject(new Error('Unknown event name: ' + eventName))
|
||||||
}
|
}
|
||||||
return Promise.resolve()
|
})
|
||||||
},
|
},
|
||||||
utils,
|
on(eventName, handler) {
|
||||||
currentScriptInfo: Object.freeze({
|
if (!eventNames.includes(eventName)) return Promise.reject(new Error('The event is not supported: ' + eventName))
|
||||||
name,
|
switch (eventName) {
|
||||||
description,
|
case EVENT_NAMES.request:
|
||||||
}),
|
events.request = handler
|
||||||
version: '1.0.0',
|
break
|
||||||
env: 'mobile',
|
default: return Promise.reject(new Error('The event is not supported: ' + eventName))
|
||||||
}),
|
}
|
||||||
})
|
return Promise.resolve()
|
||||||
|
},
|
||||||
|
utils,
|
||||||
|
currentScriptInfo: {
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
},
|
||||||
|
version: '1.0.0',
|
||||||
|
env: 'mobile',
|
||||||
|
}
|
||||||
|
|
||||||
|
globalThis.setTimeout = _setTimeout
|
||||||
|
globalThis.clearTimeout = _clearTimeout
|
||||||
|
globalThis.window = globalThis
|
||||||
|
globalThis.document = {
|
||||||
|
getElementsByTagName(name) {
|
||||||
|
if (name == 'script') {
|
||||||
|
return [
|
||||||
|
Object.freeze({
|
||||||
|
innerText: rawScript,
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
Object.defineProperty(globalThis, 'setTimeout', {
|
const _toString = Function.prototype.toString
|
||||||
configurable: false,
|
// eslint-disable-next-line no-extend-native
|
||||||
writable: false,
|
Function.prototype.toString = function() {
|
||||||
value: setTimeout,
|
return Object.getOwnPropertyDescriptors(this).name.configurable
|
||||||
})
|
? _toString.apply(this)
|
||||||
Object.defineProperty(globalThis, 'clearTimeout', {
|
: `function ${this.name}() { [native code] }`
|
||||||
configurable: false,
|
}
|
||||||
writable: false,
|
|
||||||
value: clearTimeout,
|
const excludes = [
|
||||||
})
|
Function.prototype.toString,
|
||||||
Object.defineProperty(globalThis, 'window', {
|
Function.prototype.toLocaleString,
|
||||||
configurable: false,
|
Object.prototype.toString,
|
||||||
writable: false,
|
]
|
||||||
value: globalThis,
|
const freezeObject = (obj, freezedObj = new Set()) => {
|
||||||
})
|
if (obj == null) return
|
||||||
Object.defineProperty(globalThis, 'document', {
|
switch (typeof obj) {
|
||||||
configurable: false,
|
case 'object':
|
||||||
writable: false,
|
case 'function':
|
||||||
value: Object.freeze({
|
if (freezedObj.has(obj)) return
|
||||||
getElementsByTagName(name) {
|
// Object.freeze(obj)
|
||||||
if (name == 'script') {
|
freezedObj.add(obj)
|
||||||
return [
|
for (const [name, { ...config }] of Object.entries(Object.getOwnPropertyDescriptors(obj))) {
|
||||||
Object.freeze({
|
if (!excludes.includes(config.value)) {
|
||||||
innerText: rawScript,
|
if (config.writable) config.writable = false
|
||||||
}),
|
if (config.configurable) config.configurable = false
|
||||||
]
|
Object.defineProperty(obj, name, config)
|
||||||
|
}
|
||||||
|
freezeObject(config.value, freezedObj)
|
||||||
}
|
}
|
||||||
return null
|
}
|
||||||
},
|
}
|
||||||
}),
|
freezeObject(globalThis)
|
||||||
})
|
|
||||||
|
|
||||||
console.log('Preload finished.')
|
console.log('Preload finished.')
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user