Kann ich die Optimierung deaktivieren, damit In-Scope-Variablen aus Abschlüssen nicht „optimiert“ werden?

11

Als Nebenprodukt der Codeoptimierung, die von modernen Browsern beim Debuggen durchgeführt wird, können Sie nicht alle Variablen "sehen", die "sachlich" im Geltungsbereich liegen. Dies ist bekannt und wurde in einer früheren Frage hier auf SO angesprochen . Diese Funktion ist zwar in der Produktion sehr nützlich, nervt mich aber während der Entwicklung sehr, verlangsamt mich jedoch (das sollte offensichtlich sein).

Meine Frage ist nun, gibt es eine Möglichkeit, dieses Verhalten auszuschalten? Kann ich eine Konfigurationsdatei bearbeiten oder gibt es ein Browser-Plugin oder eine "spezielle Build-Version für Entwickler" der ausführbaren Browser-Datei? Ich liebe es, meinen Code sofort in die Konsole einzugeben, wenn ich neuen Code schreibe, also nervt mich das wirklich.

visualSummaryIffalseConsoleLog

UPDATE / EDIT

Hier ist eine Teillösung, die Paul1365972 zu verdanken ist.

Sie müssen den Chrome-Browser über die Befehlszeile mit speziellen Optionen wie den folgenden starten:

  1. Schließen Sie Chrome vollständig
  2. Führen Sie Chrome von der Konsole aus, wobei "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe" --js-flags="--allow-natives-syntax" für Windows andere Betriebssysteme ähnlich sind.
  3. Öffnen Sie die Entwicklerkonsole und führen Sie sie aus "%GetHeapUsage()". Wenn Sie Chrome mit dieser Option ordnungsgemäß gestartet haben, wird eine Nummer in der Konsole protokolliert. Andernfalls wird ein Syntaxfehler angezeigt.

Mit diesem Befehlszeilenflag können Sie mit Befehlen %, die mit Syntaxfehlern in einfachem JavaScript beginnen, mit der V8-Engine kommunizieren. Eine Liste der verfügbaren V8-Befehle dieser Art wurde in Pauls Antwort gegeben .

Es gibt %NeverOptimizeFunction()auf dieser Liste etwas, das so aussah, als müsste ich einfach anrufen und damit fertig sein. Leider macht diese Funktion nicht das, was ich mir erhofft hatte, wie im nächsten Screenshot gezeigt.

Lorem noch nicht definiert

(((Der andere Link aus Pauls Antwort (v8-natives-Knotenmodul) ist für uns hier in diesem Zusammenhang nicht wichtig. Alles, was er tut, ist, Einzeiler um die Funktionsaufrufe "%" zu wickeln, damit der Code nicht abstürzt Browser, die nicht v8 sind.)))

(((Ich erinnere mich an eine Zeit, als dies funktionierte (als diese Optimierung noch nicht erfunden / implementiert wurde). Ich weiß nicht, wie lange es her ist. Zehn Jahre? 15 Jahre? So ähnlich. Was war die letzte Chrome-Version (wenn any) und was war die letzte Firefox-Version (hier sicherer, dass sie existiert), in der Sie etwas tun konnten? Sie erhalten nicht das Kopfgeld, aber Sie erhalten eine positive Bewertung, wenn Sie es zufällig wissen und als Antwort veröffentlichen .)))

DIE LÖSUNG

DANKE PETR SRNICEK

Hacky Fix

NEUE FRAGE

Petrs Lösung hilft zwar viel, ist aber nicht perfekt. Diese Frage wird zu lang, daher habe ich eine neue Frage gestellt, wie die Lösung von Petr verbessert werden kann. (Ich könnte diese Frage natürlich hier bearbeiten, aber das würde sich "unhistorisch" anfühlen, wenn Sie wissen, was ich meine.)

