как я написал свой eval()
goTo(5, 0)
.then(() => attack())
.then(() => goTo(5, 0))
.then(() => attack())
await goTo(5, 0)
await attack()
await goTo(5, 0)
await attack()
goTo(5, 0)
attack()
goTo(5, 0)
attack()
const worker = new Worker('script.js')
setTimeout(() => worker.close(), 1000)
onmessage = (message) => {
postMessage(message)
}
const customCode = 'attack()'
const blob = new Blob([customCode], {...})
const codeUrl = URL.createObjectURL(blob)
const worker = new Worker(codeUrl)
setTimeout(() => worker.terminate(), 1000)
const message$ = fromEvent(worker, 'message')
.pipe(map(e => JSON.parse(e.data)))
const timeoutClose$ = timer(1000).pipe(
takeUntil(message$),
switchMap(() => throwError(`to much time!`))
);
merge(timeoutClose$, message$)
.pipe(
map(e => e.data),
finalize(() => worker.terminate()),
catchError(error => {
reject(error)
return []
})
)
.subscribe(success => {
resolve(success)
})
goTo(5, 0)
for(i = 0; i < 10; i++) {
shoot(unitId)
}
with(unitApi) {
goTo(5, 0)
for(i = 0; i < 10; i++) {
shoot(unitId)
}
}
with({foo: 'bar'}) {
foo
}
'foo' in obj
? obj.foo
: global.foo
const safeApi = new Proxy(unitApi, {
has: () => true
})
with(safeApi) {
${userCode}
}
with ([1, 2, 3]) {
filter(i => i !== 3)
.some(i => i === 3)
}
// false
with ({hello: 'HolyJS'}) {
valueOf()
}
// {hello: 'HolyJS'}
const safeApi = new Proxy(unitApi, {
has: () => true,
get: (target, key) =>
key === Symbol.unscopables ? undefined : target[key]
})
const nativePostMessage = this.postMessage;
Object.keys(this).forEach(key => {
delete this[key]
}
with (sandboxProxy) {
(function() {
${USER_CODE}
}).call({"hi": '=)'})
}
const apis = {console, Math, parseInt, ...}
const unitApi = Object.assign(unitApi, apis)
const sandboxProxy = new Proxy(unitApi, {has, get})
with (sandboxProxy) {
try {
${USER_CODE}
} catch (e) {
console.error(e)
}
}
['log', 'info', 'warn', 'error'].forEach(patchMethod);
with (sandboxProxy) {
try {
${USER_CODE}
} catch (e) {
console.error(e)
}
}
function patchMethod(name) {
const nativeMethod = console[name].bind(console);
console[name] = (...data) => {
attributes = attributes.map(parseParams)
postMessage(JSON.stringify({type: name, data}))
}
}
goTo(x, y) {
return {type: 'goTo', x, y}
}
actions = [
{type: 'goTo', x, y},
{type: 'shoot', id},
{type: 'goTo', x, y}
]
const ids = ['IE', 'DART', 'EVAL'];
for(i = 0; i < 10; i++) {
shoot(ids[(ids.length * Math.random())|0])
}
(ids.length * Math.random())|0
1
(ids.length * Math.random())|0
3
(ids.length * Math.random())|0
2
// LCG – Линейный конгруэнтный метод
function LCG(seed) {
return function() {
seed = Math.imul(16807, seed) | 0 % 2147483647
return (seed & 2147483647) / 2147483648
}
}
const getRandomSalt = (seed) =>
[...seed].reduce((acc, curr) =>
acc + curr.charCodeAt(0), 0) % 2147483647
const salt = getRandomSalt(userCode)
Math.random = LCG(salt)
leftIsReady$ = socket$.pipe(filter(...))
rightIsReady$ = socket$.pipe(filter(...))
forkJoin(leftIsReady$, rightIsReady$)
.subscribe(() => {
this.setState({mode: 'ready'})
})
class LeftPlayer extends Client {}
class RightPlayer extends Client {}
class Watcher extends Client {}
class Admin extends Client {}
class Client {
connections = new Set()
onUnsafeMessage$ = new Subject()
}
class LeftPlayer extends Client {
get onMessage$() {
return this.onUnsafeMessage$
.pipe(
filter(query => query.type === 'state'),
map(state => ({left: state.left}))
)
}
class Room {
onState$ = this.clients.onMessage$
.pipe(filter(query => query.type === 'state'))
constructor() {
this.onState$.subscribe(state =>
this.setState(state))
}
rightArmyChanges$ = socket$.pipe(
filter(state => !!state.right),
pluck('right', 'army')
)
.subscribe(enemyArmy => {
this.setState({right: {army: enemyArmy}})
})
rightArmyChanges$
.subscribe(army => this.setRightArmy(army))
rightNameChanges$
.subscribe(name => this.setRightName(name))