Sinon: L'espionnage de l'exportation par défaut d'ESM échoue/est inexplicablement bloqué

Créé le 2 mai 2020  ·  21Commentaires  ·  Source: sinonjs/sinon

Décrivez le bogue
Auparavant, une combinaison de import * as foo from 'someModule' + spy(foo, 'default') fonctionnait très bien (et était même répertoriée dans les problèmes de ce lancer manuel .

Comportement prévisible
Sinon pour espionner l'export par défaut.

Contexte (veuillez compléter les informations suivantes) :

  • Version de la bibliothèque : 9.0.2

Contexte supplémentaire
Je suppose que c'est pour éviter TypeError: Cannot assign to read only property

Cependant, cela peut être contourné en utilisant l'ancienne école __defineGetter__

Commentaire le plus utile

@mroderick si vous n'aimez pas les commentaires, ignorez-les. Supprimer activement les commentaires qui aideraient les autres utilisateurs n'est pas du tout utile. Disons que vous supprimez les commentaires, puis vous vous retrouverez avec des utilisateurs similaires venant et commentant encore et encore, ce qui à son tour finirait par verrouiller le fil.

Edit : Vous pouvez également utiliser le bouton "se désinscrire" très facile à trouver. :)

Je suis un mainteneur de ce projet, et j'essaie de lire tous les commentaires.

Je ne peux pas ignorer les commentaires ou me désinscrire d'un numéro parce que les gens décident de ne pas respecter les règles énoncées, d'ignorer les conseils proposés et de détourner le numéro d'origine à leurs propres fins. Il est de ma responsabilité d'essayer de résoudre les problèmes avec politesse, tact et efficacité. Les problèmes de piratage rendent le soutien de la communauté plus difficile que nécessaire.

S'il vous plaît, aidez-moi à vous aider ainsi que le reste de la communauté.

Tous les 21 commentaires

Il n'y a en fait aucune mention de __defineGetter__ dans cet ancien numéro, juste Object.defineProperty, et seulement pour traiter les modules Webpack transpilés, pas les modules ECMAScript réels. Je ne dis pas que cela ne fonctionne pas, cependant 😄

Pourriez-vous publier un exemple simple de javascript vanille où vous pouvez écraser les exportations (non par défaut) d'un module ES importé ? Vous avez besoin de deux fichiers some-module.mjs et file-that-overwrites.mjs pour tester cela et ils doivent avoir l'extension .mjs pour Node pour activer la syntaxe import .

Cette suite de tests documente le comportement actuel de Sinon.

Pour info, le talon ne fonctionne pas pour [email protected]+ ici

@ fatso83, cet ancien problème ne le fait pas (mais je n'ai pas dit que c'était le cas 😜).

Ce que je veux dire, c'est que Sinon renvoie une erreur lors de la détection d'un ESM car plus tard, le code Object.defineProperty(object, property, methodDesc) échouera avec TypeError: Cannot assign to read only property 'default' . Cependant, __defineGetter__ n'échouerait pas :

object.__defineGetter__(property, methodDesc.value);

Buuuut, quand j'ai essayé de modifier le code Sinon et de l'exécuter, j'ai eu une erreur indéfinie sur __defineGetter__ (peut-être un mode strict ou quelque chose ?).

Je pense donc peut-être à une autre manière, comme recréer l'objet (avec de nouvelles valeurs) au lieu de remplacer ses propriétés. Plus complexe, mais au moins faisable.

Pour info, le talon ne fonctionne pas pour [email protected]+ ici

Même problème ici dernière version de travail 3.8.3

@zorji et @aelbore : Je ne sais pas pourquoi vous postez dans ce fil. Si vous signalez un nouveau problème, veuillez créer un problème distinct et suivre les étapes normales de signalement (comment vérifier, code réel, versions, etc.). Nous ne prenons pas en charge Typescript et ne l'avons jamais dit, même si cela devrait fonctionner, bien sûr, mais les détails dépendront de votre étape de transpilation.

