cmisJS Error with expo

I want to download/upload Files along the CMIS specification with an existing Apache Chemistry Server on localhost.

Currently I am working on the mobile application with react native and expo that should be able to login to the CMIS Server at first.

I have found a Library that could help me out with that:

When I install it (npm i cmis), and import it like that:

import {cmis} from 'cmis'

and want to use it like that as the documentation states:

import { cmis } from 'cmis';

export default function RepoManager({ navigation }) {

  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [modalVisible, setModalVisible] = useState(true);

  useEffect(() => {
    let session = new cmis.CmisSession('https://localhost/cmis/browser');
    console.log(session);

  }, [])
....
....

I get an the following Error immediately after importing ā€˜cmisā€™:

TypeError: undefined is not an object (evaluating 'self.atob.bind')
at node_modules\expo\build\environment\react-native-logs.fx.js:27:4 in error
at node_modules\react-native\Libraries\Core\ExceptionsManager.js:95:4 in reportException
at node_modules\react-native\Libraries\Core\ExceptionsManager.js:141:19 in handleException
at node_modules\react-native\Libraries\Core\setUpErrorHandling.js:24:6 in handleError
at node_modules\expo-error-recovery\build\ErrorRecovery.fx.js:12:21 in ErrorUtils.setGlobalHandler$argument_0
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:86:13 in tryCatch
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:66:31 in <anonymous>
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:86:13 in tryCatch
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:124:27 in invoke
at node_modules\@babel\runtime\helpers\regeneratorRuntime.js:130:16 in PromiseImpl.resolve.then$argument_0
at node_modules\react-native\node_modules\promise\setimmediate\core.js:37:13 in tryCallOne
at node_modules\react-native\node_modules\promise\setimmediate\core.js:123:24 in setImmediate$argument_0
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:248:12 in _allocateCallback$argument_0
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:112:14 in _callTimer
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:162:14 in _callReactNativeMicrotasksPass
at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:413:41 in callReactNativeMicrotasks
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:391:6 in __callReactNativeMicrotasks
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:133:6 in __guard$argument_0
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:368:10 in __guard
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:132:4 in flushedQueue

cmisJS works outside of expo. How can I fix that?

Hey @martze, not sure why the issue is caused after importing the library into the Expo project. Iā€™d suggest asking the library maintainers if it is compatible with React Native in general?

Hi Aman,

Already contacted the maintainer But it seems That reply wont come back. It works with react, but in my bare Expo project the error Happens within the dependency ā€žisomorphic-base64ā€œ of the Package.

Could you Check if These are compatible?

I thought about trying it again by using Another third party library ā€žNode.js for mobileā€œ That wraps cmis inside a nodejs runtime

Iā€™ve just tried it and it is not compatible with JavaScriptCore. I have not tried it with Hermes.

Thank you for trying out. cmis, which uses isomprphic-base64 does work in an node.js and react environment (not fully bc of CORS). Did you try it out with react native and it didnt work? Only the isomoprhic-base64 package or cmis?

I tried isomorphic-base64.

It does not look to me like cmis will work in React Native. Iā€™m not sure if thereā€™s some way to get it to use some other atob/btoa polyfill instead of isomorphic-base64 and what other issues there might be.

There are a couple of answers on Stack Overflow about Base64 support on React Native. It doesnā€™t directly help with using cmis on React Native, but you could potentially use patch-package to get it to work. (Would have to be option 2 if you use patch-package, I believe, because you canā€™t change dependencies with patch-package.):

  1. Use the base-64 npm
  2. Implement them in JavaScript

EDIT: Hereā€™s a possibly better one:

See also: react-native/binaryToBase64.js at 479053cb3ce2be145993cbeb17e43108313de913 Ā· facebook/react-native Ā· GitHub

1 Like

Big Thanks for your answer.

Right now I am trying to figure out which package would be the best to modify. cmis or isomorphic-base64. Also trying to understand which file to edit.

So far I Tried this:

  • created base64.js File and copy pasted code from your option 2 into it.
  • modified node_modules/isomorphic-base64/browser.js File like so:
'use strict';
import Base64 from './Base64'
console.log(self);

//From
// exports.atob = self.atob.bind(self)
// exports.atob = self.btoa.bind(self)

//To
exports.atob = Base64.atob(self)
exports.btoa = Base64.btoa(self)`

But now I get this Error from the Base64.js I imported:

Error: 'atob' failed: The string to be decoded is not correctly encoded.
at node_modules\expo\build\environment\react-native-logs.fx.js:27:4 in error
at node_modules\react-native\Libraries\Core\ExceptionsManager.js:95:4 in reportException
at node_modules\react-native\Libraries\Core\ExceptionsManager.js:141:19 in handleException
at node_modules\react-native\Libraries\Core\setUpErrorHandling.js:24:6 in handleError
at node_modules\@react-native\polyfills\error-guard.js:49:36 in ErrorUtils.reportFatalError
at node_modules\metro-runtime\src\polyfills\require.js:203:6 in guardedLoadModule
at http://172.19.1.54:8081/index.bundle?platform=android&dev=true&minify=false&app=com.martze.maincyc&modulesOnly=false&runModule=true:136067:3 in global code

Because this condition in Base64.js is true:

if (str.length % 4 == 1) {
      throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");
    }

patched with patch-package.

The Error, that atob/btoa is undefined seems not to be a problem anymore, I think thats not bad, but still some kind of problem exists

Hi again

Iā€™ve just come across this:

Not sure if you would have more luck with that.

Anyway, about the ā€œnot correctly encodedā€ error you were getting:

Base64 encoded strings are supposed to be padded to a multiple of 4 bytes. Thatā€™s why they often have ā€œ=ā€ characters on the end. Itā€™s possible that the padding is left off your data for some reason and itā€™s expecting the Base64 decoder to just treat it as if itā€™s padded. Just a guess.

If the above is whatā€™s happening, you could manually pad the data to a multiple of 4 bytes before decoding it. This could be done in the btoa polyfill.