gajus / flow-runtime

A runtime type system for JavaScript with full Flow compatibility.
MIT License
802 stars 57 forks source link

TransformError on bundling w/ RefreshControl.js #216

Open semireg opened 6 years ago

semireg commented 6 years ago

This is a:

Which concerns:


What is the current behaviour?

Reproducible repo at https://github.com/semireg/RNSemiBoilerplate/tree/fa3829669fda5cb5396eea26a6021513103f7357. This react native boilerplate uses RN 0.57.4, babel 7, flow, flow-runtime, immutable, redux, redux-immutable.

App build is broken due to TransformError when native app loads bundle.

iOS:

Failed to load bundle(http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false) with 
error:(node_modules/react-native/Libraries/Components/RefreshControl/RefreshControl.js: Property 
value expected type of string but got object (null))

__38-[RCTCxxBridge loadSource:onProgress:]_block_invoke.248
    RCTCxxBridge.mm:429
___ZL36attemptAsynchronousLoadOfBundleAtURLP5NSURLU13block_pointerFvP18RCTLoadingProgressEU13block_pointerFvP7NSErrorP9RCTSourceE_block_invoke.118
__80-[RCTMultipartDataTask URLSession:streamTask:didBecomeInputStream:outputStream:]_block_invoke
-[RCTMultipartStreamReader emitChunk:headers:callback:done:]
-[RCTMultipartStreamReader readAllPartsWithCompletionCallback:progressCallback:]
-[RCTMultipartDataTask URLSession:streamTask:didBecomeInputStream:outputStream:]
__88-[NSURLSession delegate_streamTask:didBecomeInputStream:outputStream:completionHandler:]_block_invoke
__NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__
-[NSBlockOperation main]
-[__NSOperationInternal _start:]
__NSOQSchedule_f
_dispatch_call_block_and_release
_dispatch_client_callout
_dispatch_continuation_pop
_dispatch_async_redirect_invoke
_dispatch_root_queue_drain
_dispatch_worker_thread2
_pthread_wqthread
start_wqthread

Android:

The development server returned response error code: 500

URL: http://10.0.2.2:8081/index.delta?platform=android&dev=true&minify=false