Je pense donc peut-être à une autre manière, comme recréer l'objet (avec de nouvelles valeurs) au lieu de remplacer ses propriétés. Plus complexe, mais au moins faisable.

Est-ce? Un module ES est une fonctionnalité statique qui est liée au moment de l'exécution, AFAIK, et vous ne pouvez pas la modifier.

les entités importées sont disponibles dans le fichier, ce sont des vues en lecture seule de l'entité qui a été exportée. Vous ne pouvez pas modifier la variable qui a été importée, mais vous pouvez toujours modifier des propriétés similaires à const. De plus, ces fonctionnalités sont importées en tant que liaisons dynamiques, ce qui signifie qu'elles peuvent changer de valeur même si vous ne pouvez pas modifier la liaison contrairement à const.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules

J'ai hâte de voir si vous pouvez aller quelque part avec cela, mais je serais surpris si vous (ou n'importe qui !) le faisiez.

Ce problème a été automatiquement marqué comme obsolète car il n'a pas eu d'activité récente. Il sera fermé si aucune autre activité ne se produit. Merci pour vos contributions.

Mauvais robot. Cette chose stupide peut-elle être désactivée?

@OmgImAlexis pensez -vous qu'il y a une raison de garder ce problème ouvert ?

Chers amis, essayez de garder le problème sur le point et ne discutez que de ce qui est mentionné dans le message d'origine.

Il est déjà assez difficile pour les responsables de passer notre temps libre non rémunéré à soutenir des logiciels libres, sans avoir à parcourir des sujets orthogonaux dans le même numéro.

Nous sommes ravis que Sinon (un outil JavaScript) puisse également être utile dans la communauté TypeScript. Cependant, comme l'a dit @fatso83 , nous ne prenons pas en charge Typescript .

Tout autre commentaire hors sujet sur TypeScript dans ce numéro sera supprimé.

Tout autre commentaire hors sujet sur TypeScript dans ce numéro sera supprimé.

@mroderick si vous n'aimez pas les commentaires, ignorez-les. Supprimer activement les commentaires qui aideraient les autres utilisateurs n'est pas du tout utile. Disons que vous supprimez les commentaires, puis vous vous retrouverez avec des utilisateurs similaires venant et commentant encore et encore, ce qui à son tour finirait par verrouiller le fil.

Edit : Vous pouvez également utiliser le bouton "se désinscrire" très facile à trouver. :)

Ack désolé, j'étais très occupé au travail. J'essaierai de jeter un oeil dans quelques semaines. Plusieurs bibliothèques accomplissent cela, donc cela doit être possible 😁

@mroderick si vous n'aimez pas les commentaires, ignorez-les. Supprimer activement les commentaires qui aideraient les autres utilisateurs n'est pas du tout utile. Disons que vous supprimez les commentaires, puis vous vous retrouverez avec des utilisateurs similaires venant et commentant encore et encore, ce qui à son tour finirait par verrouiller le fil.

Edit : Vous pouvez également utiliser le bouton "se désinscrire" très facile à trouver. :)

Je suis un mainteneur de ce projet, et j'essaie de lire tous les commentaires.

Je ne peux pas ignorer les commentaires ou me désinscrire d'un numéro parce que les gens décident de ne pas respecter les règles énoncées, d'ignorer les conseils proposés et de détourner le numéro d'origine à leurs propres fins. Il est de ma responsabilité d'essayer de résoudre les problèmes avec politesse, tact et efficacité. Les problèmes de piratage rendent le soutien de la communauté plus difficile que nécessaire.

S'il vous plaît, aidez-moi à vous aider ainsi que le reste de la communauté.

Ce problème a été automatiquement marqué comme obsolète car il n'a pas eu d'activité récente. Il sera fermé si aucune autre activité ne se produit. Merci pour vos contributions.

Mauvais robot.

@jshado1 pensez -vous que ce problème devrait rester ouvert?

