czy mogę wyłączyć optymalizację, aby zmienne zawarte w zamknięciach nie były „zoptymalizowane”

11

Jako produkt uboczny optymalizacji kodu wykonywanej przez nowoczesne przeglądarki, podczas debugowania nie można „zobaczyć” wszystkich zmiennych, które „faktycznie” są w zakresie. Jest to dobrze znane i zostało poruszone w poprzednim pytaniu tutaj na SO . Ta funkcja, choć z pewnością przydatna w produkcji, bardzo mnie denerwuje podczas opracowywania, ale spowalnia mnie (to powinno być oczywiste).

Teraz moje pytanie brzmi: czy jest jakiś sposób, aby wyłączyć to zachowanie? Czy mogę edytować jakiś plik konfiguracyjny, czy jest wtyczka do przeglądarki, czy może jest „specjalna wersja kompilacji dla programistów” pliku wykonywalnego przeglądarki? Uwielbiam pisać mój kod w konsoli od razu, gdy piszę nowy kod, więc to mnie naprawdę wkurza.

visualSummaryIffalseConsoleLog

AKTUALIZACJA / EDYCJA

Oto częściowe rozwiązanie, podziękowania dla Paul1365972.

Musisz uruchomić przeglądarkę chrome z wiersza poleceń, ze specjalnymi opcjami, takimi jak:

  1. Zamknij całkowicie Chrome
  2. Uruchom Chrome z konsoli z "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe" --js-flags="--allow-natives-syntax" podobnym systemem Windows.
  3. Otwórz konsolę programisty i uruchom "%GetHeapUsage()". Jeśli poprawnie uruchomiłeś Chrome z tą opcją, pewna liczba zostanie zalogowana do konsoli, w przeciwnym razie pojawi się błąd składniowy.

Za pomocą tej flagi wiersza poleceń można „rozmawiać z silnikiem V8” za pomocą poleceń rozpoczynających się od %, które są błędami składniowymi w zwykłym JavaScript. Lista dostępnych poleceń V8 tego rodzaju została podana w odpowiedzi Paula .

Na %NeverOptimizeFunction()tej liście jest coś, co wyglądało na coś, co musiałbym po prostu zadzwonić i skończyć z tym. Niestety, funkcja ta nie spełnia moich oczekiwań, jak pokazano na następnym zrzucie ekranu.

lorem nadal nie jest zdefiniowany

((( Drugi link z odpowiedzi Paula (moduł węzła v8-natives)) nie ma dla nas tutaj znaczenia w tym kontekście. Wszystko, co robi, to owija linijki wokół wywołań funkcji „%”, aby kod się nie zawiesił przeglądarki, które nie są wer. 8)))

(((Pamiętam czas, kiedy to działało (kiedy ta optymalizacja nie została jeszcze wynaleziona / wdrożona). Nie wiem, jak dawno temu. Dziesięć lat? 15 lat? Coś w tym rodzaju. Jaka była ostatnia wersja Chrome (jeśli jakikolwiek) i jaka była ostatnia wersja Firefoksa (bardziej pewna, że ​​istnieje), gdzie możesz to zrobić? Nie dostaniesz nagrody, ale dostaniesz opinię, jeśli zdołasz ją poznać i opublikować jako odpowiedź .)))

ROZWIĄZANIE

DZIĘKUJĘ PETR SRNICEK

hacky fix

NOWE PYTANIE

Chociaż rozwiązanie Petra bardzo pomaga, nie jest idealne. To pytanie staje się zbyt długie, więc opublikowałem nowe pytanie, w jaki sposób można ulepszyć rozwiązanie Petra. (Mógłbym oczywiście edytować to pytanie tutaj, ale byłoby to „niehistoryczne”, jeśli wiesz, co mam na myśli).

