Moment: React-Native Release Builds, Deep Crash lors du changement de paramètres régionaux

Créé le 10 oct. 2019  ·  4Commentaires  ·  Source: moment/moment

Lors de l'utilisation de react-native 0.59.10 et de la définition des paramètres régionaux pour momentJS, nous avons détecté un crash très brutal pour nos versions de version uniquement. Ce plantage n'était pas reproductible pour nous avec le débogueur attaché. Ce crash s'est produit pour nous à la fois sur iOS et Android. Les instructions try-catch enveloppant toute l'utilisation du moment n'ont pas détecté le plantage !

Reproduire

  1. Nous collectons les paramètres régionaux/langues que nous voulons essayer via une logique spécifique à l'application. Par exemple ["fr-CA", "en-US", "fr", "en"]
  2. Nous les parcourons un par un plutôt que d'utiliser le setter Array, afin que nous puissions appeler une autre instrumentation et potentiellement intercepter toutes les exceptions JS qui sont levées et essayer le prochain candidat.
  3. Malgré l'appel de moment.locale(localeCandidate) dans un bloc try-catch, l'application plante toujours sur cette ligne⁇

Il s'agissait d'un crash au lancement, mais uniquement pour les versions Release !! Cela rendait très difficile l'extraction des messages d'erreur/journalisation utiles.

Nous avons vu les messages d'erreur suivants via notre intégration Bugsnag et la journalisation de la console système

  • iOS : Exception in HostFunction: Error loading module0from RAM Bundle: unspecified iostream_category error
  • Android : Exception in HostFunction: Module not found: 0
  • Un jour plus tard, sur iOS et Android, nous avons également vu Requiring unknown module "./locale/en-us". -- mais étrangement, cette erreur n'était pas traitée en temps opportun. Peut-être un problème de réaction native / bugsnag.
  1. Le traçage éventuel a trouvé un seul point qui a causé le crash :
    https://github.com/moment/moment/blob/96d0d6791ab495859d09a868803d31a55c917de1/moment.js#L1852 -L1853
    Ce qui, je crois, vient d'ici : https://github.com/moment/moment/blob/6a06e7a0db2c83fb92aa72bbf6bde955d4c75a16/src/lib/locale/locales.js#L55 -L56

Solution : la mise en commentaire de ces deux lignes a interrompu le plantage !

Comportements attendus

  • Moment ne devrait jamais se comporter de manière accidentelle, mais surtout pas dans les versions de version uniquement !
  • Les exceptions de Moment devraient pouvoir être interceptées (nos instructions catch auraient évité un plantage). -- (pourrait être un problème natif de réaction en jouant avec require() dans Release)

