mirror of
https://github.com/leporello-js/leporello-js
synced 2026-01-13 13:04:30 -08:00
WIP
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
//import {ethers} from 'https://unpkg.com/ethers/dist/ethers.js'
|
||||
import {ethers} from 'https://unpkg.com/ethers@5.7.2/dist/ethers.esm.js'
|
||||
|
||||
/*
|
||||
const URL = 'https://ethereum-goerli-rpc.allthatnode.com'
|
||||
|
||||
const p = ethers.getDefaultProvider(URL)
|
||||
@@ -12,7 +11,7 @@ const latest = await p.getBlock()
|
||||
latest
|
||||
|
||||
|
||||
const txs = await Promise.all(latest.transactions.slice(0,2).map(t =>
|
||||
const txs = await Promise.all(latest.transactions.map(t =>
|
||||
p.getTransactionReceipt(t)
|
||||
))
|
||||
|
||||
@@ -23,7 +22,7 @@ const totalGas = txs.reduce((gas,tx) =>
|
||||
|
||||
|
||||
|
||||
totalGas.add(20)
|
||||
totalGas.add(21)
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
import {set_record_call} from './runtime.js'
|
||||
|
||||
const get_object_to_patch = (cxt, path) => {
|
||||
// Modify window object on module load
|
||||
// TODO check - if modules reloaded on window reopen
|
||||
// TODO - cxt.window
|
||||
apply_io_patches()
|
||||
|
||||
// Current context for current execution of code
|
||||
let cxt
|
||||
|
||||
export const set_current_context = _cxt => {
|
||||
cxt = _cxt
|
||||
}
|
||||
|
||||
const io_patch = (path, use_context = false) => {
|
||||
let obj = cxt.window
|
||||
for(let i = 0; i < path.length - 1; i++) {
|
||||
obj = obj[path[i]]
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
const io_patch = (cxt, path, use_context = false) => {
|
||||
const obj = get_object_to_patch(cxt, path)
|
||||
const method = path.at(-1)
|
||||
if(obj == null || obj[method] == null) {
|
||||
// Method is absent in current env, skip patching
|
||||
@@ -202,69 +209,40 @@ const io_patch = (cxt, path, use_context = false) => {
|
||||
obj[method].__original = original
|
||||
}
|
||||
|
||||
const io_patch_remove = (cxt, path) => {
|
||||
const obj = get_object_to_patch(cxt, path)
|
||||
const method = path.at(-1)
|
||||
if(obj == null || obj[method] == null) {
|
||||
// Method is absent in current env, skip patching
|
||||
return
|
||||
}
|
||||
|
||||
obj[method] = obj[method].__original
|
||||
}
|
||||
|
||||
const Response_methods = [
|
||||
'arrayBuffer',
|
||||
'blob',
|
||||
'formData',
|
||||
'json',
|
||||
'text',
|
||||
]
|
||||
|
||||
// TODO bare IO functions should not be exposed at all, to allow calling it
|
||||
// only from patched versions. Especially setInterval which can cause leaks
|
||||
export const apply_io_patches = cxt => {
|
||||
io_patch(cxt, ['Math', 'random'])
|
||||
export const apply_io_patches = () => {
|
||||
io_patch(['Math', 'random'])
|
||||
|
||||
io_patch(cxt, ['setTimeout'])
|
||||
io_patch(['setTimeout'])
|
||||
// TODO if call setTimeout and then clearTimeout, cache it and remove call of
|
||||
// clearTimeout, and make only setTimeout, then it would never be called when
|
||||
// replaying from cache
|
||||
io_patch(cxt, ['clearTimeout'])
|
||||
io_patch(['clearTimeout'])
|
||||
|
||||
|
||||
// TODO patch setInterval to only cleanup all intervals on finish
|
||||
|
||||
const Date = cxt.window.Date
|
||||
io_patch(cxt, ['Date'])
|
||||
io_patch(['Date'])
|
||||
cxt.window.Date.parse = Date.parse
|
||||
cxt.window.Date.now = Date.now
|
||||
cxt.window.Date.UTC = Date.UTC
|
||||
io_patch(cxt, ['Date', 'now'])
|
||||
io_patch(['Date', 'now'])
|
||||
|
||||
|
||||
io_patch(cxt, ['fetch'])
|
||||
io_patch(['fetch'])
|
||||
// Check if Response is defined, for node.js
|
||||
if(cxt.window.Response != null) {
|
||||
const Response_methods = [
|
||||
'arrayBuffer',
|
||||
'blob',
|
||||
'formData',
|
||||
'json',
|
||||
'text',
|
||||
]
|
||||
for(let key of Response_methods) {
|
||||
io_patch(cxt, ['Response', 'prototype', key], true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const remove_io_patches = cxt => {
|
||||
io_patch_remove(cxt, ['Math', 'random'])
|
||||
|
||||
io_patch_remove(cxt, ['setTimeout'])
|
||||
io_patch_remove(cxt, ['clearTimeout'])
|
||||
|
||||
io_patch_remove(cxt, ['Date'])
|
||||
io_patch_remove(cxt, ['fetch'])
|
||||
|
||||
// Check if Response is defined, for node.js
|
||||
if(cxt.window.Response != null) {
|
||||
for(let key of Response_methods) {
|
||||
io_patch_remove(cxt, ['Response', 'prototype', key])
|
||||
io_patch(['Response', 'prototype', key], true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {apply_io_patches, remove_io_patches} from './record_io.js'
|
||||
import {set_current_context} from './record_io.js'
|
||||
|
||||
/*
|
||||
Converts generator-returning function to promise-returning function. Allows to
|
||||
@@ -50,7 +50,7 @@ const do_run = function*(module_fns, cxt, io_cache){
|
||||
}
|
||||
|
||||
apply_promise_patch(cxt)
|
||||
apply_io_patches(cxt)
|
||||
set_current_context(cxt)
|
||||
|
||||
for(let {module, fn} of module_fns) {
|
||||
cxt.found_call = null
|
||||
@@ -80,7 +80,6 @@ const do_run = function*(module_fns, cxt, io_cache){
|
||||
cxt.logs = []
|
||||
cxt.children = null
|
||||
|
||||
remove_io_patches(cxt)
|
||||
remove_promise_patch(cxt)
|
||||
|
||||
cxt.searched_location = null
|
||||
@@ -97,6 +96,10 @@ const do_run = function*(module_fns, cxt, io_cache){
|
||||
}
|
||||
|
||||
export const run = gen_to_promise(function*(module_fns, cxt, io_cache) {
|
||||
if(cxt.run_window != globalThis) {
|
||||
// TODO refactor, remove cxt.run_window
|
||||
throw new Error('illegal state')
|
||||
}
|
||||
const result = yield* do_run(module_fns, cxt, io_cache)
|
||||
|
||||
if(result.eval_cxt.io_cache_is_replay_aborted) {
|
||||
|
||||
11
test/test.js
11
test/test.js
@@ -3231,4 +3231,15 @@ const y = x()`
|
||||
// Deferred calls should not be record in cache
|
||||
assert_equal(state.eval_cxt.io_cache.length, 0)
|
||||
}),
|
||||
|
||||
test_only('record io discard prev execution', () => {
|
||||
// Populate cache
|
||||
const i = test_initial_state(`Math.random(0)`)
|
||||
|
||||
// Run code that does not remove IO patches immediately
|
||||
const next = COMMANDS.input(i, `await Promise.resolve()`, 0)
|
||||
|
||||
const next2 = COMMANDS.input(i, `Math.random(1)`, 0).state
|
||||
console.log('n', next2.io_cache)
|
||||
}),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user