mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-15 05:41:08 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bec5d60b7c | |||
| 3608a5a143 |
@@ -87,7 +87,6 @@ jobs:
|
|||||||
path: |
|
path: |
|
||||||
${{ env.REVIVE_WASM_INSTALL_DIR }}/resolc.js
|
${{ env.REVIVE_WASM_INSTALL_DIR }}/resolc.js
|
||||||
${{ env.REVIVE_WASM_INSTALL_DIR }}/resolc.wasm
|
${{ env.REVIVE_WASM_INSTALL_DIR }}/resolc.wasm
|
||||||
${{ env.REVIVE_WASM_INSTALL_DIR }}/resolc_packed.js
|
|
||||||
retention-days: 1
|
retention-days: 1
|
||||||
|
|
||||||
test-revive-wasm:
|
test-revive-wasm:
|
||||||
|
|||||||
@@ -2,6 +2,18 @@
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## v0.1.0-dev.9
|
||||||
|
|
||||||
|
This is a development pre-release.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Syscalls with more than 6 arguments now pack them into registers.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Remove reloading of the resolc.js file (fix issue with relative path in web worker)
|
||||||
|
|
||||||
## v0.1.0-dev.8
|
## v0.1.0-dev.8
|
||||||
|
|
||||||
This is a development pre-release.
|
This is a development pre-release.
|
||||||
|
|||||||
Generated
+380
-396
File diff suppressed because it is too large
Load Diff
+18
-18
@@ -3,7 +3,7 @@ resolver = "2"
|
|||||||
members = ["crates/*"]
|
members = ["crates/*"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.1.0-dev.8"
|
version = "0.1.0-dev.9"
|
||||||
authors = [
|
authors = [
|
||||||
"Cyrill Leutwiler <cyrill@parity.io>",
|
"Cyrill Leutwiler <cyrill@parity.io>",
|
||||||
"Parity Technologies <admin@parity.io>",
|
"Parity Technologies <admin@parity.io>",
|
||||||
@@ -14,29 +14,29 @@ repository = "https://github.com/paritytech/revive"
|
|||||||
rust-version = "1.81.0"
|
rust-version = "1.81.0"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
revive-benchmarks = { version = "0.1.0-dev.8", path = "crates/benchmarks" }
|
revive-benchmarks = { version = "0.1.0-dev.9", path = "crates/benchmarks" }
|
||||||
revive-builtins = { version = "0.1.0-dev.8", path = "crates/builtins" }
|
revive-builtins = { version = "0.1.0-dev.9", path = "crates/builtins" }
|
||||||
revive-common = { version = "0.1.0-dev.8", path = "crates/common" }
|
revive-common = { version = "0.1.0-dev.9", path = "crates/common" }
|
||||||
revive-differential = { version = "0.1.0-dev.8", path = "crates/differential" }
|
revive-differential = { version = "0.1.0-dev.9", path = "crates/differential" }
|
||||||
revive-integration = { version = "0.1.0-dev.8", path = "crates/integration" }
|
revive-integration = { version = "0.1.0-dev.9", path = "crates/integration" }
|
||||||
revive-linker = { version = "0.1.0-dev.8", path = "crates/linker" }
|
revive-linker = { version = "0.1.0-dev.9", path = "crates/linker" }
|
||||||
lld-sys = { version = "0.1.0-dev.8", path = "crates/lld-sys" }
|
lld-sys = { version = "0.1.0-dev.9", path = "crates/lld-sys" }
|
||||||
revive-llvm-context = { version = "0.1.0-dev.8", path = "crates/llvm-context" }
|
revive-llvm-context = { version = "0.1.0-dev.9", path = "crates/llvm-context" }
|
||||||
revive-runtime-api = { version = "0.1.0-dev.8", path = "crates/runtime-api" }
|
revive-runtime-api = { version = "0.1.0-dev.9", path = "crates/runtime-api" }
|
||||||
revive-runner = { version = "0.1.0-dev.8", path = "crates/runner" }
|
revive-runner = { version = "0.1.0-dev.9", path = "crates/runner" }
|
||||||
revive-solidity = { version = "0.1.0-dev.8", path = "crates/solidity" }
|
revive-solidity = { version = "0.1.0-dev.9", path = "crates/solidity" }
|
||||||
revive-stdlib = { version = "0.1.0-dev.8", path = "crates/stdlib" }
|
revive-stdlib = { version = "0.1.0-dev.9", path = "crates/stdlib" }
|
||||||
revive-build-utils = { version = "0.1.0-dev.8", path = "crates/build-utils" }
|
revive-build-utils = { version = "0.1.0-dev.9", path = "crates/build-utils" }
|
||||||
|
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
cc = "1.0"
|
cc = "1.0"
|
||||||
libc = "0.2.169"
|
libc = "0.2.169"
|
||||||
tempfile = "3.8"
|
tempfile = "3.8"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
semver = { version = "1.0", features = [ "serde" ] }
|
semver = { version = "1.0", features = ["serde"] }
|
||||||
itertools = "0.14"
|
itertools = "0.14"
|
||||||
serde = { version = "1.0", features = [ "derive" ] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = { version = "1.0", features = [ "arbitrary_precision" ] }
|
serde_json = { version = "1.0", features = ["arbitrary_precision"] }
|
||||||
regex = "1.10"
|
regex = "1.10"
|
||||||
once_cell = "1.19"
|
once_cell = "1.19"
|
||||||
num = "0.4.3"
|
num = "0.4.3"
|
||||||
@@ -73,7 +73,7 @@ assert_fs = "1.1.2"
|
|||||||
# polkadot-sdk and friends
|
# polkadot-sdk and friends
|
||||||
codec = { version = "3.6.12", default-features = false, package = "parity-scale-codec" }
|
codec = { version = "3.6.12", default-features = false, package = "parity-scale-codec" }
|
||||||
scale-info = { version = "2.11.6", default-features = false }
|
scale-info = { version = "2.11.6", default-features = false }
|
||||||
polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "d62a90c8c729acd98c7e9a5cab9803b8b211ffc5" }
|
polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "4302f74f7874e6a894578731142a7b310a1449b0" }
|
||||||
|
|
||||||
# llvm
|
# llvm
|
||||||
[workspace.dependencies.inkwell]
|
[workspace.dependencies.inkwell]
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ install-npm:
|
|||||||
|
|
||||||
install-wasm: install-npm
|
install-wasm: install-npm
|
||||||
cargo build --target wasm32-unknown-emscripten -p revive-solidity --release --no-default-features
|
cargo build --target wasm32-unknown-emscripten -p revive-solidity --release --no-default-features
|
||||||
npm run build:package
|
|
||||||
|
|
||||||
install-llvm-builder:
|
install-llvm-builder:
|
||||||
cargo install --path crates/llvm-builder
|
cargo install --path crates/llvm-builder
|
||||||
|
|||||||
@@ -1339,11 +1339,17 @@ where
|
|||||||
self.llvm.custom_width_int_type(bit_length as u32)
|
self.llvm.custom_width_int_type(bit_length as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the register witdh sized type.
|
/// Returns the XLEN witdh sized type.
|
||||||
pub fn xlen_type(&self) -> inkwell::types::IntType<'ctx> {
|
pub fn xlen_type(&self) -> inkwell::types::IntType<'ctx> {
|
||||||
self.llvm.custom_width_int_type(crate::polkavm::XLEN as u32)
|
self.llvm.custom_width_int_type(crate::polkavm::XLEN as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the PolkaVM native register width sized type.
|
||||||
|
pub fn register_type(&self) -> inkwell::types::IntType<'ctx> {
|
||||||
|
self.llvm
|
||||||
|
.custom_width_int_type(revive_common::BIT_LENGTH_X64 as u32)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the sentinel pointer value.
|
/// Returns the sentinel pointer value.
|
||||||
pub fn sentinel_pointer(&self) -> Pointer<'ctx> {
|
pub fn sentinel_pointer(&self) -> Pointer<'ctx> {
|
||||||
let sentinel_pointer = self
|
let sentinel_pointer = self
|
||||||
|
|||||||
@@ -58,39 +58,48 @@ where
|
|||||||
};
|
};
|
||||||
let flags = context.xlen_type().const_int(flags as u64, false);
|
let flags = context.xlen_type().const_int(flags as u64, false);
|
||||||
|
|
||||||
let argument_type = revive_runtime_api::calling_convention::call(context.llvm());
|
let flags_and_callee = revive_runtime_api::calling_convention::pack_hi_lo_reg(
|
||||||
let argument_pointer = context.build_alloca_at_entry(argument_type, "call_arguments");
|
|
||||||
let arguments = &[
|
|
||||||
flags.as_basic_value_enum(),
|
|
||||||
address_pointer.value.as_basic_value_enum(),
|
|
||||||
context
|
|
||||||
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
|
|
||||||
.as_basic_value_enum(),
|
|
||||||
context
|
|
||||||
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
|
|
||||||
.as_basic_value_enum(),
|
|
||||||
deposit_pointer.value.as_basic_value_enum(),
|
|
||||||
value_pointer.value.as_basic_value_enum(),
|
|
||||||
input_pointer.value.as_basic_value_enum(),
|
|
||||||
input_length.as_basic_value_enum(),
|
|
||||||
output_pointer.value.as_basic_value_enum(),
|
|
||||||
output_length_pointer.value.as_basic_value_enum(),
|
|
||||||
];
|
|
||||||
revive_runtime_api::calling_convention::spill(
|
|
||||||
context.builder(),
|
context.builder(),
|
||||||
argument_pointer.value,
|
context.llvm(),
|
||||||
argument_type,
|
flags,
|
||||||
arguments,
|
address_pointer.to_int(context),
|
||||||
|
"address_and_callee",
|
||||||
|
)?;
|
||||||
|
let deposit_and_value = revive_runtime_api::calling_convention::pack_hi_lo_reg(
|
||||||
|
context.builder(),
|
||||||
|
context.llvm(),
|
||||||
|
deposit_pointer.to_int(context),
|
||||||
|
value_pointer.to_int(context),
|
||||||
|
"deposit_and_value",
|
||||||
|
)?;
|
||||||
|
let input_data = revive_runtime_api::calling_convention::pack_hi_lo_reg(
|
||||||
|
context.builder(),
|
||||||
|
context.llvm(),
|
||||||
|
input_length,
|
||||||
|
input_pointer.to_int(context),
|
||||||
|
"input_data",
|
||||||
|
)?;
|
||||||
|
let output_data = revive_runtime_api::calling_convention::pack_hi_lo_reg(
|
||||||
|
context.builder(),
|
||||||
|
context.llvm(),
|
||||||
|
output_length_pointer.to_int(context),
|
||||||
|
output_pointer.to_int(context),
|
||||||
|
"output_data",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let name = revive_runtime_api::polkavm_imports::CALL;
|
let name = revive_runtime_api::polkavm_imports::CALL;
|
||||||
let argument_pointer = context.builder().build_ptr_to_int(
|
|
||||||
argument_pointer.value,
|
|
||||||
context.xlen_type(),
|
|
||||||
"call_argument_pointer",
|
|
||||||
)?;
|
|
||||||
let success = context
|
let success = context
|
||||||
.build_runtime_call(name, &[argument_pointer.into()])
|
.build_runtime_call(
|
||||||
|
name,
|
||||||
|
&[
|
||||||
|
flags_and_callee.into(),
|
||||||
|
context.register_type().const_all_ones().into(),
|
||||||
|
context.register_type().const_all_ones().into(),
|
||||||
|
deposit_and_value.into(),
|
||||||
|
input_data.into(),
|
||||||
|
output_data.into(),
|
||||||
|
],
|
||||||
|
)
|
||||||
.unwrap_or_else(|| panic!("{name} should return a value"))
|
.unwrap_or_else(|| panic!("{name} should return a value"))
|
||||||
.into_int_value();
|
.into_int_value();
|
||||||
|
|
||||||
@@ -144,38 +153,41 @@ where
|
|||||||
|
|
||||||
let flags = context.xlen_type().const_int(0u64, false);
|
let flags = context.xlen_type().const_int(0u64, false);
|
||||||
|
|
||||||
let argument_type = revive_runtime_api::calling_convention::delegate_call(context.llvm());
|
let flags_and_callee = revive_runtime_api::calling_convention::pack_hi_lo_reg(
|
||||||
let argument_pointer = context.build_alloca_at_entry(argument_type, "delegate_call_arguments");
|
|
||||||
let arguments = &[
|
|
||||||
flags.as_basic_value_enum(),
|
|
||||||
address_pointer.value.as_basic_value_enum(),
|
|
||||||
context
|
|
||||||
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
|
|
||||||
.as_basic_value_enum(),
|
|
||||||
context
|
|
||||||
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
|
|
||||||
.as_basic_value_enum(),
|
|
||||||
deposit_pointer.value.as_basic_value_enum(),
|
|
||||||
input_pointer.value.as_basic_value_enum(),
|
|
||||||
input_length.as_basic_value_enum(),
|
|
||||||
output_pointer.value.as_basic_value_enum(),
|
|
||||||
output_length_pointer.value.as_basic_value_enum(),
|
|
||||||
];
|
|
||||||
revive_runtime_api::calling_convention::spill(
|
|
||||||
context.builder(),
|
context.builder(),
|
||||||
argument_pointer.value,
|
context.llvm(),
|
||||||
argument_type,
|
flags,
|
||||||
arguments,
|
address_pointer.to_int(context),
|
||||||
|
"address_and_callee",
|
||||||
|
)?;
|
||||||
|
let input_data = revive_runtime_api::calling_convention::pack_hi_lo_reg(
|
||||||
|
context.builder(),
|
||||||
|
context.llvm(),
|
||||||
|
input_length,
|
||||||
|
input_pointer.to_int(context),
|
||||||
|
"input_data",
|
||||||
|
)?;
|
||||||
|
let output_data = revive_runtime_api::calling_convention::pack_hi_lo_reg(
|
||||||
|
context.builder(),
|
||||||
|
context.llvm(),
|
||||||
|
output_length_pointer.to_int(context),
|
||||||
|
output_pointer.to_int(context),
|
||||||
|
"output_data",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let name = revive_runtime_api::polkavm_imports::DELEGATE_CALL;
|
let name = revive_runtime_api::polkavm_imports::DELEGATE_CALL;
|
||||||
let argument_pointer = context.builder().build_ptr_to_int(
|
|
||||||
argument_pointer.value,
|
|
||||||
context.xlen_type(),
|
|
||||||
"delegate_call_argument_pointer",
|
|
||||||
)?;
|
|
||||||
let success = context
|
let success = context
|
||||||
.build_runtime_call(name, &[argument_pointer.into()])
|
.build_runtime_call(
|
||||||
|
name,
|
||||||
|
&[
|
||||||
|
flags_and_callee.into(),
|
||||||
|
context.register_type().const_all_ones().into(),
|
||||||
|
context.register_type().const_all_ones().into(),
|
||||||
|
deposit_pointer.to_int(context).into(),
|
||||||
|
input_data.into(),
|
||||||
|
output_data.into(),
|
||||||
|
],
|
||||||
|
)
|
||||||
.unwrap_or_else(|| panic!("{name} should return a value"))
|
.unwrap_or_else(|| panic!("{name} should return a value"))
|
||||||
.into_int_value();
|
.into_int_value();
|
||||||
|
|
||||||
|
|||||||
@@ -26,15 +26,6 @@ where
|
|||||||
|
|
||||||
let code_hash_pointer = context.build_heap_gep(input_offset, input_length)?;
|
let code_hash_pointer = context.build_heap_gep(input_offset, input_length)?;
|
||||||
|
|
||||||
let input_data_pointer = context.build_gep(
|
|
||||||
code_hash_pointer,
|
|
||||||
&[context
|
|
||||||
.xlen_type()
|
|
||||||
.const_int(revive_common::BYTE_LENGTH_WORD as u64, false)],
|
|
||||||
context.byte_type(),
|
|
||||||
"input_ptr_parameter_offset",
|
|
||||||
);
|
|
||||||
|
|
||||||
let value_pointer = context.build_alloca_at_entry(context.value_type(), "transferred_value");
|
let value_pointer = context.build_alloca_at_entry(context.value_type(), "transferred_value");
|
||||||
context.build_store(value_pointer, value)?;
|
context.build_store(value_pointer, value)?;
|
||||||
|
|
||||||
@@ -56,40 +47,38 @@ where
|
|||||||
let deposit_pointer = context.build_alloca_at_entry(context.word_type(), "deposit_pointer");
|
let deposit_pointer = context.build_alloca_at_entry(context.word_type(), "deposit_pointer");
|
||||||
context.build_store(deposit_pointer, context.word_type().const_all_ones())?;
|
context.build_store(deposit_pointer, context.word_type().const_all_ones())?;
|
||||||
|
|
||||||
let argument_type = revive_runtime_api::calling_convention::instantiate(context.llvm());
|
let deposit_and_value = revive_runtime_api::calling_convention::pack_hi_lo_reg(
|
||||||
let argument_pointer = context.build_alloca_at_entry(argument_type, "instantiate_arguments");
|
|
||||||
let arguments = &[
|
|
||||||
code_hash_pointer.value.as_basic_value_enum(),
|
|
||||||
context
|
|
||||||
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
|
|
||||||
.as_basic_value_enum(),
|
|
||||||
context
|
|
||||||
.integer_const(revive_common::BIT_LENGTH_X64, u64::MAX)
|
|
||||||
.as_basic_value_enum(),
|
|
||||||
deposit_pointer.value.as_basic_value_enum(),
|
|
||||||
value_pointer.value.as_basic_value_enum(),
|
|
||||||
input_data_pointer.value.as_basic_value_enum(),
|
|
||||||
input_length.as_basic_value_enum(),
|
|
||||||
address_pointer.value.as_basic_value_enum(),
|
|
||||||
context.sentinel_pointer().value.as_basic_value_enum(),
|
|
||||||
context.sentinel_pointer().value.as_basic_value_enum(),
|
|
||||||
salt_pointer.value.as_basic_value_enum(),
|
|
||||||
];
|
|
||||||
revive_runtime_api::calling_convention::spill(
|
|
||||||
context.builder(),
|
context.builder(),
|
||||||
argument_pointer.value,
|
context.llvm(),
|
||||||
argument_type,
|
deposit_pointer.to_int(context),
|
||||||
arguments,
|
value_pointer.to_int(context),
|
||||||
|
"deposit_and_value",
|
||||||
|
)?;
|
||||||
|
let input_data = revive_runtime_api::calling_convention::pack_hi_lo_reg(
|
||||||
|
context.builder(),
|
||||||
|
context.llvm(),
|
||||||
|
input_length,
|
||||||
|
code_hash_pointer.to_int(context),
|
||||||
|
"input_data",
|
||||||
|
)?;
|
||||||
|
let address_and_salt = revive_runtime_api::calling_convention::pack_hi_lo_reg(
|
||||||
|
context.builder(),
|
||||||
|
context.llvm(),
|
||||||
|
address_pointer.to_int(context),
|
||||||
|
salt_pointer.to_int(context),
|
||||||
|
"output_data",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let argument_pointer = context.builder().build_ptr_to_int(
|
|
||||||
argument_pointer.value,
|
|
||||||
context.xlen_type(),
|
|
||||||
"instantiate_argument_pointer",
|
|
||||||
)?;
|
|
||||||
context.build_runtime_call(
|
context.build_runtime_call(
|
||||||
revive_runtime_api::polkavm_imports::INSTANTIATE,
|
revive_runtime_api::polkavm_imports::INSTANTIATE,
|
||||||
&[argument_pointer.into()],
|
&[
|
||||||
|
context.register_type().const_all_ones().into(),
|
||||||
|
context.register_type().const_all_ones().into(),
|
||||||
|
deposit_and_value.into(),
|
||||||
|
input_data.into(),
|
||||||
|
context.register_type().const_all_ones().into(),
|
||||||
|
address_and_salt.into(),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
let address = context.build_byte_swap(context.build_load(address_pointer, "address")?)?;
|
let address = context.build_byte_swap(context.build_load(address_pointer, "address")?)?;
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ impl ExtBuilder {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
pallet_balances::GenesisConfig::<Runtime> {
|
pallet_balances::GenesisConfig::<Runtime> {
|
||||||
balances: self.balance_genesis_config,
|
balances: self.balance_genesis_config,
|
||||||
|
dev_accounts: None,
|
||||||
}
|
}
|
||||||
.assimilate_storage(&mut t)
|
.assimilate_storage(&mut t)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -87,6 +87,5 @@ impl pallet_revive::Config for Runtime {
|
|||||||
type UploadOrigin = EnsureSigned<AccountId32>;
|
type UploadOrigin = EnsureSigned<AccountId32>;
|
||||||
type InstantiateOrigin = EnsureSigned<AccountId32>;
|
type InstantiateOrigin = EnsureSigned<AccountId32>;
|
||||||
type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
|
type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
|
||||||
type Debug = ();
|
|
||||||
type ChainId = ConstU64<420_420_420>;
|
type ChainId = ConstU64<420_420_420>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
use inkwell::{
|
use inkwell::{builder::Builder, context::Context, module::Module, values::IntValue};
|
||||||
builder::Builder,
|
|
||||||
context::Context,
|
|
||||||
module::Module,
|
|
||||||
types::{BasicType, StructType},
|
|
||||||
values::{BasicValueEnum, PointerValue},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Creates a module that sets the PolkaVM minimum stack size to [`size`] if linked in.
|
/// Creates a module that sets the PolkaVM minimum stack size to [`size`] if linked in.
|
||||||
pub fn min_stack_size<'context>(
|
pub fn min_stack_size<'context>(
|
||||||
@@ -21,115 +15,23 @@ pub fn min_stack_size<'context>(
|
|||||||
module
|
module
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper for building function calls with stack spilled arguments.
|
/// Helper for packing two 32 bit integer values into a 64 bit integer value.
|
||||||
/// - `pointer`: points to a struct of the packed argument struct type
|
pub fn pack_hi_lo_reg<'ctx>(
|
||||||
/// - `type`: the packed argument struct type
|
|
||||||
/// - `arguments`: a correctly ordered list of the struct field values
|
|
||||||
pub fn spill<'ctx>(
|
|
||||||
builder: &Builder<'ctx>,
|
builder: &Builder<'ctx>,
|
||||||
pointer: PointerValue<'ctx>,
|
context: &'ctx Context,
|
||||||
r#type: StructType<'ctx>,
|
hi: IntValue<'ctx>,
|
||||||
arguments: &[BasicValueEnum<'ctx>],
|
lo: IntValue<'ctx>,
|
||||||
) -> anyhow::Result<()> {
|
name: &str,
|
||||||
for index in 0..r#type.get_field_types().len() {
|
) -> anyhow::Result<IntValue<'ctx>> {
|
||||||
let field_pointer = builder.build_struct_gep(
|
assert_eq!(hi.get_type(), context.i32_type());
|
||||||
r#type,
|
assert_eq!(lo.get_type(), context.i32_type());
|
||||||
pointer,
|
|
||||||
index as u32,
|
|
||||||
&format!("spill_parameter_{}", index),
|
|
||||||
)?;
|
|
||||||
let field_value = arguments
|
|
||||||
.get(index)
|
|
||||||
.ok_or_else(|| anyhow::anyhow!("invalid index {index} for struct type {}", r#type))?;
|
|
||||||
builder.build_store(field_pointer, *field_value)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
let lo_part = builder.build_int_z_extend(lo, context.i64_type(), &format!("{name}_lo_part"))?;
|
||||||
}
|
let hi_part = builder.build_int_z_extend(hi, context.i64_type(), &format!("{name}_hi_part"))?;
|
||||||
|
let hi_part_shifted = builder.build_left_shift(
|
||||||
/// Returns a packed struct argument type for the `instantiate` API.
|
hi_part,
|
||||||
pub fn instantiate(context: &Context) -> StructType {
|
context.i64_type().const_int(32, false),
|
||||||
context.struct_type(
|
&format!("{name}_hi_part_shifted"),
|
||||||
&[
|
)?;
|
||||||
// code_hash_ptr: u32,
|
Ok(builder.build_or(hi_part_shifted, lo_part, name)?)
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// ref_time_limit: u64,
|
|
||||||
context.i64_type().as_basic_type_enum(),
|
|
||||||
// proof_size_limit: u64,
|
|
||||||
context.i64_type().as_basic_type_enum(),
|
|
||||||
// deposit_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// value_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// input_data_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// input_data_len: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// address_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// output_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// output_len_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// salt_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
],
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a packed struct argument type for the `call` API.
|
|
||||||
pub fn call(context: &Context) -> StructType {
|
|
||||||
context.struct_type(
|
|
||||||
&[
|
|
||||||
// flags: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// address_ptr:
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// ref_time_limit: u64,
|
|
||||||
context.i64_type().as_basic_type_enum(),
|
|
||||||
// proof_size_limit: u64,
|
|
||||||
context.i64_type().as_basic_type_enum(),
|
|
||||||
// deposit_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// value_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// input_data_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// input_data_len: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// output_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// output_len_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
],
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a packed struct argument type for the `delegate_call` API.
|
|
||||||
pub fn delegate_call(context: &Context) -> StructType {
|
|
||||||
context.struct_type(
|
|
||||||
&[
|
|
||||||
// flags: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// address_ptr:
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// ref_time_limit: u64,
|
|
||||||
context.i64_type().as_basic_type_enum(),
|
|
||||||
// proof_size_limit: u64,
|
|
||||||
context.i64_type().as_basic_type_enum(),
|
|
||||||
// deposit_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// input_data_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// input_data_len: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// output_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
// output_len_ptr: u32,
|
|
||||||
context.i32_type().as_basic_type_enum(),
|
|
||||||
],
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ POLKAVM_IMPORT(void, block_hash, uint32_t, uint32_t)
|
|||||||
|
|
||||||
POLKAVM_IMPORT(void, block_number, uint32_t)
|
POLKAVM_IMPORT(void, block_number, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, call, uint32_t)
|
POLKAVM_IMPORT(uint64_t, call, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, call_data_copy, uint32_t, uint32_t, uint32_t)
|
POLKAVM_IMPORT(uint64_t, call_data_copy, uint32_t, uint32_t, uint32_t)
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ POLKAVM_IMPORT(uint64_t, code_size, uint32_t)
|
|||||||
|
|
||||||
POLKAVM_IMPORT(void, code_hash, uint32_t, uint32_t)
|
POLKAVM_IMPORT(void, code_hash, uint32_t, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, delegate_call, uint32_t)
|
POLKAVM_IMPORT(uint64_t, delegate_call, uint64_t, uint64_t, uint64_t, uint32_t, uint64_t, uint64_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, deposit_event, uint32_t, uint32_t, uint32_t, uint32_t)
|
POLKAVM_IMPORT(void, deposit_event, uint32_t, uint32_t, uint32_t, uint32_t)
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ POLKAVM_IMPORT(uint64_t, get_storage, uint32_t, uint32_t, uint32_t, uint32_t, ui
|
|||||||
|
|
||||||
POLKAVM_IMPORT(void, hash_keccak_256, uint32_t, uint32_t, uint32_t)
|
POLKAVM_IMPORT(void, hash_keccak_256, uint32_t, uint32_t, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint64_t, instantiate, uint32_t)
|
POLKAVM_IMPORT(uint64_t, instantiate, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, now, uint32_t)
|
POLKAVM_IMPORT(void, now, uint32_t)
|
||||||
|
|
||||||
|
|||||||
-63
@@ -1,63 +0,0 @@
|
|||||||
const fs = require("fs");
|
|
||||||
const path = require("path");
|
|
||||||
const { execSync } = require("child_process");
|
|
||||||
const { minify } = require("terser");
|
|
||||||
|
|
||||||
const RESOLC_WASM_TARGET_DIR = path.join(
|
|
||||||
__dirname,
|
|
||||||
"../target/wasm32-unknown-emscripten/release",
|
|
||||||
);
|
|
||||||
const RESOLC_WASM = path.join(RESOLC_WASM_TARGET_DIR, "resolc.wasm");
|
|
||||||
const RESOLC_JS = path.join(RESOLC_WASM_TARGET_DIR, "resolc.js");
|
|
||||||
const RESOLC_JS_PACKED = path.join(RESOLC_WASM_TARGET_DIR, "resolc_packed.js");
|
|
||||||
|
|
||||||
const execShellCommand = (cmd) => {
|
|
||||||
return execSync(cmd, {
|
|
||||||
encoding: "utf-8",
|
|
||||||
maxBuffer: 1024 * 1024 * 100,
|
|
||||||
}).trim();
|
|
||||||
};
|
|
||||||
|
|
||||||
const wasmBase64 = execShellCommand(
|
|
||||||
`lz4c --no-frame-crc --best --favor-decSpeed "${RESOLC_WASM}" - | tail -c +8 | base64 -w 0`,
|
|
||||||
);
|
|
||||||
|
|
||||||
const wasmSize = fs.statSync(RESOLC_WASM).size;
|
|
||||||
|
|
||||||
const miniLz4 = fs.readFileSync(
|
|
||||||
path.join(__dirname, "utils/mini-lz4.js"),
|
|
||||||
"utf-8",
|
|
||||||
);
|
|
||||||
const base64DecToArr = fs.readFileSync(
|
|
||||||
path.join(__dirname, "utils/base64DecToArr.js"),
|
|
||||||
"utf-8",
|
|
||||||
);
|
|
||||||
const resolcJs = fs.readFileSync(RESOLC_JS, "utf-8");
|
|
||||||
|
|
||||||
const packedJsContent = `
|
|
||||||
let moduleArgs = { wasmBinary: (function(source, uncompressedSize) {
|
|
||||||
${miniLz4}
|
|
||||||
${base64DecToArr}
|
|
||||||
return uncompress(base64DecToArr(source), uncompressedSize);
|
|
||||||
})("${wasmBase64}", ${wasmSize}),
|
|
||||||
};
|
|
||||||
|
|
||||||
${resolcJs}
|
|
||||||
|
|
||||||
createRevive = createRevive.bind(null, moduleArgs);
|
|
||||||
`;
|
|
||||||
|
|
||||||
minify(packedJsContent)
|
|
||||||
.then((minifiedJs) => {
|
|
||||||
if (minifiedJs.error) {
|
|
||||||
console.error("Error during minification:", minifiedJs.error);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeFileSync(RESOLC_JS_PACKED, minifiedJs.code, "utf-8");
|
|
||||||
console.log(`Combined script written to ${RESOLC_JS_PACKED}`);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error("Minification failed:", err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
+36
-54
@@ -1,16 +1,16 @@
|
|||||||
const { test, expect } = require("@playwright/test");
|
const { test, expect } = require('@playwright/test');
|
||||||
const fs = require("fs");
|
const fs = require('fs');
|
||||||
const path = require("path");
|
const path = require('path');
|
||||||
|
|
||||||
function loadFixture(fixture) {
|
function loadFixture(fixture) {
|
||||||
const fixturePath = path.resolve(__dirname, `../fixtures/${fixture}`);
|
const fixturePath = path.resolve(__dirname, `../fixtures/${fixture}`);
|
||||||
return JSON.parse(fs.readFileSync(fixturePath, "utf-8"));
|
return JSON.parse(fs.readFileSync(fixturePath, 'utf-8'));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runWorker(page, input) {
|
async function runWorker(page, input) {
|
||||||
return await page.evaluate((input) => {
|
return await page.evaluate((input) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const worker = new Worker("worker.js");
|
const worker = new Worker('worker.js');
|
||||||
worker.postMessage(JSON.stringify(input));
|
worker.postMessage(JSON.stringify(input));
|
||||||
|
|
||||||
worker.onmessage = (event) => {
|
worker.onmessage = (event) => {
|
||||||
@@ -26,80 +26,62 @@ async function runWorker(page, input) {
|
|||||||
}, input);
|
}, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
test("should successfully compile valid Solidity code in browser", async ({
|
test('should successfully compile valid Solidity code in browser', async ({ page }) => {
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
await page.goto("http://127.0.0.1:8080");
|
await page.goto("http://127.0.0.1:8080");
|
||||||
await page.setContent("");
|
await page.setContent("");
|
||||||
const standardInput = loadFixture("storage.json");
|
const standardInput = loadFixture('storage.json')
|
||||||
const result = await runWorker(page, standardInput);
|
const result = await runWorker(page, standardInput);
|
||||||
|
|
||||||
expect(typeof result).toBe("string");
|
expect(typeof result).toBe('string');
|
||||||
let output = JSON.parse(result);
|
let output = JSON.parse(result);
|
||||||
expect(output).toHaveProperty("contracts");
|
expect(output).toHaveProperty('contracts');
|
||||||
expect(output.contracts["fixtures/storage.sol"]).toHaveProperty("Storage");
|
expect(output.contracts['fixtures/storage.sol']).toHaveProperty('Storage');
|
||||||
expect(output.contracts["fixtures/storage.sol"].Storage).toHaveProperty(
|
expect(output.contracts['fixtures/storage.sol'].Storage).toHaveProperty('abi');
|
||||||
"abi",
|
expect(output.contracts['fixtures/storage.sol'].Storage).toHaveProperty('evm');
|
||||||
);
|
expect(output.contracts['fixtures/storage.sol'].Storage.evm).toHaveProperty('bytecode');
|
||||||
expect(output.contracts["fixtures/storage.sol"].Storage).toHaveProperty(
|
|
||||||
"evm",
|
|
||||||
);
|
|
||||||
expect(output.contracts["fixtures/storage.sol"].Storage.evm).toHaveProperty(
|
|
||||||
"bytecode",
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should successfully compile large valid Solidity code in browser", async ({
|
test('should successfully compile large valid Solidity code in browser', async ({ page }) => {
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
await page.goto("http://127.0.0.1:8080");
|
await page.goto("http://127.0.0.1:8080");
|
||||||
await page.setContent("");
|
await page.setContent("");
|
||||||
const standardInput = loadFixture("token.json");
|
const standardInput = loadFixture('token.json')
|
||||||
const result = await runWorker(page, standardInput);
|
const result = await runWorker(page, standardInput);
|
||||||
|
|
||||||
expect(typeof result).toBe("string");
|
expect(typeof result).toBe('string');
|
||||||
let output = JSON.parse(result);
|
let output = JSON.parse(result);
|
||||||
expect(output).toHaveProperty("contracts");
|
expect(output).toHaveProperty('contracts');
|
||||||
expect(output.contracts["fixtures/token.sol"]).toHaveProperty("MyToken");
|
expect(output.contracts['fixtures/token.sol']).toHaveProperty('MyToken');
|
||||||
expect(output.contracts["fixtures/token.sol"].MyToken).toHaveProperty("abi");
|
expect(output.contracts['fixtures/token.sol'].MyToken).toHaveProperty('abi');
|
||||||
expect(output.contracts["fixtures/token.sol"].MyToken).toHaveProperty("evm");
|
expect(output.contracts['fixtures/token.sol'].MyToken).toHaveProperty('evm');
|
||||||
expect(output.contracts["fixtures/token.sol"].MyToken.evm).toHaveProperty(
|
expect(output.contracts['fixtures/token.sol'].MyToken.evm).toHaveProperty('bytecode');
|
||||||
"bytecode",
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should throw an error for invalid Solidity code in browser", async ({
|
test('should throw an error for invalid Solidity code in browser', async ({ page }) => {
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
await page.goto("http://127.0.0.1:8080");
|
await page.goto("http://127.0.0.1:8080");
|
||||||
await page.setContent("");
|
await page.setContent("");
|
||||||
const standardInput = loadFixture("invalid_contract_content.json");
|
const standardInput = loadFixture('invalid_contract_content.json')
|
||||||
const result = await runWorker(page, standardInput);
|
const result = await runWorker(page, standardInput);
|
||||||
|
|
||||||
expect(typeof result).toBe("string");
|
expect(typeof result).toBe('string');
|
||||||
let output = JSON.parse(result);
|
let output = JSON.parse(result);
|
||||||
expect(output).toHaveProperty("errors");
|
expect(output).toHaveProperty('errors');
|
||||||
expect(Array.isArray(output.errors)).toBeTruthy(); // Check if it's an array
|
expect(Array.isArray(output.errors)).toBeTruthy(); // Check if it's an array
|
||||||
expect(output.errors.length).toBeGreaterThan(0);
|
expect(output.errors.length).toBeGreaterThan(0);
|
||||||
expect(output.errors[0]).toHaveProperty("type");
|
expect(output.errors[0]).toHaveProperty('type');
|
||||||
expect(output.errors[0].type).toContain("ParserError");
|
expect(output.errors[0].type).toContain('ParserError');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should return not found error for missing imports in browser", async ({
|
test('should return not found error for missing imports in browser', async ({page}) => {
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
await page.goto("http://127.0.0.1:8080");
|
await page.goto("http://127.0.0.1:8080");
|
||||||
await page.setContent("");
|
await page.setContent("");
|
||||||
const standardInput = loadFixture("missing_import.json");
|
const standardInput = loadFixture('missing_import.json')
|
||||||
const result = await runWorker(page, standardInput);
|
const result = await runWorker(page, standardInput);
|
||||||
|
|
||||||
expect(typeof result).toBe("string");
|
expect(typeof result).toBe('string');
|
||||||
let output = JSON.parse(result);
|
let output = JSON.parse(result);
|
||||||
expect(output).toHaveProperty("errors");
|
expect(output).toHaveProperty('errors');
|
||||||
expect(Array.isArray(output.errors)).toBeTruthy(); // Check if it's an array
|
expect(Array.isArray(output.errors)).toBeTruthy(); // Check if it's an array
|
||||||
expect(output.errors.length).toBeGreaterThan(0);
|
expect(output.errors.length).toBeGreaterThan(0);
|
||||||
expect(output.errors[0]).toHaveProperty("message");
|
expect(output.errors[0]).toHaveProperty('message');
|
||||||
expect(output.errors[0].message).toContain(
|
expect(output.errors[0].message).toContain('Source "nonexistent/console.sol" not found');
|
||||||
'Source "nonexistent/console.sol" not found',
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|||||||
+52
-55
@@ -1,57 +1,54 @@
|
|||||||
Module.stdinData = null;
|
var Module = {
|
||||||
Module.stdinDataPosition = 0;
|
stdinData: null,
|
||||||
Module.stdoutData = [];
|
stdinDataPosition: 0,
|
||||||
Module.stderrData = [];
|
stdoutData: [],
|
||||||
|
stderrData: [],
|
||||||
|
|
||||||
// Method to read all collected stdout data
|
// Function to read and return all collected stdout data as a string
|
||||||
Module.readFromStdout = function () {
|
readFromStdout: function() {
|
||||||
if (!Module.stdoutData.length) return "";
|
if (!this.stdoutData.length) return "";
|
||||||
const decoder = new TextDecoder("utf-8");
|
const decoder = new TextDecoder('utf-8');
|
||||||
const data = decoder.decode(new Uint8Array(Module.stdoutData));
|
const data = decoder.decode(new Uint8Array(this.stdoutData));
|
||||||
Module.stdoutData = [];
|
this.stdoutData = [];
|
||||||
return data;
|
return data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Function to read and return all collected stderr data as a string
|
||||||
|
readFromStderr: function() {
|
||||||
|
if (!this.stderrData.length) return "";
|
||||||
|
const decoder = new TextDecoder('utf-8');
|
||||||
|
const data = decoder.decode(new Uint8Array(this.stderrData));
|
||||||
|
this.stderrData = [];
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Function to set input data for stdin
|
||||||
|
writeToStdin: function(data) {
|
||||||
|
const encoder = new TextEncoder();
|
||||||
|
this.stdinData = encoder.encode(data);
|
||||||
|
this.stdinDataPosition = 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
// `preRun` is called before the program starts running
|
||||||
|
preRun: function() {
|
||||||
|
// Define a custom stdin function
|
||||||
|
function customStdin() {
|
||||||
|
if (!Module.stdinData || Module.stdinDataPosition >= Module.stdinData.length) {
|
||||||
|
return null; // End of input (EOF)
|
||||||
|
}
|
||||||
|
return Module.stdinData[Module.stdinDataPosition++];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a custom stdout function
|
||||||
|
function customStdout(char) {
|
||||||
|
Module.stdoutData.push(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a custom stderr function
|
||||||
|
function customStderr(char) {
|
||||||
|
Module.stderrData.push(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
FS.init(customStdin, customStdout, customStderr);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Method to read all collected stderr data
|
|
||||||
Module.readFromStderr = function () {
|
|
||||||
if (!Module.stderrData.length) return "";
|
|
||||||
const decoder = new TextDecoder("utf-8");
|
|
||||||
const data = decoder.decode(new Uint8Array(Module.stderrData));
|
|
||||||
Module.stderrData = [];
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Method to write data to stdin
|
|
||||||
Module.writeToStdin = function (data) {
|
|
||||||
const encoder = new TextEncoder();
|
|
||||||
Module.stdinData = encoder.encode(data);
|
|
||||||
Module.stdinDataPosition = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Override the `preRun` method to customize file system initialization
|
|
||||||
Module.preRun = Module.preRun || [];
|
|
||||||
Module.preRun.push(function () {
|
|
||||||
// Custom stdin function
|
|
||||||
function customStdin() {
|
|
||||||
if (
|
|
||||||
!Module.stdinData ||
|
|
||||||
Module.stdinDataPosition >= Module.stdinData.length
|
|
||||||
) {
|
|
||||||
return null; // End of input (EOF)
|
|
||||||
}
|
|
||||||
return Module.stdinData[Module.stdinDataPosition++];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom stdout function
|
|
||||||
function customStdout(char) {
|
|
||||||
Module.stdoutData.push(char);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom stderr function
|
|
||||||
function customStderr(char) {
|
|
||||||
Module.stderrData.push(char);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the FS (File System) with custom handlers
|
|
||||||
FS.init(customStdin, customStdout, customStderr);
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,34 +1,29 @@
|
|||||||
mergeInto(LibraryManager.library, {
|
mergeInto(LibraryManager.library, {
|
||||||
soljson_compile: function (inputPtr, inputLen) {
|
soljson_compile: function(inputPtr, inputLen) {
|
||||||
const inputJson = UTF8ToString(inputPtr, inputLen);
|
const inputJson = UTF8ToString(inputPtr, inputLen);
|
||||||
const output = Module.soljson.cwrap("solidity_compile", "string", [
|
const output = Module.soljson.cwrap('solidity_compile', 'string', ['string'])(inputJson);
|
||||||
"string",
|
return stringToNewUTF8(output);
|
||||||
])(inputJson);
|
},
|
||||||
return stringToNewUTF8(output);
|
soljson_version: function() {
|
||||||
},
|
const version = Module.soljson.cwrap("solidity_version", "string", [])();
|
||||||
soljson_version: function () {
|
return stringToNewUTF8(version);
|
||||||
const version = Module.soljson.cwrap("solidity_version", "string", [])();
|
},
|
||||||
return stringToNewUTF8(version);
|
resolc_compile: function(inputPtr, inputLen) {
|
||||||
},
|
const inputJson = UTF8ToString(inputPtr, inputLen);
|
||||||
resolc_compile: function (inputPtr, inputLen) {
|
var revive = createRevive();
|
||||||
const inputJson = UTF8ToString(inputPtr, inputLen);
|
revive.writeToStdin(inputJson);
|
||||||
var revive = createRevive();
|
|
||||||
revive.writeToStdin(inputJson);
|
|
||||||
|
|
||||||
// Call main on the new instance
|
// Call main on the new instance
|
||||||
const result = revive.callMain(["--recursive-process"]);
|
const result = revive.callMain(['--recursive-process']);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
const stderrString = revive.readFromStderr();
|
const stderrString = revive.readFromStderr();
|
||||||
const error = JSON.stringify({
|
const error = JSON.stringify({ type: 'error', message: stderrString || "Unknown error" });
|
||||||
type: "error",
|
return stringToNewUTF8(error);
|
||||||
message: stderrString || "Unknown error",
|
} else {
|
||||||
});
|
const stdoutString = revive.readFromStdout();
|
||||||
return stringToNewUTF8(error);
|
const json = JSON.stringify({ type: 'success', data: stdoutString });
|
||||||
} else {
|
return stringToNewUTF8(json);
|
||||||
const stdoutString = revive.readFromStdout();
|
}
|
||||||
const json = JSON.stringify({ type: "success", data: stdoutString });
|
},
|
||||||
return stringToNewUTF8(json);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const soljson = require("solc/soljson");
|
const soljson = require('solc/soljson');
|
||||||
const createRevive = require("./resolc.js");
|
const createRevive = require('./resolc.js');
|
||||||
|
|
||||||
async function compile(standardJsonInput) {
|
async function compile(standardJsonInput) {
|
||||||
if (!standardJsonInput) {
|
if (!standardJsonInput) {
|
||||||
throw new Error("Input JSON for the Solidity compiler is required.");
|
throw new Error('Input JSON for the Solidity compiler is required.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the compiler
|
// Initialize the compiler
|
||||||
@@ -14,7 +14,7 @@ async function compile(standardJsonInput) {
|
|||||||
compiler.writeToStdin(JSON.stringify(standardJsonInput));
|
compiler.writeToStdin(JSON.stringify(standardJsonInput));
|
||||||
|
|
||||||
// Run the compiler
|
// Run the compiler
|
||||||
compiler.callMain(["--standard-json"]);
|
compiler.callMain(['--standard-json']);
|
||||||
|
|
||||||
// Collect output
|
// Collect output
|
||||||
const stdout = compiler.readFromStdout();
|
const stdout = compiler.readFromStdout();
|
||||||
@@ -29,4 +29,4 @@ async function compile(standardJsonInput) {
|
|||||||
return stdout;
|
return stdout;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { compile };
|
module.exports = { compile };
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
const { compile } = require("./revive.js");
|
const { compile } = require('./revive.js');
|
||||||
|
|
||||||
const compilerStandardJsonInput = {
|
const compilerStandardJsonInput = {
|
||||||
language: "Solidity",
|
language: 'Solidity',
|
||||||
sources: {
|
sources: {
|
||||||
"MyContract.sol": {
|
'MyContract.sol': {
|
||||||
content: `
|
content: `
|
||||||
// SPDX-License-Identifier: UNLICENSED
|
// SPDX-License-Identifier: UNLICENSED
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.0;
|
||||||
contract MyContract {
|
contract MyContract {
|
||||||
@@ -13,26 +13,26 @@ const compilerStandardJsonInput = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
},
|
|
||||||
},
|
|
||||||
settings: {
|
|
||||||
optimizer: {
|
|
||||||
enabled: true,
|
|
||||||
runs: 200,
|
|
||||||
},
|
|
||||||
outputSelection: {
|
|
||||||
"*": {
|
|
||||||
"*": ["abi"],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
settings: {
|
||||||
};
|
optimizer: {
|
||||||
|
enabled: true,
|
||||||
|
runs: 200,
|
||||||
|
},
|
||||||
|
outputSelection: {
|
||||||
|
'*': {
|
||||||
|
'*': ['abi'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
async function runCompiler() {
|
async function runCompiler() {
|
||||||
let output = await compile(compilerStandardJsonInput);
|
let output = await compile(compilerStandardJsonInput)
|
||||||
console.log("Output: " + output);
|
console.log("Output: " + output);
|
||||||
}
|
}
|
||||||
|
|
||||||
runCompiler().catch((err) => {
|
runCompiler().catch(err => {
|
||||||
console.error("Error:", err);
|
console.error('Error:', err);
|
||||||
});
|
});
|
||||||
|
|||||||
+47
-49
@@ -1,53 +1,51 @@
|
|||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<title>Web Worker Example</title>
|
|
||||||
<style>
|
|
||||||
/* Ensure the pre tag wraps long lines */
|
|
||||||
pre {
|
|
||||||
white-space: pre-wrap; /* Wrap long lines */
|
|
||||||
word-wrap: break-word; /* Break long words */
|
|
||||||
max-width: 100%; /* Optional: Ensures it doesn't overflow container */
|
|
||||||
overflow-wrap: break-word; /* Another method for wrapping */
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
<head>
|
||||||
<h1>Revive Compilation Output</h1>
|
<meta charset="utf-8" />
|
||||||
<pre id="output"></pre>
|
<title>Web Worker Example</title>
|
||||||
<script>
|
<style>
|
||||||
var outputElement = document.getElementById("output");
|
/* Ensure the pre tag wraps long lines */
|
||||||
var worker = new Worker("./worker.js");
|
pre {
|
||||||
const standardJsonInput = {
|
white-space: pre-wrap; /* Wrap long lines */
|
||||||
language: "Solidity",
|
word-wrap: break-word; /* Break long words */
|
||||||
sources: {
|
max-width: 100%; /* Optional: Ensures it doesn't overflow container */
|
||||||
contract: {
|
overflow-wrap: break-word; /* Another method for wrapping */
|
||||||
content: "contract MyContract { function f() public { } }",
|
}
|
||||||
},
|
</style>
|
||||||
},
|
</head>
|
||||||
settings: {
|
|
||||||
optimizer: {
|
<body>
|
||||||
enabled: true,
|
<h1>Revive Compilation Output</h1>
|
||||||
runs: 200,
|
<pre id="output"></pre>
|
||||||
},
|
<script>
|
||||||
outputSelection: {
|
var outputElement = document.getElementById('output');
|
||||||
"*": {
|
var worker = new Worker('./worker.js');
|
||||||
"*": ["abi"],
|
const standardJsonInput = {
|
||||||
},
|
language: 'Solidity',
|
||||||
},
|
sources: {
|
||||||
},
|
contract: {
|
||||||
};
|
content: 'contract MyContract { function f() public { } }',
|
||||||
worker.addEventListener(
|
}
|
||||||
"message",
|
},
|
||||||
function (e) {
|
settings: {
|
||||||
outputElement.textContent = e.data.output;
|
optimizer: {
|
||||||
},
|
enabled: true,
|
||||||
false,
|
runs: 200,
|
||||||
);
|
},
|
||||||
|
outputSelection: {
|
||||||
|
'*': {
|
||||||
|
'*': ['abi'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
worker.addEventListener('message', function (e) {
|
||||||
|
outputElement.textContent = e.data.output;
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
worker.postMessage(JSON.stringify(standardJsonInput));
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
worker.postMessage(JSON.stringify(standardJsonInput));
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
importScripts("./soljson.js");
|
|
||||||
importScripts("./resolc.js");
|
importScripts('./soljson.js');
|
||||||
|
importScripts('./resolc.js');
|
||||||
|
|
||||||
// Handle messages from the main thread
|
// Handle messages from the main thread
|
||||||
onmessage = async function (e) {
|
onmessage = async function (e) {
|
||||||
const m = createRevive();
|
const m = createRevive();
|
||||||
m.soljson = Module;
|
|
||||||
|
|
||||||
// Set input data for stdin
|
m.soljson = Module;
|
||||||
m.writeToStdin(e.data);
|
|
||||||
|
|
||||||
// Compile the Solidity source code
|
// Set input data for stdin
|
||||||
m.callMain(["--standard-json"]);
|
m.writeToStdin(e.data);
|
||||||
|
|
||||||
postMessage({ output: m.readFromStdout() || m.readFromStderr() });
|
// Compile the Solidity source code
|
||||||
|
m.callMain(['--standard-json']);
|
||||||
|
|
||||||
|
postMessage({output: m.readFromStdout() || m.readFromStderr()});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
{
|
{
|
||||||
"language": "Solidity",
|
"language": "Solidity",
|
||||||
"sources": {
|
"sources": {
|
||||||
"fixtures/storage.sol": {
|
"fixtures/storage.sol": {
|
||||||
"content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\nimport \"nonexistent/console.sol\";\ncontract MyContract { function greet() public pure returns (string memory) { return \"Hello\" // Missing semicolon }}"
|
"content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\nimport \"nonexistent/console.sol\";\ncontract MyContract { function greet() public pure returns (string memory) { return \"Hello\" // Missing semicolon }}"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"settings": {
|
|
||||||
"optimizer": {
|
|
||||||
"enabled": true,
|
|
||||||
"runs": 200
|
|
||||||
},
|
},
|
||||||
"outputSelection": {
|
"settings": {
|
||||||
"*": {
|
"optimizer": {
|
||||||
"*": ["abi"]
|
"enabled": true,
|
||||||
|
"runs": 200
|
||||||
|
},
|
||||||
|
"outputSelection": {
|
||||||
|
"*": {
|
||||||
|
"*": [
|
||||||
|
"abi"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,19 +1,22 @@
|
|||||||
{
|
{
|
||||||
"language": "Solidity",
|
"language": "Solidity",
|
||||||
"sources": {
|
"sources": {
|
||||||
"fixtures/storage.sol": {
|
"fixtures/storage.sol": {
|
||||||
"content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\nimport \"nonexistent/console.sol\";\ncontract MyContract { function f() public { } }"
|
"content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\nimport \"nonexistent/console.sol\";\ncontract MyContract { function f() public { } }"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"settings": {
|
|
||||||
"optimizer": {
|
|
||||||
"enabled": true,
|
|
||||||
"runs": 200
|
|
||||||
},
|
},
|
||||||
"outputSelection": {
|
"settings": {
|
||||||
"*": {
|
"optimizer": {
|
||||||
"*": ["abi"]
|
"enabled": true,
|
||||||
|
"runs": 200
|
||||||
|
},
|
||||||
|
"outputSelection": {
|
||||||
|
"*": {
|
||||||
|
"*": [
|
||||||
|
"abi"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
+17
-14
@@ -1,19 +1,22 @@
|
|||||||
{
|
{
|
||||||
"language": "Solidity",
|
"language": "Solidity",
|
||||||
"sources": {
|
"sources": {
|
||||||
"fixtures/storage.sol": {
|
"fixtures/storage.sol": {
|
||||||
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.8.2 <0.9.0;\ncontract Storage {\n uint256 number;\n function store(uint256 num) public { number = num; }\n function retrieve() public view returns (uint256){ return number; }\n}"
|
"content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.8.2 <0.9.0;\ncontract Storage {\n uint256 number;\n function store(uint256 num) public { number = num; }\n function retrieve() public view returns (uint256){ return number; }\n}"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"settings": {
|
|
||||||
"optimizer": {
|
|
||||||
"enabled": true,
|
|
||||||
"runs": 200
|
|
||||||
},
|
},
|
||||||
"outputSelection": {
|
"settings": {
|
||||||
"*": {
|
"optimizer": {
|
||||||
"*": ["abi"]
|
"enabled": true,
|
||||||
|
"runs": 200
|
||||||
|
},
|
||||||
|
"outputSelection": {
|
||||||
|
"*": {
|
||||||
|
"*": [
|
||||||
|
"abi"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
+77
-74
File diff suppressed because one or more lines are too long
+2
-6
@@ -10,16 +10,12 @@
|
|||||||
"example:node": "node ./examples/node/run_revive.js",
|
"example:node": "node ./examples/node/run_revive.js",
|
||||||
"test:node": "mocha --timeout 60000 ./tests",
|
"test:node": "mocha --timeout 60000 ./tests",
|
||||||
"test:bun": "bun test --timeout 60000 node.test",
|
"test:bun": "bun test --timeout 60000 node.test",
|
||||||
"test:all": "npm run test:node && npm run test:bun",
|
"test:all": "npm run test:node && npm run test:bun"
|
||||||
"format": "prettier --write .",
|
|
||||||
"build:package": "node ./build.js"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.49.1",
|
"@playwright/test": "^1.49.1",
|
||||||
"chai": "^5.1.2",
|
"chai": "^5.1.2",
|
||||||
"http-server": "^14.1.1",
|
"http-server": "^14.1.1",
|
||||||
"mocha": "^11.0.1",
|
"mocha": "^11.0.1"
|
||||||
"prettier": "^3.4.2",
|
|
||||||
"terser": "^5.37.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-14
@@ -1,10 +1,10 @@
|
|||||||
const { defineConfig, devices } = require("@playwright/test");
|
const { defineConfig, devices } = require('@playwright/test');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://playwright.dev/docs/test-configuration
|
* @see https://playwright.dev/docs/test-configuration
|
||||||
*/
|
*/
|
||||||
module.exports = defineConfig({
|
module.exports = defineConfig({
|
||||||
testDir: "./e2e",
|
testDir: './e2e',
|
||||||
/* Run tests in files in parallel */
|
/* Run tests in files in parallel */
|
||||||
fullyParallel: true,
|
fullyParallel: true,
|
||||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
@@ -14,38 +14,39 @@ module.exports = defineConfig({
|
|||||||
/* Opt out of parallel tests on CI. */
|
/* Opt out of parallel tests on CI. */
|
||||||
workers: process.env.CI ? 1 : undefined,
|
workers: process.env.CI ? 1 : undefined,
|
||||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
reporter: "list",
|
reporter: 'list',
|
||||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
use: {
|
use: {
|
||||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||||
baseURL: "http://127.0.0.1:8080",
|
baseURL: 'http://127.0.0.1:8080',
|
||||||
|
|
||||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
trace: "on-first-retry",
|
trace: 'on-first-retry',
|
||||||
},
|
},
|
||||||
timeout: 480000,
|
timeout: 480000,
|
||||||
/* Configure projects for major browsers */
|
/* Configure projects for major browsers */
|
||||||
projects: [
|
projects: [
|
||||||
{
|
{
|
||||||
name: "chromium",
|
name: 'chromium',
|
||||||
use: { ...devices["Desktop Chrome"] },
|
use: { ...devices['Desktop Chrome'] },
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "firefox",
|
name: 'firefox',
|
||||||
use: { ...devices["Desktop Firefox"] },
|
use: { ...devices['Desktop Firefox'] },
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "webkit",
|
name: 'webkit',
|
||||||
use: { ...devices["Desktop Safari"] },
|
use: { ...devices['Desktop Safari'] },
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
/* Run your local dev server before starting the tests */
|
/* Run your local dev server before starting the tests */
|
||||||
webServer: {
|
webServer: {
|
||||||
command: "npm run example:web",
|
command: 'npm run example:web',
|
||||||
url: "http://127.0.0.1:8080",
|
url: 'http://127.0.0.1:8080',
|
||||||
reuseExistingServer: !process.env.CI,
|
reuseExistingServer: !process.env.CI,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+35
-53
@@ -1,88 +1,70 @@
|
|||||||
import { expect } from "chai";
|
import { expect } from 'chai';
|
||||||
import { compile } from "../examples/node/revive.js";
|
import { compile } from '../examples/node/revive.js';
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from 'url';
|
||||||
import path from "path";
|
import path from 'path';
|
||||||
import fs from "fs";
|
import fs from 'fs';
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
function loadFixture(fixture) {
|
function loadFixture(fixture) {
|
||||||
const fixturePath = path.resolve(__dirname, `../fixtures/${fixture}`);
|
const fixturePath = path.resolve(__dirname, `../fixtures/${fixture}`);
|
||||||
return JSON.parse(fs.readFileSync(fixturePath, "utf-8"));
|
return JSON.parse(fs.readFileSync(fixturePath, 'utf-8'));
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("Compile Function Tests", function () {
|
describe('Compile Function Tests', function () {
|
||||||
it("should successfully compile valid Solidity code", async function () {
|
it('should successfully compile valid Solidity code', async function () {
|
||||||
const standardInput = loadFixture("storage.json");
|
const standardInput = loadFixture('storage.json')
|
||||||
|
|
||||||
const result = await compile(standardInput);
|
const result = await compile(standardInput);
|
||||||
expect(result).to.be.a("string");
|
expect(result).to.be.a('string');
|
||||||
const output = JSON.parse(result);
|
const output = JSON.parse(result);
|
||||||
expect(output).to.have.property("contracts");
|
expect(output).to.have.property('contracts');
|
||||||
expect(output.contracts["fixtures/storage.sol"]).to.have.property(
|
expect(output.contracts['fixtures/storage.sol']).to.have.property('Storage');
|
||||||
"Storage",
|
expect(output.contracts['fixtures/storage.sol'].Storage).to.have.property('abi');
|
||||||
);
|
expect(output.contracts['fixtures/storage.sol'].Storage).to.have.property('evm');
|
||||||
expect(output.contracts["fixtures/storage.sol"].Storage).to.have.property(
|
expect(output.contracts['fixtures/storage.sol'].Storage.evm).to.have.property('bytecode');
|
||||||
"abi",
|
|
||||||
);
|
|
||||||
expect(output.contracts["fixtures/storage.sol"].Storage).to.have.property(
|
|
||||||
"evm",
|
|
||||||
);
|
|
||||||
expect(
|
|
||||||
output.contracts["fixtures/storage.sol"].Storage.evm,
|
|
||||||
).to.have.property("bytecode");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (typeof globalThis.Bun == "undefined") {
|
if (typeof globalThis.Bun == 'undefined') {
|
||||||
// Running this test with Bun on a Linux host causes:
|
// Running this test with Bun on a Linux host causes:
|
||||||
// RuntimeError: Out of bounds memory access (evaluating 'getWasmTableEntry(index)(a1, a2, a3, a4, a5)')
|
// RuntimeError: Out of bounds memory access (evaluating 'getWasmTableEntry(index)(a1, a2, a3, a4, a5)')
|
||||||
// Once this issue is resolved, the test will be re-enabled.
|
// Once this issue is resolved, the test will be re-enabled.
|
||||||
it("should successfully compile large Solidity code", async function () {
|
it('should successfully compile large Solidity code', async function () {
|
||||||
const standardInput = loadFixture("token.json");
|
const standardInput = loadFixture('token.json')
|
||||||
|
|
||||||
const result = await compile(standardInput);
|
const result = await compile(standardInput);
|
||||||
expect(result).to.be.a("string");
|
expect(result).to.be.a('string');
|
||||||
const output = JSON.parse(result);
|
const output = JSON.parse(result);
|
||||||
expect(output).to.have.property("contracts");
|
expect(output).to.have.property('contracts');
|
||||||
expect(output.contracts["fixtures/token.sol"]).to.have.property(
|
expect(output.contracts['fixtures/token.sol']).to.have.property('MyToken');
|
||||||
"MyToken",
|
expect(output.contracts['fixtures/token.sol'].MyToken).to.have.property('abi');
|
||||||
);
|
expect(output.contracts['fixtures/token.sol'].MyToken).to.have.property('evm');
|
||||||
expect(output.contracts["fixtures/token.sol"].MyToken).to.have.property(
|
expect(output.contracts['fixtures/token.sol'].MyToken.evm).to.have.property('bytecode');
|
||||||
"abi",
|
|
||||||
);
|
|
||||||
expect(output.contracts["fixtures/token.sol"].MyToken).to.have.property(
|
|
||||||
"evm",
|
|
||||||
);
|
|
||||||
expect(
|
|
||||||
output.contracts["fixtures/token.sol"].MyToken.evm,
|
|
||||||
).to.have.property("bytecode");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
it("should throw an error for invalid Solidity code", async function () {
|
it('should throw an error for invalid Solidity code', async function () {
|
||||||
const standardInput = loadFixture("invalid_contract_content.json");
|
const standardInput = loadFixture('invalid_contract_content.json')
|
||||||
|
|
||||||
const result = await compile(standardInput);
|
const result = await compile(standardInput);
|
||||||
expect(result).to.be.a("string");
|
expect(result).to.be.a('string');
|
||||||
const output = JSON.parse(result);
|
const output = JSON.parse(result);
|
||||||
expect(output).to.have.property("errors");
|
expect(output).to.have.property('errors');
|
||||||
expect(output.errors).to.be.an("array");
|
expect(output.errors).to.be.an('array');
|
||||||
expect(output.errors.length).to.be.greaterThan(0);
|
expect(output.errors.length).to.be.greaterThan(0);
|
||||||
expect(output.errors[0].type).to.exist;
|
expect(output.errors[0].type).to.exist;
|
||||||
expect(output.errors[0].type).to.contain("ParserError");
|
expect(output.errors[0].type).to.contain("ParserError");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return not found error for missing imports", async function () {
|
it('should return not found error for missing imports', async function () {
|
||||||
const standardInput = loadFixture("missing_import.json");
|
const standardInput = loadFixture('missing_import.json')
|
||||||
|
|
||||||
const result = await compile(standardInput);
|
const result = await compile(standardInput);
|
||||||
const output = JSON.parse(result);
|
const output = JSON.parse(result);
|
||||||
expect(output).to.have.property("errors");
|
expect(output).to.have.property('errors');
|
||||||
expect(output.errors).to.be.an("array");
|
expect(output.errors).to.be.an('array');
|
||||||
expect(output.errors.length).to.be.greaterThan(0);
|
expect(output.errors.length).to.be.greaterThan(0);
|
||||||
expect(output.errors[0].message).to.exist;
|
expect(output.errors[0].message).to.exist;
|
||||||
expect(output.errors[0].message).to.include(
|
expect(output.errors[0].message).to.include('Source "nonexistent/console.sol" not found');
|
||||||
'Source "nonexistent/console.sol" not found',
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
function base64DecToArr (sBase64) {
|
|
||||||
/*\
|
|
||||||
|*|
|
|
||||||
|*| Base64 / binary data / UTF-8 strings utilities
|
|
||||||
|*|
|
|
||||||
|*| https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
|
|
||||||
|*|
|
|
||||||
\*/
|
|
||||||
|
|
||||||
/* Array of bytes to Base64 string decoding */
|
|
||||||
|
|
||||||
function b64ToUint6 (nChr) {
|
|
||||||
|
|
||||||
return nChr > 64 && nChr < 91 ?
|
|
||||||
nChr - 65
|
|
||||||
: nChr > 96 && nChr < 123 ?
|
|
||||||
nChr - 71
|
|
||||||
: nChr > 47 && nChr < 58 ?
|
|
||||||
nChr + 4
|
|
||||||
: nChr === 43 ?
|
|
||||||
62
|
|
||||||
: nChr === 47 ?
|
|
||||||
63
|
|
||||||
:
|
|
||||||
0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var
|
|
||||||
nInLen = sBase64.length,
|
|
||||||
nOutLen = nInLen * 3 + 1 >> 2, taBytes = new Uint8Array(nOutLen);
|
|
||||||
|
|
||||||
for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
|
|
||||||
nMod4 = nInIdx & 3;
|
|
||||||
nUint24 |= b64ToUint6(sBase64.charCodeAt(nInIdx)) << 6 * (3 - nMod4);
|
|
||||||
if (nMod4 === 3 || nInLen - nInIdx === 1) {
|
|
||||||
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
|
|
||||||
taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
|
|
||||||
}
|
|
||||||
nUint24 = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return taBytes;
|
|
||||||
}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
function uncompress(source, uncompressedSize) {
|
|
||||||
/*
|
|
||||||
Source https://github.com/ethereum/solidity/blob/develop/scripts/ci/mini-lz4.js
|
|
||||||
====
|
|
||||||
based off https://github.com/emscripten-core/emscripten/blob/main/third_party/mini-lz4.js
|
|
||||||
The license only applies to the body of this function (``uncompress``).
|
|
||||||
====
|
|
||||||
MiniLZ4: Minimal LZ4 block decoding and encoding.
|
|
||||||
|
|
||||||
based off of node-lz4, https://github.com/pierrec/node-lz4
|
|
||||||
|
|
||||||
====
|
|
||||||
Copyright (c) 2012 Pierre Curto
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
====
|
|
||||||
|
|
||||||
changes have the same license
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Decode a block. Assumptions: input contains all sequences of a
|
|
||||||
* chunk, output is large enough to receive the decoded data.
|
|
||||||
* If the output buffer is too small, an error will be thrown.
|
|
||||||
* If the returned value is negative, an error occurred at the returned offset.
|
|
||||||
*
|
|
||||||
* @param {ArrayBufferView} input input data
|
|
||||||
* @param {ArrayBufferView} output output data
|
|
||||||
* @param {number=} sIdx
|
|
||||||
* @param {number=} eIdx
|
|
||||||
* @return {number} number of decoded bytes
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
function uncompressBlock (input, output, sIdx, eIdx) {
|
|
||||||
sIdx = sIdx || 0
|
|
||||||
eIdx = eIdx || (input.length - sIdx)
|
|
||||||
// Process each sequence in the incoming data
|
|
||||||
for (var i = sIdx, n = eIdx, j = 0; i < n;) {
|
|
||||||
var token = input[i++]
|
|
||||||
|
|
||||||
// Literals
|
|
||||||
var literals_length = (token >> 4)
|
|
||||||
if (literals_length > 0) {
|
|
||||||
// length of literals
|
|
||||||
var l = literals_length + 240
|
|
||||||
while (l === 255) {
|
|
||||||
l = input[i++]
|
|
||||||
literals_length += l
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the literals
|
|
||||||
var end = i + literals_length
|
|
||||||
while (i < end) output[j++] = input[i++]
|
|
||||||
|
|
||||||
// End of buffer?
|
|
||||||
if (i === n) return j
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match copy
|
|
||||||
// 2 bytes offset (little endian)
|
|
||||||
var offset = input[i++] | (input[i++] << 8)
|
|
||||||
|
|
||||||
// XXX 0 is an invalid offset value
|
|
||||||
if (offset === 0) return j
|
|
||||||
if (offset > j) return -(i-2)
|
|
||||||
|
|
||||||
// length of match copy
|
|
||||||
var match_length = (token & 0xf)
|
|
||||||
var l = match_length + 240
|
|
||||||
while (l === 255) {
|
|
||||||
l = input[i++]
|
|
||||||
match_length += l
|
|
||||||
}
|
|
||||||
// Copy the match
|
|
||||||
var pos = j - offset // position of the match copy in the current output
|
|
||||||
var end = j + match_length + 4 // minmatch = 4
|
|
||||||
while (j < end) output[j++] = output[pos++]
|
|
||||||
}
|
|
||||||
|
|
||||||
return j
|
|
||||||
}
|
|
||||||
var result = new ArrayBuffer(uncompressedSize);
|
|
||||||
var sourceIndex = 0;
|
|
||||||
var destIndex = 0;
|
|
||||||
var blockSize;
|
|
||||||
while((blockSize = (source[sourceIndex] | (source[sourceIndex + 1] << 8) | (source[sourceIndex + 2] << 16) | (source[sourceIndex + 3] << 24))) > 0)
|
|
||||||
{
|
|
||||||
sourceIndex += 4;
|
|
||||||
if (blockSize & 0x80000000)
|
|
||||||
{
|
|
||||||
blockSize &= 0x7FFFFFFFF;
|
|
||||||
for (var i = 0; i < blockSize; i++) {
|
|
||||||
result[destIndex++] = source[sourceIndex++];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
destIndex += uncompressBlock(source, new Uint8Array(result, destIndex, uncompressedSize - destIndex), sourceIndex, sourceIndex + blockSize);
|
|
||||||
sourceIndex += blockSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Uint8Array(result, 0, uncompressedSize);
|
|
||||||
}
|
|
||||||
+1
-2
@@ -3,8 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test:cli": "npm run test -w crates/solidity/src/tests/cli-tests",
|
"test:cli": "npm run test -w crates/solidity/src/tests/cli-tests",
|
||||||
"test:wasm": "npm run test:all -w js",
|
"test:wasm": "npm run test:all -w js"
|
||||||
"build:package": "npm run build:package -w js"
|
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"crates/solidity/src/tests/cli-tests",
|
"crates/solidity/src/tests/cli-tests",
|
||||||
|
|||||||
Reference in New Issue
Block a user