Smartphone (veuillez compléter les informations suivantes) :

  • Appareil : iPhone X, iPhone 11 Pro, Samsung (? -- n'a pas capturé exactement quoi), Google Pixel 3, (react-native 0.59.10)
  • Système d'exploitation : iOS et Android
  • iOS JavaScript Core (pour les versions iOS mentionnées ci-dessous) et jsc-android(+intl) 245459.0.0
  • Versions : iOS 12.4 & iOS 13.1, iOS 13.1.2 et iOS 13.2 (beta ?), Android 28, autres.

Environnement spécifique à un moment

  • Heure du Pacifique et peut-être heure de Londres
  • Bug de code affiché de manière cohérente au cours des 2 dernières semaines (2019-10-09) à tout moment de la journée.
  • Autres bibliothèques utilisées : moment-timezone et moment-with-locales, TypeScript, react-native 0.59.10, Apollo-Client et autres

Veuillez exécuter le code suivant dans votre environnement et inclure la sortie :

        console.log([
            new Date().toString(),
            new Date().toLocaleString(),
            new Date().getTimezoneOffset(),
            navigator && navigator.userAgent, // react-native might not have a navigator
            moment.version,
        ]);

Sortir:

[
  "Wed Oct 09 2019 18:52:16 GMT-0700 (PDT)",
  "09/10/2019 à 18:52:16", // This particular device is configured as fr-FR
  420,
  null,
  "2.24.0"
]

Contexte supplémentaire

Billets associés

  • #5214 - Différent car il y a moins de contexte ici, et en utilisant une API différente et en obtenant un message d'erreur différent. Similaire car cela ne se produit que dans les versions de version, ce qui suggère également une réaction native, mais ils ne l'ont reproduit que sur ios-simulator/ios.
  • #3872
  • #2979

Commentaire le plus utile

Les lignes référencées essaient "automatiquement" d'exiger des modules au moment de l'exécution, mais la documentation des paramètres régionaux de chargement indique que si vous utilisez un gestionnaire de packages comme JSPM, vous pouvez charger les paramètres régionaux de import "moment/locale/fr . Étant donné que nous avons besoin que le gestionnaire de packages react-native "sache" que le fichier doit être importé, nous avons essayé ce style d'importation afin que le packager puisse "voir" tous les fichiers qui doivent être regroupés.

En fin de compte, nos lignes d'importation ressemblaient à ceci :

import moment from "moment";
import "moment/min/locales"; // Import all moment-locales -- it's just 400kb
import "moment-timezone";

L'implémentation exacte de require() est injectée par l'environnement d'exécution avec lequel vous travaillez, et c'est certainement quelque chose qui se comporte de manière significativement différente entre les versions Debug & Release.

Dans react-native, il existe également plusieurs variantes de regroupement JavaScript en mode Release, notamment des fichiers tout-en-un, des fichiers tout-en-un et des ensembles RAM. Chacun d'entre eux modifie également le fonctionnement de require. Debug require() connecte au Metro Bundler exécuté sur un serveur http local. C'est probablement très similaire aux serveurs de débogage webpack/jspm/autres, c'est probablement pourquoi l'aliasing require ne pose pas de problèmes dans cet environnement.

Tous les 4 commentaires

Les lignes référencées essaient "automatiquement" d'exiger des modules au moment de l'exécution, mais la documentation des paramètres régionaux de chargement indique que si vous utilisez un gestionnaire de packages comme JSPM, vous pouvez charger les paramètres régionaux de import "moment/locale/fr . Étant donné que nous avons besoin que le gestionnaire de packages react-native "sache" que le fichier doit être importé, nous avons essayé ce style d'importation afin que le packager puisse "voir" tous les fichiers qui doivent être regroupés.

En fin de compte, nos lignes d'importation ressemblaient à ceci :

import moment from "moment";
import "moment/min/locales"; // Import all moment-locales -- it's just 400kb
import "moment-timezone";

L'implémentation exacte de require() est injectée par l'environnement d'exécution avec lequel vous travaillez, et c'est certainement quelque chose qui se comporte de manière significativement différente entre les versions Debug & Release.

Dans react-native, il existe également plusieurs variantes de regroupement JavaScript en mode Release, notamment des fichiers tout-en-un, des fichiers tout-en-un et des ensembles RAM. Chacun d'entre eux modifie également le fonctionnement de require. Debug require() connecte au Metro Bundler exécuté sur un serveur http local. C'est probablement très similaire aux serveurs de débogage webpack/jspm/autres, c'est probablement pourquoi l'aliasing require ne pose pas de problèmes dans cet environnement.

Mes propositions de correctifs :

A. Supprimer complètement le aliasedRequire si ce n'est plus comme ça que vous êtes censé faire les choses + modifier les instructions d'installation à ce sujet ?
B. Détecter react-native vs navigateur ( navigator n'est pas disponible dans react-native, mais il existe d'autres techniques ici), et se comporter différemment selon la situation dans laquelle nous nous trouvons ? par exemple. si react-native && DEV, imprimez une console.error si la locale est théoriquement prise en charge, mais n'a pas encore été required (+ mettre à jour la documentation).
C. Déplacez le aliasedRequire d'une variable locale dans cette fonction vers un "semi-global". moment.aliasedRequire , de cette façon, nous pourrions injecter une fonction no-op/do-nothing afin que aliasedRequire ne puisse plus provoquer le crash dur de react-native.

Je serais heureux d'implémenter l'une de ces options si un responsable peut m'indiquer laquelle il aimerait que j'implémente, et pour les propositions B/C, aidez-moi à affiner l'implémentation exacte qu'il serait enclin à accepter !

@marwahaha --

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

RobinvanderVliet picture RobinvanderVliet  ·  3Commentaires

alvarotrigo picture alvarotrigo  ·  3Commentaires

benhathaway picture benhathaway  ·  3Commentaires

slavafomin picture slavafomin  ·  3Commentaires

tanepiper picture tanepiper  ·  3Commentaires