Je vois que @ jshado1 dit que cela fonctionnait bien, mais je ne pense pas que cela ait jamais fonctionné en javascript non transpilé à la vanille. Parce qu'il ne devrait pas. Cela peut fonctionner lors de la transpilation de modules à l'aide de Babel/Webpack ou similaire, car vous émulez uniquement des modules et ne créez pas réellement un objet en lecture seule dans le runtime (ce que sont les modules). La clause throw a été ajoutée par moi, car elle _serait autrement_ un peu plus tard lorsque vous avez essayé de changer l'inchangeable. Les runtimes/chargeurs de modules tels que esm modifient un peu le champ, cependant.

Si vous pensez que le comportement est incorrect, je suggère simplement de modifier node_modules/sinon/lib/sinon/spy.js , de supprimer la clause throws et de faire rapport. Pas d'émotions fortes. Promesse :licorne: :arc-en-ciel:

Pour citer @RyanCavanaugh (https://github.com/microsoft/TypeScript/issues/38568#issuecomment-628860591)

Si vous ciblez commonjs mais que vous écrivez des importations/exportations de modules ES, TS essaiera toujours de vous donner le comportement du module ES.

Ce code n'est effectivement pas un ES légal, car il tente de modifier (indirectement via sinon.stub ) une propriété en lecture seule (les propriétés de quelque chose importé avec import * as name ne sont pas modifiables). Cela n'aurait jamais dû fonctionner.

C'est essentiellement ce que j'ai dit. Donc, fermeture, car les résultats de ceci dépendent entièrement de l'utilisation d'une étape de transpilation, de la façon dont le transpiler effectue cette étape, etc. S'il essaie de créer un résultat quelque peu conforme à la spécification ESM, _il ne devrait pas fonctionner_ comme le les exportations des modules ES sont immuables (pas les objets réels liés par ces exportations, bien sûr).

@mroderick @fatso83 désolé, je n'ai jamais eu ce temps libre et j'ai été critiqué au travail depuis. Cela fait plusieurs mois, mais si ma mémoire est bonne, j'avais à l'époque un exemple de travail _très_ rudimentaire (et sale) pour confirmer que cela fonctionnait (mais en effet _probablement_ n'aurait pas dû). MAIS, je pense que ce n'est pas la voie à suivre car je pense qu'il existe / qu'il y aura un moyen officiel de le faire via les chargeurs ems : https://github.com/nodejs/node/blob/master/doc/api/esm .md#chargeurs

Celles-ci sont actuellement instables (il est explicitement indiqué qu'elles seront bientôt modifiées), donc attendez probablement jusqu'à ce qu'elles deviennent plus stables. Mais une fois qu'ils le font, je pense que c'est la voie à suivre.

Mise à jour : ceci est actuellement discuté dans nodejs/node#36396.

Je pense que ma proposition dans ce commentaire rendrait cela très simple. Un utilisateur pourrait fournir manuellement une carte, et le chargeur esm pourrait l'utiliser pour remplacer :

// const mocksMap = { 'serviceA.js': 'serviceA.mock.js' };

const mock = mocksMap[importPath]; // note: it's not called `importPath` in the loader hooks
if (mock) // …

et/ou, le chargeur esm pourrait rechercher une correspondance fictive basée sur le nom de fichier (exemple quick n dirty):

const ext = path.ext(importPath);
const filename = path.basename(importPath, ext);
const mockFile = await import(`${filename}.mock${ext}`);

if (mockFile) // …

@ jshado1 Merci d'avoir fourni ce lien. Le problème lié consiste essentiellement à essayer de trouver un moyen standardisé de gérer le problème de la substitution des dépendances sur le _niveau de lien_, ce qui est similaire à ce que font des outils tels que rewire et proxyquire (que nous décrivons dans ce mode d'emploi sur notre page d'accueil ) . Dans tous les cas, ce n'est pas quelque chose que Sinon devrait ou va résoudre, car c'est hors de portée et la façon de le résoudre dépendra entièrement de votre environnement.

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