Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Realm is not defined due to collection-methods.js in Jest and while Remote Debugging #4029

Closed
liamjones opened this issue Oct 14, 2021 · 7 comments · Fixed by #4109
Closed
Assignees

Comments

@liamjones
Copy link

liamjones commented Oct 14, 2021

How frequently does the bug occur?

All the time

Description

Upgraded from Realm 10.4.0 to 10.5.0+ (still present in 10.8.0)

Can no longer run Jest tests that use Realm or connect the Chrome Remote Debugger to the JSC, both error out with Realm is not defined.

This was fixed in PR #3748 but that was closed without merging. Other bug reports for this issue include issue #3835 and issue #3991.

For now, we have patched Realm via patch-package with the code review suggestion on PR #3748 to work around this issue with the current implementation. Patch file: https://gist.github.com/liamjones/cca9c81f26e0d998c9904d734e9be400

Stacktrace & log output

IllegalStateError: ReferenceError: Realm is not defined
    at loadFileUploadConfiguration$ (http://localhost:8081/packages/apps/the-app/index.bundle?platform=ios&dev=true&minify=false:230110:84)
    at tryCatch (http://localhost:8081/packages/apps/the-app/index.bundle?platform=ios&dev=true&minify=false:28789:19)
    at Generator.invoke [as _invoke] (http://localhost:8081/packages/apps/the-app/index.bundle?platform=ios&dev=true&minify=false:28962:24)
    at Generator.next (http://localhost:8081/packages/apps/the-app/index.bundle?platform=ios&dev=true&minify=false:28832:23)
    at next (http://localhost:8081/packages/apps/the-app/index.bundle?platform=ios&dev=true&minify=false:181472:29)
    at proc (http://localhost:8081/packages/apps/the-app/index.bundle?platform=ios&dev=true&minify=false:181447:5)
    at runForkEffect (http://localhost:8081/packages/apps/the-app/index.bundle?platform=ios&dev=true&minify=false:181688:21)
    at runEffect (http://localhost:8081/packages/apps/the-app/index.bundle?platform=ios&dev=true&minify=false:181573:770)
    at next (http://localhost:8081/packages/apps/the-app/index.bundle?platform=ios&dev=true&minify=false:181476:11)
    at currCb (http://localhost:8081/packages/apps/the-app/index.bundle?platform=ios&dev=true&minify=false:181550:9)

Can you reproduce the bug?

Yes, always

Reproduction Steps

Unfortunately, I haven't been able to make a minimal repro that still triggers the issue yet and I don't really want to give you the entire source code to our app if I can help it.

For Jest, I thought it might be caused by the fact we normally have a manual mock for Realm in Jest (e.g. __mocks__/realm.ts) and then jest.unmock('realm') in one specific test to check our migration functions. However, just setting that up in a fresh RN project doesn't trigger the issue.

Setting a breakpoint in the remote debugger on https://github.com/realm/realm-js/blob/v10.8.0/lib/collection-methods.js#L21 I can see that our RN app entry point index.js imports our App.tsx and, as a result of dependencies, this eventually does import Realm from 'realm' and when collection-methods.js is imported, Realm is already not defined (but it doesn't care at this point). Later on, a redux-saga is trying to load stuff from the DB, which results in https://github.com/realm/realm-js/blob/v10.8.0/lib/collection-methods.js#L60 executing and falling over due to Realm not being defined.

Version

10.5.0, 10.8.0

What SDK flavour are you using?

Local Database only

Are you using encryption?

Yes, using encryption

Platform OS and version(s)

macOS 11.6

Build environment

Which debugger for React Native: React Native Debugger 0.12.1
RN 0.63.4

@liamjones
Copy link
Author

I can raise a cleaner version of the patch (https://gist.github.com/liamjones/cca9c81f26e0d998c9904d734e9be400) as a PR if you want but I couldn't get the builds/tests working when I checked out the realm-js repo locally so it might make sense for you to just make the code changes + test changes internally?

@kraenhansen
Copy link
Member

Thanks for taking the time to write up this issue.

To be completely honest, we are focussed on getting a version of Realm JS out which works well with Flipper. We already have an alpha release of this published. Once that is officially out, we will most likely discontinue our support of the (now legacy) Chrome Remote Debugger workflow and in that light, we probably won't be investigating this issue any further.

Out of curiosity, would you be interested in moving from React Native Debugger to Flipper to resolve this issue?

@liamjones
Copy link
Author

Would you be interested in moving from React Native Debugger to Flipper to resolve this issue?

Unfortunately, that's not possible for us right now. Flipper's debugger is only for Hermes (AFAIK) and we're stuck on the JSC at the moment. We would ultimately like to try moving our apps over to Hermes and then we have to use Flipper's debugger I believe?

Currently, we're blocked by Realm not supporting Hermes (I know you're working on it). Beyond that, I don't know how many other things will need changes when we try to migrate engines - we haven't been able to test yet because of the Realm blocker - and ours is a pretty chunky app so it may not be an easy thing to do if we find a lot of issues. I'm hopeful though! 🤞

Once that is officially out, we will most likely discontinue our support of the (now legacy) Chrome Remote Debugger workflow and in that light, we probably won't be investigating this issue any further.

How will JSC based projects debug their apps containing Realm in future then? Is there another option I'm not aware of?

@takameyer
Copy link
Contributor

takameyer commented Oct 14, 2021

@liamjones We are currently recommending Safari for debugging. It requires a small addition to the AppDelegate.m, but it is much more reliable than Chrome, since we don't need to maintain a workaround to communicate with the browser and the device/simulator.
But that's just part of the problem it seems. I would like to know more about how you are mocking Realm in Jest. Perhaps that will give us a clue into what is causing your tests to fail.

@liamjones
Copy link
Author

We are currently recommending Safari for debugging.

Thanks, I'll take a look. It'll be a shame to lose the integrated Redux DevTools and React DevTools but it looks like both can be set up independently.

I would like to know more about how you are mocking Realm in Jest. Perhaps that will give us a clue into what is causing your tests to fail.

Sure. We have a manual mock for Realm in Jest that most of our tests use when they don't care about a real Realm. Code for the mock is here but I think it's probably irrelevant: https://gist.github.com/liamjones/2f7b50cef351f2aedb0adf796e83e11c

However, we use linear migrations and have a test that uses real Realm to check these run correctly so we jest.unmock('realm') in this file.

If I set various breakpoints in the manual mock, the test and Realm itself I can see the following happen:

  1. Test is parsed and import Realm from 'realm' is found at the top of the file.
  2. This requires the real Realm, index.js shows environment as node.js and realmConstructor as function Realm() { [native code] } which seems correct (I don't see the breakpoint in the manual mock ever get called if I'm only running the test containing the unmock call).
  3. extensions.js loads collection-methods.js and if I breakpoint on the first executable line (var arrayPrototype = Array.prototype;), Realm is not defined at this point, nor is it present in global.Realm but this isn't, yet, a problem.
  4. Back in the test we start looping through our migration upgrades in an async function:
const migrateToLatestSchemaFrom = async (schemaVersionToStartFrom: number, testSchemaConfigs: Realm.Configuration[], testRealmFile: string): Promise<Realm> => {
    let schemaVersion = schemaVersionToStartFrom
    while (schemaVersion < testSchemaConfigs.length - 1) {
        const migratedRealm = new Realm(testSchemaConfigs[schemaVersion++])
        migratedRealm.close()
    }
    const latestRealmConfigWithRealmSchemaObjects: Realm.Configuration = {
        ...testSchemaConfigs[testSchemaConfigs.length - 1],
        schema: latestRealmSchemaObjects,
        path: testRealmFile,
    }
    return Realm.open(latestRealmConfigWithRealmSchemaObjects)
}
  1. The real Realm is present and correct at this point in the context of the test. The new Realm(...) line works fine with the first two schemas.
  2. When we attempt to new Realm() with schema 3 we hit the issue.
    Schema 3 added one new property and changed the data in a second:
export const schemaVersion3MigrationFunction = (oldRealm: Realm, newRealm: Realm): void => {
    migrateThings(newRealm)
    // ... other migrations
}

function migrateThings(newRealm: Realm) {
    const things = newRealm.objects<{ id: string, type: string }>('Thing')
    for (const thing of things) {
        thing.id = uuid.v4()
        thing.type = migrateThingType(thing.type)
    }
}

things is set to a Proxy, which I believe is correct, but when the for of attempts to start iterating over the results we end up on const isSet = (this.constructor && this.constructor.name === "Set") || this instanceof Realm.Set; in collection-methods.js of Realm and Realm is not defined.

I'm not sure if it is the manual mock causing issues - if I delete the mock entirely, remove the unmock line from the above test and try running it again it falls over in exactly the same way.

@liamjones
Copy link
Author

We are currently recommending Safari for debugging. It requires a small addition to the AppDelegate.m, but it is much more reliable than Chrome, since we don't need to maintain a workaround to communicate with the browser and the device/simulator.

@takameyer I gave this a try today and the app exits/crashes as soon as I attempt to attach Safari to debug so this doesn't look like it's a solution for us on the JSC. 😞

@fronck fronck linked a pull request Dec 15, 2021 that will close this issue
9 tasks
@fronck
Copy link

fronck commented Dec 16, 2021

This issue should be fixed by #4109 .
Thanks for reporting.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants