Leak canary detects some memory leak on detach fragments - memory-leaks

When I detach fragments from activity, Leak Canary detects some memory leaks inside androidx.core.widget.NestedScrollView. I have no observable in it and just a viewmodel binded to its databinding object.
ApplicationLeak(className=androidx.core.widget.NestedScrollView, leakTrace=
┬
.
.
.
│ ↓ MainActivity.controller
├─ com.ncapdevi.fragnav.FragNavController
│ Leaking: NO (ArrayList↓ is not leaking)
│ ↓ FragNavController.rootFragments
├─ java.util.ArrayList
│ Leaking: NO (Object[]↓ is not leaking)
│ ↓ ArrayList.elementData
├─ java.lang.Object[]
│ Leaking: NO (MoreFragment↓ is not leaking)
│ ↓ array Object[].[3]
├─ my.package.name.ui.main.more.MoreFragment
│ Leaking: NO (Fragment#mFragmentManager is not null)
│ Fragment.mTag=my.package.name.ui.main.more.MoreFragment4
│ ↓ MoreFragment.binding
│ ~~~~~~~
├─ my.package.name.databinding.FragmentMoreBindingImpl
│ Leaking: UNKNOWN
│ ↓ FragmentMoreBindingImpl.mRoot
│ ~~~~~
╰→ androidx.core.widget.NestedScrollView
Leaking: YES (ObjectWatcher was watching this)
mContext instance of my.package.name.ui.main.MainActivity with mDestroyed = false
View#mParent is null
View#mAttachInfo is null (view detached)
View.mWindowAttachCount = 1
key = 2262922d-06f8-4abb-ba7b-d276c6fe3082
watchDurationMillis = 1910
retainedDurationMillis = -1
, retainedHeapByteSize=7132)

MoreFragment is holding on to FragmentMoreBindingImpl (which itself holds NestedScrollView) after onDestroyView. You should clear the reference to the binding in Fragment.onDestroyView()

Related

Trait not implemented for a thing I think implements the trait

I am trying to call a method from a rust crate and getting an error stating that a trait is not implemented for one of the methods I am passing however when I look the method up on docs.rs it does appear to be implementing the required trait.
I am trying to call a method called new_with_count from a crate called wagyu_ethereum.
The code I am using to make the call is here:
use rand::{rngs::StdRng, SeedableRng};
use wagyu_ethereum::*;
use wagyu_model::mnemonic::MnemonicCount;
use wagyu_model::MnemonicError;
pub fn generate_mnemonic() -> Result<String, MnemonicError> {
let mut rng = StdRng::from_entropy();
let mnemonic = EthereumMnemonic::<
wagyu_ethereum::network::Mainnet,
wagyu_ethereum::wordlist::English,
>::new_with_count(&mut rng, 24)?;
Ok(String::from("placeholder"))
}
The code for the method (from the projects GitHub page:
impl<N: EthereumNetwork, W: EthereumWordlist> MnemonicCount for EthereumMnemonic<N, W> {
/// Returns a new mnemonic given the word count.
fn new_with_count<R: Rng>(rng: &mut R, word_count: u8) -> Result<Self, MnemonicError> {
let length: usize = match word_count {
12 => 16,
15 => 20,
18 => 24,
21 => 28,
24 => 32,
wc => return Err(MnemonicError::InvalidWordCount(wc)),
};
let entropy: [u8; 32] = rng.gen();
Ok(Self {
entropy: entropy[0..length].to_vec(),
_network: PhantomData,
_wordlist: PhantomData,
})
}
}
The error:
error[E0277]: the trait bound `StdRng: rand_core::RngCore` is not satisfied
--> src/lib.rs:12:23
|
9 | let mnemonic = EthereumMnemonic::<
| ____________________-
10 | | wagyu_ethereum::network::Mainnet,
11 | | wagyu_ethereum::wordlist::English,
12 | | >::new_with_count(&mut rng, 24)?;
| | - ^^^^^^^^ the trait `rand_core::RngCore` is not implemented for `StdRng`
| |_____________________|
| required by a bound introduced by this call
|
= help: the following other types implement trait `rand_core::RngCore`:
&'a mut R
Box<R>
rand::rngs::adapter::read::ReadRng<R>
rand::rngs::adapter::reseeding::ReseedingRng<R, Rsdr>
rand::rngs::entropy::EntropyRng
rand::rngs::mock::StepRng
rand::rngs::std::StdRng
rand::rngs::thread::ThreadRng
and 6 others
= note: required because of the requirements on the impl of `rand::Rng` for `StdRng`
note: required by a bound in `new_with_count`
--> /home/me/.cargo/registry/src/github.com-1ecc6299db9ec823/wagyu-model-0.6.3/src/mnemonic.rs:44:26
|
44 | fn new_with_count<R: Rng>(rng: &mut R, word_count: u8) -> Result<Self, MnemonicError>;
| ^^^ required by this bound in `new_with_count`
So as far as I can tell from the documentation on docs.rs it appears that StdRng does actually implement RngCore. I've also found this question that indicates I might be borrowing to many time but I'm not sure if it is relevant here because I don't think I am borrowing as many times.
Finally on the projects Github account they have instances of calling the method the same way I am doing (method call, rng assignment). This is what prompted me to use this method. Their program also works when you run it. So the question I have is what am I doing wrong when trying to call this method?
At the time of writing, the newest versions are:
rand = "0.8.5"
wagyu-ethereum = "0.6.3"
wagyu-model = "0.6.3"
It seems that a version mismatch exists here. wagyu-ethereum = "0.6.3" depends on rand = "0.7.3", while the current default if you do cargo add rand is rand = "0.8.5".
You can see this in cargo tree:
rust_test v0.1.0 (/home/me/work/rust_test)
├── rand v0.8.5
│ ├── libc v0.2.139
│ ├── rand_chacha v0.3.1
│ │ ├── ppv-lite86 v0.2.17
│ │ └── rand_core v0.6.4
│ │ └── getrandom v0.2.8
│ │ ├── cfg-if v1.0.0
│ │ └── libc v0.2.139
│ └── rand_core v0.6.4 (*)
├── wagyu-ethereum v0.6.3
│ ├── base58 v0.1.0
│ ├── bitvec v0.17.4
│ │ ├── either v1.8.0
│ │ └── radium v0.3.0
│ ├── ethereum-types v0.9.2
│ │ ├── ethbloom v0.9.2
│ │ │ ├── crunchy v0.2.2
│ │ │ ├── fixed-hash v0.6.1
│ │ │ │ ├── byteorder v1.4.3
│ │ │ │ ├── rand v0.7.3
│ │ │ │ │ ├── getrandom v0.1.16
│ │ │ │ │ │ ├── cfg-if v1.0.0
│ │ │ │ │ │ └── libc v0.2.139
│ │ │ │ │ ├── libc v0.2.139
│ │ │ │ │ ├── rand_chacha v0.2.2
│ │ │ │ │ │ ├── ppv-lite86 v0.2.17
│ │ │ │ │ │ └── rand_core v0.5.1
│ │ │ │ │ │ └── getrandom v0.1.16 (*)
│ │ │ │ │ └── rand_core v0.5.1 (*)
│ │ │ │ ├── rustc-hex v2.1.0
│ │ │ │ └── static_assertions v1.1.0
│ │ │ ├── impl-rlp v0.2.1
│ │ │ │ └── rlp v0.4.6
│ │ │ │ └── rustc-hex v2.1.0
│ │ │ ├── impl-serde v0.3.2
│ │ │ │ └── serde v1.0.152
│ │ │ │ └── serde_derive v1.0.152 (proc-macro)
│ │ │ │ ├── proc-macro2 v1.0.49
│ │ │ │ │ └── unicode-ident v1.0.6
│ │ │ │ ├── quote v1.0.23
│ │ │ │ │ └── proc-macro2 v1.0.49 (*)
│ │ │ │ └── syn v1.0.107
│ │ │ │ ├── proc-macro2 v1.0.49 (*)
│ │ │ │ ├── quote v1.0.23 (*)
│ │ │ │ └── unicode-ident v1.0.6
│ │ │ └── tiny-keccak v2.0.2
│ │ │ └── crunchy v0.2.2
│ │ ├── fixed-hash v0.6.1 (*)
│ │ ├── impl-rlp v0.2.1 (*)
│ │ ├── impl-serde v0.3.2 (*)
│ │ ├── primitive-types v0.7.3
│ │ │ ├── fixed-hash v0.6.1 (*)
│ │ │ ├── impl-codec v0.4.2
│ │ │ │ └── parity-scale-codec v1.3.7
│ │ │ │ ├── arrayvec v0.5.2
│ │ │ │ ├── bitvec v0.17.4 (*)
│ │ │ │ ├── byte-slice-cast v0.3.5
│ │ │ │ └── serde v1.0.152 (*)
│ │ │ ├── impl-rlp v0.2.1 (*)
│ │ │ ├── impl-serde v0.3.2 (*)
│ │ │ └── uint v0.8.5
│ │ │ ├── byteorder v1.4.3
│ │ │ ├── crunchy v0.2.2
│ │ │ ├── rustc-hex v2.1.0
│ │ │ └── static_assertions v1.1.0
│ │ └── uint v0.8.5 (*)
│ ├── hex v0.4.3
│ ├── hmac v0.7.1
│ │ ├── crypto-mac v0.7.0
│ │ │ ├── generic-array v0.12.4
│ │ │ │ └── typenum v1.16.0
│ │ │ └── subtle v1.0.0
│ │ └── digest v0.8.1
│ │ └── generic-array v0.12.4 (*)
│ ├── pbkdf2 v0.3.0
│ │ ├── byteorder v1.4.3
│ │ ├── crypto-mac v0.7.0 (*)
│ │ └── rayon v1.6.1
│ │ ├── either v1.8.0
│ │ └── rayon-core v1.10.1
│ │ ├── crossbeam-channel v0.5.6
│ │ │ ├── cfg-if v1.0.0
│ │ │ └── crossbeam-utils v0.8.14
│ │ │ └── cfg-if v1.0.0
│ │ ├── crossbeam-deque v0.8.2
│ │ │ ├── cfg-if v1.0.0
│ │ │ ├── crossbeam-epoch v0.9.13
│ │ │ │ ├── cfg-if v1.0.0
│ │ │ │ ├── crossbeam-utils v0.8.14 (*)
│ │ │ │ ├── memoffset v0.7.1
│ │ │ │ │ [build-dependencies]
│ │ │ │ │ └── autocfg v1.1.0
│ │ │ │ └── scopeguard v1.1.0
│ │ │ │ [build-dependencies]
│ │ │ │ └── autocfg v1.1.0
│ │ │ └── crossbeam-utils v0.8.14 (*)
│ │ ├── crossbeam-utils v0.8.14 (*)
│ │ └── num_cpus v1.15.0
│ │ └── libc v0.2.139
│ ├── rand v0.7.3 (*)
│ ├── regex v1.7.0
│ │ ├── aho-corasick v0.7.20
│ │ │ └── memchr v2.5.0
│ │ ├── memchr v2.5.0
│ │ └── regex-syntax v0.6.28
│ ├── rlp v0.4.6 (*)
│ ├── secp256k1 v0.17.2
│ │ └── secp256k1-sys v0.1.2
│ │ [build-dependencies]
│ │ └── cc v1.0.41
│ ├── serde v1.0.152 (*)
│ ├── serde_json v1.0.91
│ │ ├── itoa v1.0.5
│ │ ├── ryu v1.0.12
│ │ └── serde v1.0.152 (*)
│ ├── sha2 v0.8.2
│ │ ├── block-buffer v0.7.3
│ │ │ ├── block-padding v0.1.5
│ │ │ │ └── byte-tools v0.3.1
│ │ │ ├── byte-tools v0.3.1
│ │ │ ├── byteorder v1.4.3
│ │ │ └── generic-array v0.12.4 (*)
│ │ ├── digest v0.8.1 (*)
│ │ ├── fake-simd v0.1.2
│ │ └── opaque-debug v0.2.3
│ ├── tiny-keccak v1.5.0
│ │ └── crunchy v0.2.2
│ └── wagyu-model v0.6.3
│ ├── base58 v0.1.0
│ ├── base58-monero v0.2.1
│ │ ├── async-stream v0.2.1
│ │ │ ├── async-stream-impl v0.2.1 (proc-macro)
│ │ │ │ ├── proc-macro2 v1.0.49 (*)
│ │ │ │ ├── quote v1.0.23 (*)
│ │ │ │ └── syn v1.0.107 (*)
│ │ │ └── futures-core v0.3.25
│ │ ├── futures-util v0.3.25
│ │ │ ├── futures-core v0.3.25
│ │ │ ├── futures-macro v0.3.25 (proc-macro)
│ │ │ │ ├── proc-macro2 v1.0.49 (*)
│ │ │ │ ├── quote v1.0.23 (*)
│ │ │ │ └── syn v1.0.107 (*)
│ │ │ ├── futures-task v0.3.25
│ │ │ ├── pin-project-lite v0.2.9
│ │ │ ├── pin-utils v0.1.0
│ │ │ └── slab v0.4.7
│ │ │ [build-dependencies]
│ │ │ └── autocfg v1.1.0
│ │ ├── thiserror v1.0.38
│ │ │ └── thiserror-impl v1.0.38 (proc-macro)
│ │ │ ├── proc-macro2 v1.0.49 (*)
│ │ │ ├── quote v1.0.23 (*)
│ │ │ └── syn v1.0.107 (*)
│ │ ├── tiny-keccak v2.0.2 (*)
│ │ └── tokio v0.2.25
│ │ ├── bytes v0.5.6
│ │ ├── futures-core v0.3.25
│ │ ├── memchr v2.5.0
│ │ └── pin-project-lite v0.1.12
│ ├── bech32 v0.6.0
│ ├── byteorder v1.4.3
│ ├── crypto-mac v0.7.0 (*)
│ ├── ethereum-types v0.9.2 (*)
│ ├── failure v0.1.8
│ │ ├── backtrace v0.3.57
│ │ │ ├── addr2line v0.14.1
│ │ │ │ └── gimli v0.23.0
│ │ │ ├── cfg-if v1.0.0
│ │ │ ├── libc v0.2.139
│ │ │ ├── miniz_oxide v0.4.4
│ │ │ │ └── adler v1.0.2
│ │ │ │ [build-dependencies]
│ │ │ │ └── autocfg v1.1.0
│ │ │ ├── object v0.23.0
│ │ │ └── rustc-demangle v0.1.21
│ │ └── failure_derive v0.1.8 (proc-macro)
│ │ ├── proc-macro2 v1.0.49 (*)
│ │ ├── quote v1.0.23 (*)
│ │ ├── syn v1.0.107 (*)
│ │ └── synstructure v0.12.6
│ │ ├── proc-macro2 v1.0.49 (*)
│ │ ├── quote v1.0.23 (*)
│ │ ├── syn v1.0.107 (*)
│ │ └── unicode-xid v0.2.4
│ ├── ff v0.6.0
│ │ ├── byteorder v1.4.3
│ │ └── rand_core v0.5.1 (*)
│ ├── hex v0.4.3
│ ├── rand v0.7.3 (*)
│ ├── rand_core v0.5.1 (*)
│ ├── ripemd160 v0.8.0
│ │ ├── block-buffer v0.7.3 (*)
│ │ ├── digest v0.8.1 (*)
│ │ └── opaque-debug v0.2.3
│ ├── rlp v0.4.6 (*)
│ ├── secp256k1 v0.17.2 (*)
│ ├── serde_json v1.0.91 (*)
│ ├── sha2 v0.8.2 (*)
│ └── uint v0.8.5 (*)
└── wagyu-model v0.6.3 (*)
Usually, Cargo tries to find a single common version of a library for all dependencies, but 0.7.x and 0.8.x are not compatible according to Rust's semver rules, so it includes the library twice. Of course it can't allow those two to be used with each other, as the results would be unpredictable.
While the problem is complicated and obscure, the solution is simple:
Use rand = "0.7.3" in your Cargo.toml until wagyu gets upgraded to rand = "0.8.x".
You could open an issue in their issue-tracker about it, but it seems that the project as a whole didn't get maintained since over a year. Their website doesn't even exist any more. So be aware that this project might be abandoned.

Memory leak caused by MobileAds.registerWebView

I add MobileAds.registerWebView (webView) in activity onCreate; However, a memory leak was found,
When I delete this code, I will not prompt for memory leak
How to solve this problem?
GC Root: Thread object
│
├─ Dk instance
│ Leaking: NO (PathClassLoader↓ is not leaking)
│ Thread name: 'CleanupReference'
│ ↓ Thread.contextClassLoader
├─ dalvik.system.PathClassLoader instance
│ Leaking: NO (zzbzz↓ is not leaking and A ClassLoader is never leaking)
│ ↓ ClassLoader.runtimeInternalObjects
├─ java.lang.Object[] array
│ Leaking: NO (zzbzz↓ is not leaking)
│ ↓ Object[2266]
├─ com.google.android.gms.internal.ads.zzbzz class
│ Leaking: NO (a class is never leaking)
│ ↓ static zzbzz.zza
│ ~~~
├─ com.google.android.gms.internal.ads.zzcfk instance
│ Leaking: UNKNOWN
│ Retaining 16 B in 1 objects
│ ↓ zzasd.zza
│ ~~~
├─ com.google.android.gms.ads.nonagon.signalgeneration.ab instance
│ Leaking: UNKNOWN
│ Retaining 379.4 kB in 5156 objects
│ e instance of sg.just4fun.tgasdk.ui.HomeActivity with mDestroyed = true
│ ↓ ab.e
│ ~
╰→ xxx.xxx.WebViewActivity instance
​ Leaking: YES (ObjectWatcher was watching this because xxx.xxx.WebViewActivity received Activity#onDestroy() callback and
​ Activity#mDestroyed is true)
​ Retaining 376.6 kB in 5078 objects
​ key = 9500b00e-35f4-476d-bb2e-836c21f4c80f
​ watchDurationMillis = 7971
​ retainedDurationMillis = 2971
​ mApplication instance of com.just4fun.tga.App
​ mBase instance of androidx.appcompat.view.ContextThemeWrapper

ts-jest disable babel, babel still appears to be running

So the docs say it should not be; but I'm seeing this output.
➤ YN0000: [#bb/graph]: [BABEL] Note: The code generator has deoptimised the styling of /home/runner/work/services/services/.pnp.js as it exceeds the max of 500KB.
> yarn info -A '*babel-*' # services -> feature/RS2-1243-logging $ !
├─ babel-jest#npm:26.5.2
│ ├─ Instances: 1
│ ├─ Version: 26.5.2
│ │
│ └─ Dependencies
│ ├─ #jest/transform#npm:^26.5.2 → npm:26.5.2
│ ├─ #jest/types#npm:^26.5.2 → npm:26.5.2
│ ├─ #types/babel__core#npm:^7.1.7 → npm:7.1.9
│ ├─ babel-plugin-istanbul#npm:^6.0.0 → npm:6.0.0
│ ├─ babel-preset-jest#npm:^26.5.0 → npm:26.5.0
│ ├─ chalk#npm:^4.0.0 → npm:4.1.0
│ ├─ graceful-fs#npm:^4.2.4 → npm:4.2.4
│ └─ slash#npm:^3.0.0 → npm:3.0.0
│
├─ babel-plugin-dynamic-import-node#npm:2.3.3
│ ├─ Version: 2.3.3
│ │
│ └─ Dependencies
│ └─ object.assign#npm:^4.1.0 → npm:4.1.0
│
├─ babel-plugin-istanbul#npm:6.0.0
│ ├─ Version: 6.0.0
│ │
│ └─ Dependencies
│ ├─ #babel/helper-plugin-utils#npm:^7.0.0 → npm:7.10.4
│ ├─ #istanbuljs/load-nyc-config#npm:^1.0.0 → npm:1.1.0
│ ├─ #istanbuljs/schema#npm:^0.1.2 → npm:0.1.2
│ ├─ istanbul-lib-instrument#npm:^4.0.0 → npm:4.0.3
│ └─ test-exclude#npm:^6.0.0 → npm:6.0.0
│
├─ babel-plugin-jest-hoist#npm:26.5.0
│ ├─ Version: 26.5.0
│ │
│ └─ Dependencies
│ ├─ #babel/template#npm:^7.3.3 → npm:7.10.4
│ ├─ #babel/types#npm:^7.3.3 → npm:7.11.5
│ ├─ #types/babel__core#npm:^7.0.0 → npm:7.1.9
│ └─ #types/babel__traverse#npm:^7.0.6 → npm:7.0.13
│
├─ babel-plugin-syntax-trailing-function-commas#npm:7.0.0-beta.0
│ └─ Version: 7.0.0-beta.0
│
├─ babel-preset-current-node-syntax#npm:0.1.3
│ ├─ Instances: 1
│ ├─ Version: 0.1.3
│ │
│ └─ Dependencies
│ ├─ #babel/plugin-syntax-async-generators#npm:^7.8.4 → npm:7.8.4
│ ├─ #babel/plugin-syntax-bigint#npm:^7.8.3 → npm:7.8.3
│ ├─ #babel/plugin-syntax-class-properties#npm:^7.8.3 → npm:7.10.4
│ ├─ #babel/plugin-syntax-import-meta#npm:^7.8.3 → npm:7.10.4
│ ├─ #babel/plugin-syntax-json-strings#npm:^7.8.3 → npm:7.8.3
│ ├─ #babel/plugin-syntax-logical-assignment-operators#npm:^7.8.3 → npm:7.10.4
│ ├─ #babel/plugin-syntax-nullish-coalescing-operator#npm:^7.8.3 → npm:7.8.3
│ ├─ #babel/plugin-syntax-numeric-separator#npm:^7.8.3 → npm:7.10.4
│ ├─ #babel/plugin-syntax-object-rest-spread#npm:^7.8.3 → npm:7.8.3
│ ├─ #babel/plugin-syntax-optional-catch-binding#npm:^7.8.3 → npm:7.8.3
│ └─ #babel/plugin-syntax-optional-chaining#npm:^7.8.3 → npm:7.8.3
│
├─ babel-preset-fbjs#npm:3.3.0
│ ├─ Instances: 1
│ ├─ Version: 3.3.0
│ │
│ └─ Dependencies
│ ├─ #babel/plugin-proposal-class-properties#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-proposal-object-rest-spread#npm:^7.0.0 → npm:7.11.0
│ ├─ #babel/plugin-syntax-class-properties#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-syntax-flow#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-syntax-jsx#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-syntax-object-rest-spread#npm:^7.0.0 → npm:7.8.3
│ ├─ #babel/plugin-transform-arrow-functions#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-block-scoped-functions#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-block-scoping#npm:^7.0.0 → npm:7.11.1
│ ├─ #babel/plugin-transform-classes#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-computed-properties#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-destructuring#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-flow-strip-types#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-for-of#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-function-name#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-literals#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-member-expression-literals#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-modules-commonjs#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-object-super#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-parameters#npm:^7.0.0 → npm:7.10.5
│ ├─ #babel/plugin-transform-property-literals#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-react-display-name#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-react-jsx#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-shorthand-properties#npm:^7.0.0 → npm:7.10.4
│ ├─ #babel/plugin-transform-spread#npm:^7.0.0 → npm:7.11.0
│ ├─ #babel/plugin-transform-template-literals#npm:^7.0.0 → npm:7.10.5
│ └─ babel-plugin-syntax-trailing-function-commas#npm:^7.0.0-beta.0 → npm:7.0.0-beta.0
│
└─ babel-preset-jest#npm:26.5.0
├─ Instances: 1
├─ Version: 26.5.0
│
└─ Dependencies
├─ babel-plugin-jest-hoist#npm:^26.5.0 → npm:26.5.0
└─ babel-preset-current-node-syntax#npm:^0.1.3 → npm:0.1.3
> yarn why -R 'babel-jest' # services -> feature/RS2-1243-logging $ !
├─ #bb/apollo-test-util#workspace:app-lib/graph/packages/apollo-test-util
│ └─ jest#npm:26.5.2 (via npm:^26.5.2)
│ ├─ #jest/core#npm:26.5.2 (via npm:^26.5.2)
│ │ └─ jest-config#npm:26.5.2 (via npm:^26.5.2)
│ │ └─ babel-jest#npm:26.5.2 [dc086] (via npm:^26.5.2 [dc086])
│ └─ jest-cli#npm:26.5.2 (via npm:^26.5.2)
│ ├─ #jest/core#npm:26.5.2 (via npm:^26.5.2)
│ └─ jest-config#npm:26.5.2 (via npm:^26.5.2)
│
├─ #bb/app-lib#workspace:app-lib
│ └─ jest#npm:26.5.2 (via npm:^26.5.2)
│
├─ #bb/graph#workspace:app-lib/graph/packages/app
│ ├─ #bb/apollo-test-util#workspace:app-lib/graph/packages/apollo-test-util (via workspace:app-lib/graph/packages/apollo-test-util)
│ └─ jest#npm:26.5.2 (via npm:^26.5.2)
│
└─ #bb/test-apollo-configuration#workspace:app-lib/graph/packages/test-apollo-configuration
└─ #bb/apollo-test-util#workspace:app-lib/graph/packages/apollo-test-util (via workspace:app-lib/graph/packages/
is there any way with yarn2 I can just remove babel safely? or barring that completely prevent it from running?

Spawning a new process on node on an headless Raspberry

I'm currently trying to spawn a process inside my node server to take a screenshot of the only screen attached to my raspberry with this command :
var scrot = childProcess.spawn(path.join(__dirname, "bin", "scrot", "scrot"), [options.output]);
This command work on my local machine but I get a code 2 response when I try to run it on my headless raspberry under Debian. I suspect it is because my node process is spawned at the beginning of the boot routine, before the x server is started.
The pstree command show me this :
systemd─┬─avahi-daemon───avahi-daemon
├─bluetoothd
├─cron
├─2*[dbus-daemon]
├─dbus-launch
├─dhcpcd
├─hciattach
├─login───startx───xinit─┬─Xorg───{InputThread}
│ └─openbox─┬─openbox-autosta───sh───chromium-browse─┬─ch+
│ │ ├─ch+
│ │ ├─{A+
│ │ ├─{B+
│ │ ├─{C+
│ │ ├─{C+
│ │ ├─{C+
│ │ ├─{C+
│ │ ├─{C+
│ │ ├─{D+
│ │ ├─{N+
│ │ ├─2*+
│ │ ├─3*+
│ │ ├─{T+
│ │ ├─7*+
│ │ ├─{c+
│ │ ├─{e+
│ │ ├─{g+
│ │ ├─{i+
│ │ ├─{r+
│ │ └─{s+
│ └─ssh-agent
├─node───9*[{node}]
Is there a way to add a child process to the x server context ?
Thanks for any help in advance,
C.

A simpler way to determine the winner in tic-tac-toe?

I model the tic-tac-toe game board this way:
one sig gameBoard {
cells: Row -> Col -> Mark -> Time
}
Mark is either X or O:
enum Mark { X, O }
Row and Col are simply sets:
sig Row {}{ #Row = 3}
sig Col {}{ #Col = 3}
There is a winner when:
there is a row with all X's or all O's, or
there is a col with all X's or all O's, or
there is a left-to-right diagonal with all X's or all O's, or
there is a right-to-left diagonal with all X's or all O's.
I express that with the following complex predicate. Is there a simpler way to express the winner?
pred winner [t: Time] {
some m: Mark |
some r: Row | all c: Col | board[r, c, t] = m
or
some c: Col| all r: Row | board[r, c, t] = m
or
board[first, first, t] = m and
board[first.next, first.next, t] = m and
board[first.next.next, first.next.next, t] = m
or
board[last,last, t] = m and
board[last.prev, last.prev, t] = m and
board[last.prev.prev,last.prev.prev, t] = m
}
Here is my complete tic-tac-toe model:
open util/ordering[Time]
open util/ordering[Row]
open util/ordering[Col]
/*
Structure:
1. The game is played on a 3x3 board.
2. There are two players, Player1 and Player2.
3. Players mark the game board with either X or O.
4. The game is played over a series of time steps.
*/
// 4. The game is played over a series of time steps.
sig Time {}
// 3. Players mark the game board with either X or O.
enum Mark { X, O }
// 2. There are two players, Player1 and Player2.
enum Player { Player1, Player2 }
// 1. The game is played on a ... board.
one sig gameBoard {
cells: Row -> Col -> Mark -> Time
}
// 1. ... on a 3x3 board.
sig Row {}{ #Row = 3}
sig Col {}{ #Col = 3}
/*
Constraints:
1. Each cell has at most one mark (X or O) at each time.
2. A win stops further marking.
3. When all cells are marked, there can be no additional marking.
4. Players alternate moves.
5. There is no interrupt in the play: If cells are empty at time t-1,
and there is no winner at time t-1, then there will be one
fewer empty cells at time t. If there is a winner at time t-1,
then there will be no change to the number of empty cells at
time t (per invariant 2).
6. Player1 marks cells O and Player2 marks cells X.
7. When there is a winner or when all cells are marked,
then the recording of "last player to move" is blank.
*/
// 1. Each cell has at most one mark (X or O) at each time.
pred Each_cell_has_at_most_one_mark {
no r: Row, c: Col, t: Time, disj m, m': Mark |
((r -> c -> m) in gameBoard.cells.t) and
((r -> c -> m') in gameBoard.cells.t)
}
// 2. A win stops further marking.
pred gameBoard_remains_unchanged_after_win {
all t: Time - first |
winner[t.prev] => gameBoard.cells.t = gameBoard.cells.(t.prev)
}
// 3. When all cells are marked, there can be no additional marking.
pred gameBoard_remains_unchanged_after_every_cell_is_marked {
all t: Time - first |
every_cell_is_marked[t.prev] => gameBoard.cells.t = gameBoard.cells.(t.prev)
}
// 4. Players alternate moves.
pred Players_alternately_move {
no t: Time - last, t': t.next |
(some LastPlayerToMove.person.t) and
(some LastPlayerToMove.person.t') and
(LastPlayerToMove.person.t = LastPlayerToMove.person.t')
}
// 5. There is no interrupt in the play: If cells are empty at time t-1,
// and there is no winner at time t-1, then there will be one
// fewer empty cells at time t. If there is a winner at time t-1,
// then there will be no change to the number of empty cells at
// time t (per invariant 2).
pred Progressively_fewer_empty_cells {
all t: Time - first |
not every_cell_is_marked[t.prev] and not winner[t.prev] =>
#empty_cells[t] < #empty_cells[t.prev]
}
// 6. Player1 marks cells O and Player2 marks cells X.
pred Players_mark_cells_appropriately {
all t: Time - first |
not every_cell_is_marked[t.prev] and not winner[t.prev] =>
let c = gameBoard.cells.t - gameBoard.cells.(t.prev) |
c[Row][Col] = X =>
(LastPlayerToMove.person.t = Player2)
else
(LastPlayerToMove.person.t = Player1)
}
// 7. When there is a winner or when all cells are marked,
// then the recording of "last player to move" is blank.
pred LastPlayerToMove_remains_unchanged_after_win_or_all_cells_marked {
all t: Time - first |
((every_cell_is_marked[t.prev]) or (winner[t.prev])) =>
no LastPlayerToMove.person.t
}
// This provides one place that you can call to
// have all the constraints enforced.
pred game_is_constrained_by_these_constraints {
Each_cell_has_at_most_one_mark
gameBoard_remains_unchanged_after_win
gameBoard_remains_unchanged_after_every_cell_is_marked
Players_alternately_move
Progressively_fewer_empty_cells
Players_mark_cells_appropriately
LastPlayerToMove_remains_unchanged_after_win_or_all_cells_marked
}
// Return the set of empty cells at time t.
// This is implemented using set subtraction.
// (Row -> Col) is the set of all possible combinations
// of row and col. Subtract from that the set
// of (row, col) pairs containing a mark at time t.
fun empty_cells[t: Time]: Row -> Col {
(Row -> Col) - gameBoard.cells.t.Mark
}
// Once the game board is completely marked,
// there won't be a "last player." Ditto for when
// there is a winner. That's why there "may" be
// a last player at time t. That is, there isn’t
// necessarily a player involved at every time step,
// i.e., there isn’t necessarily a (Player, Time) pair
// for every value of Time.
one sig LastPlayerToMove {
person: Player lone -> Time
}
// Return the mark (X or O) on board[r][c] at time t,
// or none if there is no mark.
fun board [r: Row, c: Col, t: Time]: lone Mark {
gameBoard.cells[r][c].t
}
// There is a winner when (a) there is a row
// with all X's or all O's, or (b) there is a col
// with all X's or all O's, or (c) there is a left-to-right
// diagonal with all X's or all O's, or (d) there is a
// right-to-left diagonal with all X's or all O's.
pred winner [t: Time] {
some m: Mark |
some r: Row | all c: Col | board[r, c, t] = m
or
some c: Col| all r: Row | board[r, c, t] = m
or
board[first, first, t] = m and
board[first.next, first.next, t] = m and
board[first.next.next, first.next.next, t] = m
or
board[last,last, t] = m and
board[last.prev, last.prev, t] = m and
board[last.prev.prev,last.prev.prev, t] = m
}
// Every call of the game board is marked when
// the set of cells with marks equals all combinations
// of (row, col)
pred every_cell_is_marked[t: Time] {
gameBoard.cells.t.Mark = (Row -> Col)
}
// Initially the game board has no cells.
// One of the players is first to play.
// The game is constrained by the invariants.
pred init [t: Time] {
no gameBoard.cells.t
one p: Player | LastPlayerToMove.person.t = p
game_is_constrained_by_these_constraints
}
pred doNothing [t: Time] {
gameBoard.cells.t = gameBoard.cells.(t.prev)
}
pred Play {
init[first]
all t: Time - first |
X.marked_on_gameboard_at_time[t]
or O.marked_on_gameboard_at_time[t]
or doNothing[t]
}
pred marked_on_gameboard_at_time [m: Mark, t: Time] {
some r: Row, c: Col {
gameBoard.cells.t = gameBoard.cells.(t.prev) +
{r': Row, c': Col, m': Mark | r' = r and c' = c and m' = m}
}
}
run Play for 3 but 12 Time
comment: You can run this whole markdown text in Alloy 5 Beta
TIC-TAC-TOE
We design this game around a Board. The Board is the state and we will use game rules encoded in predicates to
constrain the transitions to the next board.
Setup
Setup the game by defining the board size, the board and the players. The Board has a relative large number
of fields because that makes the trace output nice to read.
```alloy
open util/ordering[Board]
let N = 0+1+2
let highest = max[N]
sig Board {
cells : N -> N -> Cell,
move: Cell,
to : N->N,
won : Cell
}
enum Cell { _, X, O }
```
Winning
The game is won when there is a row, a colum, or a diagonal that holds the same player. We can encode this as follows:
```alloy
let rightdiag = { r,c : N | r = c }
let leftdiag = { r,c : N | c = highest.minus[r] }
pred won[b,b':Board ] {
some token : X + O {
let positions = b.cells.token {
some row : N | N = row.positions
or some column : N | N = positions.column
or rightdiag in positions
or leftdiag in positions
b'.won = token
}
}
}
```
Finished
The game is finished when a player won or there are no more free places.
```alloy
pred finished[ b,b' : Board ] {
not won[b,b'] implies {
b'.won = _
_ not in b'.cells[N][N]
}
b'.cells = b.cells
b'.move = _
b'.to = none -> none
}
```
Play
Plays should alternate between the players. That is why we keep the player in the previous board's move field
and check it is not us. We then constrain the board to have an empty position replaced with the player's
token.
```alloy
pred play[b, b' : Board ] {
b'.won=_
some token : X+O {
b.move != token
b'.move = token
some row,col : N {
b.cells[row][col] = _
b'.cells = b.cells - row->col->_ + row->col->token
b'.to = row->col
}
}
}
```
Trace
Then the only thing remaining is to setup the first board and ensure the game (the trace of Boards) is
played according to the rules.
```alloy
fact trace {
first.move = _
first.won = _
first.cells = N->N->_
all b' : Board - first, b : b'.prev {
not finished[b,b'] => play[b,b']
}
}
```
Run
With the run we can look for certain types of solutions. In this example we try to find a game where O
wins with a righ diagonal ...
```alloy
run { some b : Board | rightdiag in b.cells.(O) } for 11 but 3 int
```
This provides the following output in Alloy 5 Table view (table is reorded from beta 5):
┌──────────┬──────┬────┬───┬───┐
│this/Board│cells │move│to │won│
├──────────┼─┬─┬──┼────┼───┼───┤
│Board⁰ │0│0│_⁰│_⁰ │ │_⁰ │
│ │ ├─┼──┼────┤ ├───┤
│ │ │1│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │1│0│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │2│0│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
├──────────┼─┼─┼──┼────┼─┬─┼───┤
│Board¹ │0│0│_⁰│X⁰ │2│1│_⁰ │
│ │ ├─┼──┼────┼─┴─┼───┤
│ │ │1│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │1│0│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │2│0│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
├──────────┼─┼─┼──┼────┼─┬─┼───┤
│Board² │0│0│_⁰│O⁰ │1│2│_⁰ │
│ │ ├─┼──┼────┼─┴─┼───┤
│ │ │1│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │1│0│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│O⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │2│0│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
├──────────┼─┼─┼──┼────┼─┬─┼───┤
│Board³ │0│0│_⁰│X⁰ │0│1│_⁰ │
│ │ ├─┼──┼────┼─┴─┼───┤
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │1│0│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│O⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │2│0│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
├──────────┼─┼─┼──┼────┼─┬─┼───┤
│Board⁴ │0│0│O⁰│O⁰ │0│0│_⁰ │
│ │ ├─┼──┼────┼─┴─┼───┤
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │1│0│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│O⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │2│0│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
├──────────┼─┼─┼──┼────┼─┬─┼───┤
│Board⁵ │0│0│O⁰│X⁰ │2│0│_⁰ │
│ │ ├─┼──┼────┼─┴─┼───┤
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │1│0│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│O⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │2│0│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
├──────────┼─┼─┼──┼────┼─┬─┼───┤
│Board⁶ │0│0│O⁰│O⁰ │1│1│_⁰ │
│ │ ├─┼──┼────┼─┴─┼───┤
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │1│0│_⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│O⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│O⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │2│0│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
├──────────┼─┼─┼──┼────┼─┬─┼───┤
│Board⁷ │0│0│O⁰│X⁰ │1│0│_⁰ │
│ │ ├─┼──┼────┼─┴─┼───┤
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │1│0│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│O⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│O⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │2│0│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
├──────────┼─┼─┼──┼────┼─┬─┼───┤
│Board⁸ │0│0│O⁰│O⁰ │2│2│_⁰ │
│ │ ├─┼──┼────┼─┴─┼───┤
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │1│0│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│O⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│O⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │2│0│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│O⁰│ │ │ │
├──────────┼─┼─┼──┼────┼───┼───┤
│Board⁹ │0│0│O⁰│_⁰ │ │O⁰ │
│ │ ├─┼──┼────┤ ├───┤
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │1│0│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│O⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│O⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │2│0│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│O⁰│ │ │ │
├──────────┼─┼─┼──┼────┼───┼───┤
│Board¹⁰ │0│0│O⁰│_⁰ │ │O⁰ │
│ │ ├─┼──┼────┤ ├───┤
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│_⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │1│0│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│O⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│O⁰│ │ │ │
│ ├─┼─┼──┤ │ │ │
│ │2│0│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │1│X⁰│ │ │ │
│ │ ├─┼──┤ │ │ │
│ │ │2│O⁰│ │ │ │
└──────────┴─┴─┴──┴────┴───┴───┘
I had some fun implementing this example in Lightning. You might find my results interesting:
Lightning (lightning-workbench) is a language workbench based on Alloy allowing you to define a concrete syntax for any of your Alloy specifications. The concrete syntax is defined through the use of a dedicated model transformation language called f-alloy ( an Alloy variant having the property of being interpretable rather than analyzable ), so you might need a bit of time getting used to it.
The tool's available as an eclipse plugin (update site).
Here's an archive file containing the source of the TicTacToe project illustrated in the above picture, so that you can play around the example by yourself.

Resources