mathheadinclouds
źródło
niezamierzone konsekwencje, rozdział dziesiąty. ta optymalizacja ma negatywny wpływ na mój styl kodowania. Używam staroświeckiej pętli for (zamiast .map, .forEach, .reduce) bardziej niż w innym przypadku, po prostu unikam tego problemu.
mathheadinclouds
v8-nativesBiblioteka właśnie owija ważnych% połączeń w kodzie w prosty biblioteki, które powinny być noopsw przeglądarce lub węzła, który nie został uruchomiony specjalny flagą --allow-tubylcy-składni ..
Natanaela
Przeprowadziłem kilka testów, funkcja bodyOnLoad i tak nie jest zoptymalizowana; więc używanie poleceń wewnętrznych w celu zmuszenia go do dezoptymalizacji nic nie robi.
Nathanael
@Nathanael: Ważnym wezwaniem jest to, %NeverOptimizeFunction(foo)że właśnie nazwałem to dla bodyOnload, „tylko dlatego, że”, myśląc „no cóż, nie będzie bolało”. Problem polega na tym, że fooNIE jest on dezoptymalizowany w sposób, na jaki liczyłem. Zmienna loremjest niewidoczna. Powiedzmy, że chcę napisać kod, który ma przejść do funkcji foo. Zamiast wpisywać go w moim edytorze tekstu, piszę go w konsoli programisty (podczas gdy debugger siedzi w foo), sprawdzam, czy robi to, co chcę, a następnie kopiuję / wklejam go z konsoli do mojego edytora tekstu. Tak uwielbiam pracować. I nie mogę. Z powodu optymalizacji. Zdobyć?
mathheadinclouds
1
Spędziłem kilka naszych eksperymentów z różnymi --js-flags(w tym kilkoma związanymi z TurboFan ), a także z kilkoma natywnymi poleceniami V8, zanim Paul1365972 opublikował swoją odpowiedź, ale nie byłem w stanie osiągnąć pożądanego zachowania. Uważam, że takie podejście może być ślepym zaułkiem. Warto dodać [v8]tag do tego pytania. Ktoś, kto dogłębnie rozumie wewnętrzne funkcjonowanie V8, może wyjaśnić, czy to jest właściwa droga, czy może skieruje cię we właściwym kierunku.
Petr Srníček

Odpowiedzi:

2

Możesz uzyskać dostęp do wszystkich zmiennych owijając oświadczenie debuggera w eval tak: eval("debugger;");. To zhackowane rozwiązanie dodaje kolejną anonimową funkcję do stosu wywołań i oczywiście nie ma zastosowania do punktów przerwania, które są ustawiane ręcznie w DevTools.

Nie wydaje się to być dobrym rozwiązaniem, ale ponieważ jest to jedyne, które dotychczas osiągnęło zamierzone zachowanie, zamieszczam je jako odpowiedź.

Petr Srníček
źródło
zaskakuje mnie, że to działa. Wiesz, próbowałem wpisać eval („lorem”), co dało ten sam błąd „lorem nie jest zdefiniowany”. Nie ma dla mnie większego sensu, że pisanie eval („lorem”) na konsoli (podczas gdy polecenie debuggera w funkcji foo) powinno robić cokolwiek innego niż to, co robi eval („debugger”) - spodziewaj się, wypisz „ipsum” do konsoli. Ale są bardzo różne. Dziwne.
mathheadinclouds
To ciekawe obejście. Jest to trochę zhackowane, ponieważ nie można wyjść z instrukcji debuggera (wystarczy ręcznie przełączyć się do pliku źródłowego), w przeciwnym razie stracisz cały stos i powrócisz do funkcji, która wywołała eval; pozostawiając zredukowany stos, pomijając inny kontekst.
Natanael,
można zmodyfikować tę sztuczkę w ten sposób: zamiast eval („debugger”), po prostu eval („”) - ale wiele z nich, rozmieszczonych w całym kodzie, wszędzie tam, gdzie uważasz, że możesz chcieć „rozszerzonego punktu przerwania”. Następnie możesz ustawić punkt przerwania (za pomocą narzędzi deweloperskich), w którym znajduje się jedna z tych instrukcji eval (''), a kiedy się tam zatrzymasz, „wkraczasz”. Zastanawiam się nad napisaniem małego transpilatora (dużego słowa na małą rzecz, którą robię), umieszczając te instrukcje na początku każdej funkcji. stackoverflow.com/questions/59159996/…
mathheadinclouds
Właśnie próbowałem zastąpić eval („debugger”) przez eval (); debugger i uzyskał różne wyniki, w zależności od użycia Firefoxa lub Chrome. i.stack.imgur.com/wy5WT.png
mathheadinclouds
3

