mirror of
https://github.com/leporello-js/leporello-js
synced 2026-01-13 21:14:28 -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/dist/ethers.js'
|
||||||
import {ethers} from 'https://unpkg.com/ethers@5.7.2/dist/ethers.esm.js'
|
import {ethers} from 'https://unpkg.com/ethers@5.7.2/dist/ethers.esm.js'
|
||||||
|
|
||||||
/*
|
|
||||||
const URL = 'https://ethereum-goerli-rpc.allthatnode.com'
|
const URL = 'https://ethereum-goerli-rpc.allthatnode.com'
|
||||||
|
|
||||||
const p = ethers.getDefaultProvider(URL)
|
const p = ethers.getDefaultProvider(URL)
|
||||||
@@ -12,7 +11,7 @@ const latest = await p.getBlock()
|
|||||||
latest
|
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)
|
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'
|
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
|
let obj = cxt.window
|
||||||
for(let i = 0; i < path.length - 1; i++) {
|
for(let i = 0; i < path.length - 1; i++) {
|
||||||
obj = obj[path[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)
|
const method = path.at(-1)
|
||||||
if(obj == null || obj[method] == null) {
|
if(obj == null || obj[method] == null) {
|
||||||
// Method is absent in current env, skip patching
|
// Method is absent in current env, skip patching
|
||||||
@@ -202,17 +209,31 @@ const io_patch = (cxt, path, use_context = false) => {
|
|||||||
obj[method].__original = original
|
obj[method].__original = original
|
||||||
}
|
}
|
||||||
|
|
||||||
const io_patch_remove = (cxt, path) => {
|
// TODO bare IO functions should not be exposed at all, to allow calling it
|
||||||
const obj = get_object_to_patch(cxt, path)
|
// only from patched versions. Especially setInterval which can cause leaks
|
||||||
const method = path.at(-1)
|
export const apply_io_patches = () => {
|
||||||
if(obj == null || obj[method] == null) {
|
io_patch(['Math', 'random'])
|
||||||
// Method is absent in current env, skip patching
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
obj[method] = obj[method].__original
|
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(['clearTimeout'])
|
||||||
|
|
||||||
|
|
||||||
|
// TODO patch setInterval to only cleanup all intervals on finish
|
||||||
|
|
||||||
|
const Date = cxt.window.Date
|
||||||
|
io_patch(['Date'])
|
||||||
|
cxt.window.Date.parse = Date.parse
|
||||||
|
cxt.window.Date.now = Date.now
|
||||||
|
cxt.window.Date.UTC = Date.UTC
|
||||||
|
io_patch(['Date', 'now'])
|
||||||
|
|
||||||
|
|
||||||
|
io_patch(['fetch'])
|
||||||
|
// Check if Response is defined, for node.js
|
||||||
|
if(cxt.window.Response != null) {
|
||||||
const Response_methods = [
|
const Response_methods = [
|
||||||
'arrayBuffer',
|
'arrayBuffer',
|
||||||
'blob',
|
'blob',
|
||||||
@@ -220,51 +241,8 @@ const Response_methods = [
|
|||||||
'json',
|
'json',
|
||||||
'text',
|
'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'])
|
|
||||||
|
|
||||||
io_patch(cxt, ['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'])
|
|
||||||
|
|
||||||
|
|
||||||
// TODO patch setInterval to only cleanup all intervals on finish
|
|
||||||
|
|
||||||
const Date = cxt.window.Date
|
|
||||||
io_patch(cxt, ['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(cxt, ['fetch'])
|
|
||||||
// Check if Response is defined, for node.js
|
|
||||||
if(cxt.window.Response != null) {
|
|
||||||
for(let key of Response_methods) {
|
for(let key of Response_methods) {
|
||||||
io_patch(cxt, ['Response', 'prototype', key], true)
|
io_patch(['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])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
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_promise_patch(cxt)
|
||||||
apply_io_patches(cxt)
|
set_current_context(cxt)
|
||||||
|
|
||||||
for(let {module, fn} of module_fns) {
|
for(let {module, fn} of module_fns) {
|
||||||
cxt.found_call = null
|
cxt.found_call = null
|
||||||
@@ -80,7 +80,6 @@ const do_run = function*(module_fns, cxt, io_cache){
|
|||||||
cxt.logs = []
|
cxt.logs = []
|
||||||
cxt.children = null
|
cxt.children = null
|
||||||
|
|
||||||
remove_io_patches(cxt)
|
|
||||||
remove_promise_patch(cxt)
|
remove_promise_patch(cxt)
|
||||||
|
|
||||||
cxt.searched_location = null
|
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) {
|
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)
|
const result = yield* do_run(module_fns, cxt, io_cache)
|
||||||
|
|
||||||
if(result.eval_cxt.io_cache_is_replay_aborted) {
|
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
|
// Deferred calls should not be record in cache
|
||||||
assert_equal(state.eval_cxt.io_cache.length, 0)
|
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