Kudo/react-native-v8

Promise has some unusual behavior.

NiuGuohui opened this issue · 2 comments

I plan to remove the @babel/plugin-transform-regenerator to implement a simplified package content.
After removing it, RN will use the native v8 Promise, but this Promise will not trigger when communicating with Native.

So, can I use the native Promise and other capabilities without metro-polyfill?

This is the node_modules/metro-react-native-babel-preset/src/configs/main.js file, which contains my changes:

/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 */
"use strict";

function ownKeys(object, enumerableOnly) {
  var keys = Object.keys(object);

  if (Object.getOwnPropertySymbols) {
    var symbols = Object.getOwnPropertySymbols(object);
    if (enumerableOnly)
      symbols = symbols.filter(function(sym) {
        return Object.getOwnPropertyDescriptor(object, sym).enumerable;
      });
    keys.push.apply(keys, symbols);
  }

  return keys;
}

function _objectSpread(target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = arguments[i] != null ? arguments[i] : {};

    if (i % 2) {
      ownKeys(Object(source), true).forEach(function(key) {
        _defineProperty(target, key, source[key]);
      });
    } else if (Object.getOwnPropertyDescriptors) {
      Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
    } else {
      ownKeys(Object(source)).forEach(function(key) {
        Object.defineProperty(
          target,
          key,
          Object.getOwnPropertyDescriptor(source, key)
        );
      });
    }
  }

  return target;
}

function _defineProperty(obj, key, value) {
  if (key in obj) {
    Object.defineProperty(obj, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true
    });
  } else {
    obj[key] = value;
  }

  return obj;
}

function _toConsumableArray(arr) {
  return (
    _arrayWithoutHoles(arr) ||
    _iterableToArray(arr) ||
    _unsupportedIterableToArray(arr) ||
    _nonIterableSpread()
  );
}

function _nonIterableSpread() {
  throw new TypeError(
    "Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
  );
}

function _unsupportedIterableToArray(o, minLen) {
  if (!o) return;
  if (typeof o === "string") return _arrayLikeToArray(o, minLen);
  var n = Object.prototype.toString.call(o).slice(8, -1);
  if (n === "Object" && o.constructor) n = o.constructor.name;
  if (n === "Map" || n === "Set") return Array.from(o);
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
    return _arrayLikeToArray(o, minLen);
}

function _iterableToArray(iter) {
  if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter))
    return Array.from(iter);
}

function _arrayWithoutHoles(arr) {
  if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}

function _arrayLikeToArray(arr, len) {
  if (len == null || len > arr.length) len = arr.length;

  for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];

  return arr2;
}

const lazyImports = require("./lazy-imports");

const passthroughSyntaxPlugins = require("../passthrough-syntax-plugins");

function isTypeScriptSource(fileName) {
  return !!fileName && fileName.endsWith(".ts");
}

function isTSXSource(fileName) {
  return !!fileName && fileName.endsWith(".tsx");
}

const defaultPlugins = [
  [require("@babel/plugin-syntax-flow")],
  [require("@babel/plugin-syntax-dynamic-import")],
  [require("@babel/plugin-syntax-export-default-from")],
].concat(_toConsumableArray(passthroughSyntaxPlugins), [
  [require("@babel/plugin-transform-function-name")],
  [require("@babel/plugin-transform-literals")],
  [require("@babel/plugin-transform-sticky-regex")],
  [require("@babel/plugin-transform-unicode-regex")],
]);
const exponentiationOperator = [
  require("@babel/plugin-transform-exponentiation-operator")
];
const reactDisplayName = [
  require("@babel/plugin-transform-react-display-name")
];
const reactJsxSource = [require("@babel/plugin-transform-react-jsx-source")];
const reactJsxSelf = [require("@babel/plugin-transform-react-jsx-self")];
const babelRuntime = [
  require("@babel/plugin-transform-runtime"),
  {
    helpers: true,
    regenerator: true
  }
];

const getPreset = (src, options) => {
  const isNull = src == null;
  const extraPlugins = [];

  if (!options.useTransformReactJSXExperimental) {
    extraPlugins.push([require("@babel/plugin-transform-react-jsx")]);
  }

  if (!options || !options.disableImportExportTransform) {
    extraPlugins.push(
      [require("@babel/plugin-proposal-export-default-from")],
      [
        require("@babel/plugin-transform-modules-commonjs"),
        {
          strict: false,
          strictMode: false,
          // prevent "use strict" injections
          lazy:
            options && options.lazyImportExportTransform != null
              ? options.lazyImportExportTransform
              : importSpecifier => lazyImports.has(importSpecifier),
          allowTopLevelThis: true // dont rewrite global `this` -> `undefined`
        }
      ]
    );
  }


  if (isNull || src.indexOf("**") !== -1) {
    extraPlugins.push(exponentiationOperator);
  }

  if (
    isNull ||
    src.indexOf("React.createClass") !== -1 ||
    src.indexOf("createReactClass") !== -1
  ) {
    extraPlugins.push(reactDisplayName);
  }

  if (options && options.dev && !options.useTransformReactJSXExperimental) {
    extraPlugins.push(reactJsxSource);
    extraPlugins.push(reactJsxSelf);
  }

  if (!options || options.enableBabelRuntime !== false) {
    extraPlugins.push(babelRuntime);
  }

  return {
    comments: false,
    compact: true,
    overrides: [
      // the flow strip types plugin must go BEFORE class properties!
      // there'll be a test case that fails if you don't.
      {
        plugins: [require("@babel/plugin-transform-flow-strip-types")]
      },
      {
        plugins: defaultPlugins
      },
      {
        test: isTypeScriptSource,
        plugins: [
          [
            require("@babel/plugin-transform-typescript"),
            {
              isTSX: false,
              allowNamespaces: true
            }
          ]
        ]
      },
      {
        test: isTSXSource,
        plugins: [
          [
            require("@babel/plugin-transform-typescript"),
            {
              isTSX: true,
              allowNamespaces: true
            }
          ]
        ]
      },
      {
        plugins: extraPlugins
      }
    ]
  };
};

module.exports = options => {
  if (options.withDevTools == null) {
    const env = process.env.BABEL_ENV || process.env.NODE_ENV;

    if (!env || env === "development") {
      return getPreset(
        null,
        _objectSpread(
          _objectSpread({}, options),
          {},
          {
            dev: true
          }
        )
      );
    }
  }

  return getPreset(null, options);
};

module.exports.getPreset = getPreset;

@Kudo You can test with this code:
index.js

(async () => {
  function sleep(s) {
    return new Promise(r => setTimeout(r, s));
  }
  console.log(Date.now());
  await sleep(5000);
// In fact we waited more than 5 seconds.
  console.log(Date.now());
})();
Kudo commented

hi there! do you mind to create a github repository of minimal reproducible example for me? because i've tried to disable Promise polyfill and regenerator runtime and it works for me.