Google Chrome używa silnika JS V8, możesz włączyć natywne wywołania za pomocą flagi --allow-natives-syntax, ujawnia to wiele przydatnych funkcji debugowania (pełna lista tutaj ), takich jak ta, której szukasz:% NeverOptimizeFunction () . Bez tej flagi wywołania te byłyby nielegalne, więc należy zachować ostrożność podczas wdrażania (lub użyć biblioteki v8-Natives ).

Aby włączyć tę funkcję, po prostu otwórz chrome za pomocą --js-flags = "- allow-natives-syntax" (używaj tego tylko do debugowania zaufanych stron internetowych, ponieważ może to dać niezaufanemu kodowi js dostęp do rzeczy, których tak naprawdę nie chcesz mieć dostęp do).

Paul1365972
źródło
Dziękuję Ci. Proszę przeczytać moje zaktualizowane pytanie. Wydaje się całkiem prawdopodobne, że masz tutaj rozwiązanie, ale potrzebuję więcej wyjaśnień, aby je zrealizować. Jeśli to zadziała, na pewno zasługujesz na nagrodę.
mathheadinclouds
tl; dr zamiast tego użyj --js-flags = "- allow-natives-syntax". Aby włączyć tę funkcję, V8 JS-Engine musi być uruchomiony z flagą --allow-natives-syntax, jednak nie można go uruchomić bezpośrednio, jest to zadanie chromes. Więc musisz powiedzieć chrome, żeby uruchomił silnik z flagą, jak to robisz? Przekaż wspomnianą flagę silnika przez --js-flags = <twoja flaga tutaj> do chrome.
Paul1365972,
nie. Próbowałem jeszcze raz, aby być po bezpiecznej stronie. Próbowałem zarówno --allow-natives-syntaxi --js-flags="--allow-natives-syntax"wielokrotnie jako „rzecz ja rodzaju po«chrom»w konsoli systemu operacyjnego”. Gdybym nie próbował tego wszystkiego sam, ja też pomyślałbym, że literówka jest najbardziej prawdopodobnym wyjaśnieniem. Zrobiłem kolejny zrzut ekranu. i.stack.imgur.com/7cpPP.png Zobacz literówkę? Proszę dać mi uczciwą odpowiedź: czy po prostu „przeczytałeś i zrozumiałeś artykuł” (żeby być jasnym, nic złego z tym, jeśli nie żądasz więcej), czy rzeczywiście próbowałeś tego wszystkiego na swoim komputerze? thx
mathheadinclouds
zgadnij: czy to możliwe, że nie uruchamiam pliku wykonywalnego chrome z tą opcją, ale kompiluję źródła chrome C ++ (lub cokolwiek innego) z tą opcją?
mathheadinclouds
1
To dziwne, właśnie go przetestowałem i działało dobrze, kompilacja nie była wymagana. Napiszę dokładnie to, co zrobiłem, aby nie było nieporozumień. 1. Zamknij całkowicie Chrome 2. Uruchom Chrome z konsoli za pomocą „C: / Program Files (x86) /Google/Chrome/Application/chrome.exe” --js-flags = "- allow-natives-syntax" 3. Otwórz konsola programisty i uruchom „% GetHeapUsage ()”, aby sprawdzić, czy wszystko działa
Paul1365972,
0

Naprawdę mam nadzieję, że to pytanie ma PRAWDZIWĄ odpowiedź. To, co następuje, nie jest prawdziwą odpowiedzią, jest prowizoryczne. Napisałem narzędzie pomocnicze, za pomocą którego możesz stworzyć głupi kod pomocniczy formularza if (false) { console.log(variables, from, closures); }(patrz zrzut ekranu w pytaniu) za pomocą analizy statycznej - wklejasz swój kod, tworzona jest głupia instrukcja, możesz ją skopiować, a następnie nie potrzebujesz wpisać to. Nie wiem, czy to bardzo pomaga, ponieważ całe to kopiowanie i wklejanie również wymaga czasu, ale to właśnie dostałem.

zrzut ekranu

skrzypce

mathheadinclouds
źródło