Mathheadinclouds
quelle
unbeabsichtigte Folgen, Kapitel Zehntausend. Diese Optimierung wirkt sich negativ auf meinen Codierungsstil aus. Ich verwende die altmodische for-Schleife (anstelle von .map, .forEach, .reduce) mehr als sonst, nur damit ich nicht auf dieses Problem stoße.
Mathheadinclouds
Die v8-nativesBibliothek packt nur die wichtigen% -Aufrufe in Code in eine einfache Bibliothek, die sich noopsin einem Browser oder Knoten befinden sollte, der nicht im speziellen Flag --allow-natives-syntax gestartet wurde.
Nathanael
Ich habe einige Tests durchgeführt, die Funktion 'bodyOnLoad' ist sowieso nicht optimiert. Die Verwendung der internen Befehle, um zu versuchen, die Optimierung zu erzwingen, führt also zu nichts.
Nathanael
@Nathanael: Der wichtige Anruf ist, dass %NeverOptimizeFunction(foo)ich es gerade auch für bodyOnload genannt habe, "nur weil" und dachte "gut, es wird nicht weh tun". Das Problem ist, dass fooes NICHT so deoptimiert wird, wie ich es mir erhofft hatte. Variable loremist unsichtbar. Nehmen wir an, ich möchte einen Code schreiben, der in die Funktion foo gehen soll. Anstatt es in meinen Texteditor einzugeben, tippe ich es in die Entwicklungskonsole (während der Debugger bei foo sitzt), überprüfe, ob es das tut, was ich will, und kopiere es dann von der Konsole in meinen Texteditor. So liebe ich es zu arbeiten. Und kann nicht. Wegen der Optimierung. Kapiert?
Mathheadinclouds
1
Ich habe mehrere unserer Experimente mit verschiedenen --js-flags(einschließlich mehrerer TurboFan-bezogener ) sowie mit mehreren nativen V8-Befehlen durchgeführt, bevor Paul1365972 seine Antwort veröffentlichte, aber ich konnte das gewünschte Verhalten nicht erreichen. Ich glaube, dass dieser Ansatz eine Sackgasse sein könnte. Es kann sinnvoll sein [v8], dieser Frage ein Tag hinzuzufügen . Jemand mit einem tiefen Verständnis des Innenlebens von V8 kann möglicherweise klären, ob dies der richtige Weg ist, oder Sie vielleicht in die richtige Richtung weisen.
Petr Srníček

Antworten:

2

Sie können auf alle Variablen zugreifen, indem Sie die Debugger-Anweisung in eine Auswertung wie folgt einschließen : eval("debugger;");. Diese hackige Lösung fügt dem Aufrufstapel jedoch eine weitere anonyme Funktion hinzu und ist offensichtlich nicht nützlich für Haltepunkte, die manuell in DevTools festgelegt werden.

Dies scheint keine sehr gute Lösung zu sein, aber da es die einzige ist, die das beabsichtigte Verhalten bisher erreicht, poste ich es als Antwort.

Petr Srníček
quelle
es überrascht mich irgendwie, dass das funktioniert. Weißt du, ich habe versucht, eval ("lorem") einzugeben, und das ergab den gleichen Fehler "lorem ist nicht definiert". Es macht für mich nicht viel Sinn, dass die Eingabe von eval ("lorem") auf der Konsole (während der Debugger-Anweisung in Funktion foo) etwas anderes tun sollte als das, was eval ("Debugger") tut - erwarten Sie, drucken Sie "ipsum" zur Konsole. Aber sie sind sehr unterschiedlich. Seltsam.
Mathheadinclouds
Das ist eine interessante Arbeit. Es ist ein bisschen hackig, da Sie die Debugger-Anweisung nicht verlassen können (Sie müssen nur manuell zur Quelldatei wechseln), da Sie sonst den gesamten Stapel verlieren und zu der Funktion zurückkehren, die eval aufgerufen hat. Der reduzierte Stapel lässt den anderen Kontext fehlen.
Nathanael
Man kann diesen Trick folgendermaßen ändern: Anstelle von eval ("Debugger") setzen Sie einfach eval ("") - aber viele davon sind über den gesamten Code verteilt, überall dort, wo Sie glauben, dass Sie einen "erweiterten Haltepunkt" wünschen. Sie können dann einen Haltepunkt (mit den Entwicklungswerkzeugen) festlegen, an dem sich eine dieser eval ('') - Anweisungen befindet, und sobald Sie dort anhalten, "treten Sie ein". Ich denke darüber nach, einen kleinen Transpiler zu schreiben (großes Wort für eine kleine Sache, die ich mache), der diese Anweisungen am Anfang jeder Funktion setzt. stackoverflow.com/questions/59159996/…
mathheadinclouds
Ich habe gerade versucht, eval ("Debugger") durch eval () zu ersetzen. Debugger und erzielte je nach Verwendung von Firefox oder Chrome unterschiedliche Ergebnisse. i.stack.imgur.com/wy5WT.png
mathheadinclouds
3