Body:
{"type":"TransformError","lineNumber":0,"errors":[{"description":"node_modules/react-
native/Libraries/Components/RefreshControl/RefreshControl.js: Property value expected type of string 
but got object","lineNumber":0}],"name":"SyntaxError","message":"node_modules/react-
native/Libraries/Components/RefreshControl/RefreshControl.js: Property value expected type of string 
but got object","stack":"TypeError: Property value expected type of string but got object\n    at 
Object.validate (/Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-
types/lib/definitions/index.js:161:13)\n    at validate (/Users/devuser/local-
dev/rn/RNSemiBoilerplate/node_modules/babel-types/lib/index.js:505:9)\n    at Object.builder 
(/Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-types/lib/index.js:466:7)\n    at 
qualifiedToMemberExpression (/Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-
plugin-flow-runtime/lib/convert.js:217:19)\n    at annotationToValue (/Users/devuser/local-
dev/rn/RNSemiBoilerplate/node_modules/babel-plugin-flow-runtime/lib/convert.js:247:14)\n    at 
annotationToValue (/Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-plugin-flow-
runtime/lib/convert.js:245:14)\n    at converters.TypeofTypeAnnotation (/Users/devuser/local-
dev/rn/RNSemiBoilerplate/node_modules/babel-plugin-flow-runtime/lib/convert.js:411:15)\n    at 
convert (/Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-plugin-flow-
runtime/lib/convert.js:52:16)\n    at /Users/devuser/local-
dev/rn/RNSemiBoilerplate/node_modules/babel-plugin-flow-runtime/lib/convert.js:533:12"}

processBundleResult
    BundleDownloader.java:296
access$200
    BundleDownloader.java:37
onResponse
    BundleDownloader.java:174
execute
    RealCall.java:153
run
    NamedRunnable.java:32
runWorker
    ThreadPoolExecutor.java:1113
run
    ThreadPoolExecutor.java:588
run
    Thread.java:818

What is the expected behaviour?

Build should bundle and load without error.

I've tried clearing my caches/tmp directories, build assets, etc via:

watchman watch-del-all && rm -rf $TMPDIR/react-* && rm -rf $TMPDIR/metro* && rm -rf $TMPDIR/haste-*
rm -rf node_modules
yarn install

If the repo above does not reproduce the error, can anyone think of other directories that I need to reset that could be tainted?

I have searched GitHub issues, Google, and Stack Overflow and can not find any similar issues.


Which package versions are you using?

  "dependencies": {
    "babel-plugin-flow-runtime": "^0.17.0",
    "flow-runtime": "^0.17.0",
    "immutable": "^4.0.0-rc.11",
    "react": "16.6.0-alpha.8af6728",
    "react-native": "0.57.4",
    "react-redux": "^5.1.0",
    "redux": "^4.0.1",
    "redux-immutable": "^4.0.0",
    "redux-thunk": "^2.3.0"
  },
  "devDependencies": {
    "babel-eslint": "^10.0.1",
    "babel-jest": "23.6.0",
    "eslint": "^5.8.0",
    "eslint-config-airbnb": "^17.1.0",
    "eslint-config-prettier": "^3.1.0",
    "eslint-plugin-eslint-comments": "^3.0.1",
    "eslint-plugin-flowtype": "^3.1.4",
    "eslint-plugin-import": "^2.14.0",
    "eslint-plugin-jest": "^21.26.2",
    "eslint-plugin-jsx-a11y": "^6.1.2",
    "eslint-plugin-prettier": "^3.0.0",
    "eslint-plugin-react": "^7.11.1",
    "eslint-plugin-react-native": "^3.5.0",
    "flow": "^0.2.3",
    "flow-bin": "^0.84.0",
    "jest": "23.6.0",
    "metro-react-native-babel-preset": "0.48.3",
    "prettier": "1.14.3",
    "react-test-renderer": "16.6.0-alpha.8af6728",
    "remote-redux-devtools": "^0.5.13"
  },

.babelrc

{
  "presets": ["module:metro-react-native-babel-preset"],
  "env": {
    "production": {
    },
    "development": {
      "plugins": [
        ["@babel/plugin-proposal-decorators", { "legacy": true }],
        [
          "flow-runtime",
          {
            "assert": true,
            "annotate": true
          }
        ]
      ]
    }
  }
}
semireg commented 6 years ago

This command can be used to generate the error:

$ react-native bundle --platform ios --entry-file index.js --bundle-output ./ios/main.jsbundle
Loading dependency graph, done.

node_modules/react-native/Libraries/Components/RefreshControl/RefreshControl.js: Property value expected type of string but got object

TypeError: Property value expected type of string but got object
    at Object.validate (/Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-types/lib/definitions/index.js:161:13)
    at validate (/Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-types/lib/index.js:505:9)
    at Object.builder (/Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-types/lib/index.js:466:7)
    at qualifiedToMemberExpression (/Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-plugin-flow-runtime/lib/convert.js:217:19)
    at annotationToValue (/Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-plugin-flow-runtime/lib/convert.js:247:14)
    at annotationToValue (/Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-plugin-flow-runtime/lib/convert.js:245:14)
    at converters.TypeofTypeAnnotation (/Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-plugin-flow-runtime/lib/convert.js:411:15)
    at convert (/Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-plugin-flow-runtime/lib/convert.js:52:16)
    at /Users/devuser/local-dev/rn/RNSemiBoilerplate/node_modules/babel-plugin-flow-runtime/lib/convert.js:533:12
semireg commented 6 years ago

This seems to be related to flow-runtime lacking babel 7 support https://github.com/codemix/flow-runtime/issues/184. Fwiw, "babel-types" is babel version 6. Perhaps that is causing the underlying issue. I've since removed flow-runtime support from master branch of https://github.com/semireg/RNSemiBoilerplate.

semireg commented 6 years ago

This is turning out to be a very interesting error and possibly a bug. I distilled the issue down to this failing test:

export const input = `
// var Foo;
if (true) {
  var Foo = {BAR: {}};
} else {
  var Foo = {BAR: {}};
}

type test = { thing: Foo.BAR };
`;

When var Foo is not declared, the test fails with the same TypeError Property value expected type of string but got null, deep within babel type validators. If you uncomment the declaration, you'll see a standard test failure because the test isn't fully setup (const expected = ``;).

Here's the offending lines from RefreshControl.js:

if (Platform.OS === 'android') {
  const AndroidSwipeRefreshLayout = require('UIManager')
    .AndroidSwipeRefreshLayout;
  var RefreshLayoutConsts = AndroidSwipeRefreshLayout
    ? AndroidSwipeRefreshLayout.Constants
    : {SIZE: {}};
} else {
  var RefreshLayoutConsts = {SIZE: {}};
}

And low and behold... https://github.com/facebook/react-native/commit/a06c0da828f42b804b526a5de35b94b5b4468c1c

💯

I'm going to leave this issue open until it gets released.