I’m getting this strange, intermittent bug in Minimongo after upgrading from Meteor 2.16 to 3.3.
It seems that the Minimongo code is being transpiled in order to avoid using async calls on iOS and Android. The web version isn’t transpiled.
I’ve traced it as below. query
is undefined, so the highlighted statement throws “Cannot read properties of undefined” when running query.dirty
:
In the original code, this is impossible since query
is used to iterate over this.queries
in a for-of loop:
async insertAsync(doc, callback) {
doc = EJSON.clone(doc);
const id = this.prepareInsert(doc);
const queriesToRecompute = [];
// trigger live queries that match
for (const qid of Object.keys(this.queries)) {
const query = this.queries[qid];
if (query.dirty) {
continue;
}
In the case I traced above, qid
is 80
, but this.queries
only has entries for 81
and 82
.
So the transpiler seems to be injecting this
somehow, but it gets mixed up.
I suspect that Cordova might be doing the transpiling, probably to support older mobile browsers without async / promises support.
I expect that this would affect anybody using collections on the client side on mobile devices.
Has anybody experienced something similar? Any ideas or suggestions would be appreciated.
1 Like
do you have some reproducible example? is it hapenening in a hello world cordova app?
I’ll see what I can do about reproducing it.
However, it’s definitely the case that Cordova builds are being transpiled to avoid async / promises. I checked the insert
method (vs the insertAsync
in the previous post) and it doesn’t have any of that weird while(1)-case stuff.
Surely modern Cordova builds should be able to use async code by now? I wonder if raising the minimum iOS or Android version will switch it over to native async.
If so, then the problem is solved since the bug can’t happen when using the for-of loop.
2 Likes
I think it might be Meteor doing the transpiling.
I found a reference to “@babel/plugin-transform-async-to-generator” in meteor/npm-packages/babel-preset-meteor/package.json
Does anyone know how to tweak these settings for Cordova builds?
2 Likes
With some LLM help, I figured out that adding
if (arch === "web.cordova")
features.modernBrowsers = true;
to packages/babel-compiler/babel-compiler.js stops Meteor from polyfilling the asyncs for Cordova. This is probably something that should be changed for everyone - I’ll submit a pull request.
However, this didn’t solve my problem 
I thought about it a bit more. I pretty sure it’s a Meteor bug: the for-of loop iterates a static list (Object.keys(this.queries)
), but in the body of the loop keys can be removed from this.queries
directly or elsewhere (when the code pauses due to await
), so trying to lookup a key from the static list can give you an undefined
This will probably fix the problem:
if (!query || query.dirty) {
continue;
}
I think I’ll submit an issue on Github for this. I’ll link it here.
1 Like
Furthermore, I suspect calls to insertAsync
in packages/minimongo/local_collection.js should be queued. Otherwise multiple invocations can trip over each other by modifying this.queries
1 Like
status report: discussion moved to github