Google Chrome verwendet die V8 JS-Engine. Sie können native Aufrufe mit dem Flag --allow-natives-syntax aktivieren. Dadurch werden viele nützliche Debugging-Funktionen (vollständige Liste hier ) wie die gesuchte angezeigt:% NeverOptimizeFunction () . Ohne dieses Flag wären diese Aufrufe eine unzulässige Syntax. Seien Sie daher bei der Bereitstellung vorsichtig (oder verwenden Sie die v8-Natives- Bibliothek).

Um diese Funktion zu aktivieren, öffnen Sie Chrome einfach mit --js-flags = "- allow-natives-syntax" (verwenden Sie dies nur zum Debuggen vertrauenswürdiger Websites, da dies nicht vertrauenswürdigem js-Code Zugriff auf Dinge gewähren kann, die Sie wirklich nicht möchten Zugang haben zu).

Paul1365972
quelle
Vielen Dank. Bitte lesen Sie meine aktualisierte Frage. Es scheint ziemlich wahrscheinlich, dass Sie hier die Lösung haben, aber ich brauche etwas mehr Klarstellung, um sie in Gang zu bringen. Wenn dies funktioniert, haben Sie das Kopfgeld verdient.
Mathheadinclouds
tl; dr benutze stattdessen --js-flags = "- allow-natives-syntax". Um die Funktion zu aktivieren, muss die V8 JS-Engine mit dem Flag --allow-natives-syntax gestartet werden. Sie können sie jedoch nicht direkt starten. Dies ist ein Chromes-Job. Sie müssen Chrom also anweisen, den Motor mit der Flagge zu starten. Wie machen Sie das? Übergeben Sie einfach das erwähnte Motorflag über --js-flags = <Ihr Flag hier> an Chrome.
Paul1365972
Nee. Ich habe es noch einmal versucht, um auf der sicheren Seite zu sein. Ich habe beide --allow-natives-syntaxund --js-flags="--allow-natives-syntax"mehrere Male als "das, was ich nach 'chrome' in der Betriebssystemkonsole tippe" ausprobiert . Wenn ich das nicht alles selbst versucht hätte, würde ich auch denken, dass ein Tippfehler die wahrscheinlichste Erklärung ist. Ich habe einen weiteren Screenshot gemacht. i.stack.imgur.com/7cpPP.png Tippfehler anzeigen ? Bitte geben Sie mir eine ehrliche Antwort: Haben Sie gerade "den Artikel gelesen und verstanden" (um klar zu sein, nichts Falsches daran, wenn Sie nicht mehr behaupten), oder haben Sie das alles tatsächlich auf Ihrem Computer ausprobiert? thx
mathheadinclouds
Nur eine Vermutung: Könnte es sein, dass ich die ausführbare Chrome-Datei nicht mit dieser Option starte, sondern die Chrome C ++ (oder was auch immer) -Quellen mit dieser Option kompiliere ?
Mathheadinclouds
1
Das ist seltsam, ich habe es gerade getestet und es hat gut funktioniert, es ist kein Kompilieren erforderlich. Ich werde nur genau das schreiben, was ich getan habe, damit es kein Missverständnis gibt. 1. Schließen Sie Chrome vollständig. 2. Führen Sie Chrome von der Konsole aus mit "C: / Programme (x86) /Google/Chrome/Application/chrome.exe" aus. --Js-flags = "- allow-natives-syntax" 3. Öffnen Sie Entwicklerkonsole und führen Sie "% GetHeapUsage ()" aus, um zu testen, ob alles funktioniert
Paul1365972
0

Ich hoffe wirklich, dass diese Frage eine WIRKLICHE Antwort hat. Was folgt, ist keine wirkliche Antwort, es ist eine Behelfslösung. Ich habe ein Hilfsprogramm geschrieben, mit dem Sie if (false) { console.log(variables, from, closures); }mithilfe statischer Analyse einen dummen Hilfscode des Formulars erstellen können (siehe Abbildung). Sie fügen Ihren Code ein, die dumme Anweisung wird erstellt, Sie können sie kopieren, dann brauchen Sie sie nicht um es zu tippen. Ich weiß nicht, ob das viel hilft, da all das Kopieren und Einfügen auch Zeit braucht, aber das habe ich bekommen.

Bildschirmfoto

Geige

Mathheadinclouds
quelle