नए टूल की मदद से WebAssembly को डीबग करना

Ingvar Stepanyan
Ingvar Stepanyan

अब तक सड़क

एक साल पहले, Chrome ने शुरुआती सहायता का एलान किया था Chrome DevTools में नेटिव WebAssembly डीबगिंग के लिए.

हमने बुनियादी चरणों की सहायता के बारे में बताया. साथ ही, आने वाले समय में सोर्स मैप के बजाय DWARF की जानकारी का इस्तेमाल करने के अवसरों के बारे में भी बताया:

  • वैरिएबल के नामों को हल करना
  • प्रिटी-प्रिंट के टाइप
  • सोर्स भाषाओं में एक्सप्रेशन का आकलन करना
  • …और ऐसी ही कई अन्य सुविधाएं!

आज, हमें यह बताते हुए खुशी हो रही है कि हमने जो सुविधाएं देने का वादा किया था वे अब उपलब्ध हैं. साथ ही, हम Emscripten और Chrome DevTools की टीमों की इस साल की उपलब्धियों के बारे में भी बताना चाहते हैं. खास तौर पर, C और C++ ऐप्लिकेशन के लिए की गई उपलब्धियों के बारे में.

शुरू करने से पहले, कृपया ध्यान रखें कि यह अब भी बीटा वर्शन है है, तो आपको सभी टूल के सबसे नए वर्शन का इस्तेमाल करना होगा पर रिपोर्ट करें और अगर आपको कोई समस्या आती है, तो कृपया उसकी शिकायत करें https://issues.chromium.org/issues/new?noWizard=true&template=0&component=1456350.

आइए, पिछले लेख में दिए गए C के उसी आसान उदाहरण से शुरू करते हैं:

#include <stdlib.h>

void assert_less(int x, int y) {
  if (x >= y) {
    abort();
  }
}

int main() {
  assert_less(10, 20);
  assert_less(30, 20);
}

इसे कंपाइल करने के लिए, हम सबसे नए एंस्क्रिप्टन का इस्तेमाल करते हैं और डीबग को शामिल करने के लिए, मूल पोस्ट की तरह ही एक -g फ़्लैग पास करें जानकारी:

emcc -g temp.c -o temp.html

अब जनरेट किए गए पेज को localhost एचटीटीपी सर्वर से दिखाया जा सकता है. उदाहरण के लिए, serve की मदद से. साथ ही, इसे Chrome Canary के नए वर्शन में खोला जा सकता है.

इस बार, हमें एक हेल्पर एक्सटेंशन की भी ज़रूरत होगी, जो Chrome DevTools के साथ इंटिग्रेट हो. साथ ही, WebAssembly फ़ाइल में एन्कोड की गई, डीबग करने से जुड़ी सारी जानकारी को समझने में मदद करता हो. कृपया इस पर जाकर इसे इंस्टॉल करें लिंक: goo.gle/wasm-debugging-extension

DevTools में WebAssembly डीबग करने की सुविधा को भी चालू करना होगा एक्सपेरिमेंट. Chrome DevTools खोलें और गियर () आइकॉन पर क्लिक करें DevTools पैनल के सबसे ऊपर दाएं कोने में, एक्सपेरिमेंट पैनल पर जाएं और WebAssembly डीबगिंग: DWARF सहायता चालू करें पर सही का निशान लगाएं.

DevTools की सेटिंग का एक्सपेरिमेंट पैनल

सेटिंग बंद करने पर, DevTools खुद को फिर से लोड करने का सुझाव देगा सेटिंग लागू करनी है, तो बस इतना ही करें. एक बार के लिए बस इतना ही सेटअप.

अब हम सोर्स पैनल पर वापस जा सकते हैं और अपवाद मिलने पर रोकें (⏸ आइकॉन) को चालू कर सकते हैं. इसके बाद, पकड़े गए अपवादों पर रोकें को चुनें और पेज को फिर से लोड करें. आपको DevTools को किसी अपवाद पर रोका हुआ दिखेगा:

सोर्स पैनल का स्क्रीनशॉट, जिसमें &#39;मिलने वाले अपवादों पर रोकें&#39; को चालू करने का तरीका बताया गया है

डिफ़ॉल्ट रूप से, यह Emscripten से जनरेट किए गए ग्लू कोड पर रुक जाता है. हालांकि, दाईं ओर आपको कॉल स्टैक व्यू दिख सकता है, जो गड़बड़ी के स्टैकट्रैस को दिखाता है. साथ ही, abort को कॉल करने वाली ओरिजनल C लाइन पर नेविगेट किया जा सकता है:

DevTools, `assert_less` फ़ंक्शन में रोका गया और स्कोप व्यू में `x` और `y` की वैल्यू दिखा रहा है

अब, स्कोप व्यू में जाकर, C/C++ कोड में वैरिएबल के ओरिजनल नाम और वैल्यू देखी जा सकती हैं. साथ ही, अब आपको यह पता लगाने की ज़रूरत नहीं है कि $localN जैसे गलत नामों का क्या मतलब है और वे आपके लिखे गए सोर्स कोड से कैसे जुड़े हैं.

यह न सिर्फ़ पूर्णांकों जैसे शुरुआती वैल्यू पर लागू होता है, बल्कि कंपाउंड पर भी लागू होता है संरचना, क्लास, अरे वगैरह जैसे टाइप भी!

रिच टाइप के लिए सहायता

आइए, अब इन्हें दिखाने के लिए ज़्यादा मुश्किल उदाहरण पर नज़र डालें. इस बार, हम C++ के इस कोड की मदद से मंडेलब्रॉट फ़्रैक्टल बनाएंगे:

#include <SDL2/SDL.h>
#include <complex>

int main() {
  // Init SDL.
  int width = 600, height = 600;
  SDL_Init(SDL_INIT_VIDEO);
  SDL_Window* window;
  SDL_Renderer* renderer;
  SDL_CreateWindowAndRenderer(width, height, SDL_WINDOW_OPENGL, &window,
                              &renderer);

  // Generate a palette with random colors.
  enum { MAX_ITER_COUNT = 256 };
  SDL_Color palette[MAX_ITER_COUNT];
  srand(time(0));
  for (int i = 0; i < MAX_ITER_COUNT; ++i) {
    palette[i] = {
        .r = (uint8_t)rand(),
        .g = (uint8_t)rand(),
        .b = (uint8_t)rand(),
        .a = 255,
    };
  }

  // Calculate and draw the Mandelbrot set.
  std::complex<double> center(0.5, 0.5);
  double scale = 4.0;
  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      std::complex<double> point((double)x / width, (double)y / height);
      std::complex<double> c = (point - center) * scale;
      std::complex<double> z(0, 0);
      int i = 0;
      for (; i < MAX_ITER_COUNT - 1; i++) {
        z = z * z + c;
        if (abs(z) > 2.0)
          break;
      }
      SDL_Color color = palette[i];
      SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
      SDL_RenderDrawPoint(renderer, x, y);
    }
  }

  // Render everything we've drawn to the canvas.
  SDL_RenderPresent(renderer);

  // SDL_Quit();
}

आप देख सकते हैं कि यह ऐप्लिकेशन अब भी काफ़ी छोटा है-यह एकल फ़ाइल में 50 पंक्तियों का कोड है-लेकिन इस बार मैं कुछ बाहरी एपीआई, जैसे कि SDL लाइब्रेरी और साथ ही, कॉम्प्लेक्स नंबर C++ स्टैंडर्ड लाइब्रेरी.

मैं इसे ऊपर बताए गए उसी -g फ़्लैग के साथ कंपाइल कर रहा/रही हूं और मैं Emscripten से SDL2 उपलब्ध कराने के लिए भी कहूँगी और आर्बिट्ररी साइज़ की मेमोरी की अनुमति दें:

emcc -g mandelbrot.cc -o mandelbrot.html \
     -s USE_SDL=2 \
     -s ALLOW_MEMORY_GROWTH=1

ब्राउज़र में जनरेट किए गए पेज पर जाने पर, मुझे कुछ रंगों के साथ खूबसूरत फ़्रैक्टल आकार दिखता है:

डेमो पेज

DevTools खोलने पर, मुझे फिर से ओरिजनल C++ फ़ाइल दिख रही है. हालांकि, इस बार कोड में कोई गड़बड़ी नहीं है (वाह!), इसलिए अपने कोड की शुरुआत में कुछ ब्रेकपॉइंट सेट करें.

जब हम पेज को फिर से लोड करते हैं, तो डीबगर हमारी C++ सोर्स:

DevTools, `SDL_Init` कॉल पर रुका

हमें दाईं ओर अपने सभी वैरिएबल पहले से दिख रहे हैं. हालांकि, फ़िलहाल सिर्फ़ width और height को शुरू किया गया है. इसलिए, जांचने के लिए ज़्यादा कुछ नहीं है.

आइए, अपने मुख्य मेंडलब्रॉट लूप में एक और ब्रेकपॉइंट सेट करें और फिर से शुरू करें करने के लिए एक्ज़ीक्यूशन का इस्तेमाल करता है.

DevTools को नेस्ट किए गए लूप में रोका गया है

इस समय, हमारे palette में कुछ रंग भरे गए हैं. साथ ही, हम ऐरे और अलग-अलग SDL_Color स्ट्रक्चर, दोनों को बड़ा कर सकते हैं. साथ ही, उनके कॉम्पोनेंट की जांच करके यह पुष्टि कर सकते हैं कि सब कुछ ठीक है या नहीं. उदाहरण के लिए, "अल्फा" चैनल हमेशा पूरी ओपैसिटी पर सेट है. इसी तरह, हम अपने विश्लेषण के मकसद से, center वैरिएबल में सेव किए गए कॉम्प्लेक्स नंबर के काल्पनिक हिस्से.

अगर आपको किसी ऐसी प्रॉपर्टी को ऐक्सेस करना है जो स्कोप व्यू से ऐक्सेस करना मुश्किल है, तो कंसोल के आकलन का इस्तेमाल किया जा सकता है! हालांकि, ध्यान दें कि फ़िलहाल C++ के ज़्यादा जटिल एक्सप्रेशन काम नहीं करते.

`palette[10].r` का नतीजा दिखाने वाला कंसोल पैनल

कुछ बार फिर से एक्ज़ीक्यूशन करते हैं और देख सकते हैं कि अंदरूनी x कैसा है दायरा व्यू में दोबारा देखकर, वैरिएबल के नाम को वॉच लिस्ट में जोड़ सकता है, कंसोल में इसका आकलन कर सकता है या सोर्स कोड में वैरिएबल पर कर्सर घुमाना:

सोर्स में वैरिएबल `x` पर टूलटिप की वैल्यू `3` दिख रही है

यहां से, हम C++ स्टेटमेंट में स्टैप-इन या स्टैप-ओवर कर सकते हैं. साथ ही, यह भी देख सकते हैं कि अन्य वैरिएबल कैसे बदल रहे हैं:

`रंग`, `पॉइंट`, और अन्य वैरिएबल की वैल्यू दिखाने वाले टूलटिप और स्कोप व्यू

ठीक है, डीबग करने की जानकारी उपलब्ध होने पर यह तरीका बहुत अच्छा काम करता है. हालांकि, अगर हमें ऐसे कोड को डीबग करना हो जिसे डीबग करने के विकल्पों के साथ नहीं बनाया गया है, तो क्या होगा?

रॉ WebAssembly डीबगिंग

उदाहरण के लिए, हमने Emscripten से कहा है कि वह हमें पहले से बनी SDL लाइब्रेरी उपलब्ध कराए. हम खुद सोर्स से इसे कंपाइल नहीं करना चाहते. इसलिए, कम से कम फ़िलहाल, डीबगर के पास इससे जुड़े सोर्स ढूंढने का कोई तरीका नहीं है. SDL_RenderDrawColor में जाने के लिए, फिर से शुरू करें:

`mandelbrot.vasm` को अलग करने वाला व्यू दिखाने वाला DevTools

हम रॉ WebAssembly डीबग करने के अनुभव पर वापस आ गए हैं.

अब, यह थोड़ा डरावना लग रहा है और यह कुछ ऐसा नहीं है जिसे ज़्यादातर वेब डेवलपरों को कभी-कभी समस्याओं का सामना करना पड़ता है, लेकिन कभी-कभी डीबग करने की जानकारी के बिना बनाई गई लाइब्रेरी-चाहें, क्योंकि यह तीसरे पक्ष की लाइब्रेरी जिन पर आपका कोई कंट्रोल नहीं है या हमें ऐसी गड़बड़ियों का सामना करना पड़ता है जो सिर्फ़ प्रोडक्शन के दौरान होती हैं.

ऐसे मामलों में आपकी मदद करने के लिए, हमने डीबग करने का अनुभव भी.

सबसे पहले, अगर आपने पहले कभी रॉ WebAssembly डीबगिंग का इस्तेमाल किया था, तो ध्यान दें कि पूरा असेंबली अब एक ही फ़ाइल-नहीं में दिखता है यह अनुमान लगाने में ज़्यादा मदद मिलेगी कि सोर्स एंट्री wasm-53834e3e/ wasm-53834e3e-7 किस फ़ंक्शन से जुड़ा हो सकता है.

नया नाम जनरेट करने की स्कीम

हमने डिसएसेम्बली व्यू में भी नामों को बेहतर बनाया है. पहले आपको सिर्फ़ संख्या वाले इंडेक्स दिखते थे या फ़ंक्शन के मामले में, कोई नाम नहीं दिखता था.

अब हम अलग करने वाले दूसरे टूल की तरह ही नाम जनरेट कर रहे हैं. WebAssembly के नाम वाले सेक्शन से मिले संकेतों का इस्तेमाल करके, पाथ इंपोर्ट/एक्सपोर्ट करना और आखिर में, अगर बाकी सब कुछ फ़ेल हो जाता है, तो $func123 जैसे आइटम के टाइप और इंडेक्स के हिसाब से तय किया जाता है. ऊपर दिए गए स्क्रीनशॉट में देखा जा सकता है कि इससे स्टैक ट्रेस और डिसअसेम्बली को थोड़ा और आसानी से पढ़ा जा सकता है.

जब टाइप की जानकारी उपलब्ध नहीं होती है, तो प्राइमिटिव के अलावा किसी भी वैल्यू की जांच करना मुश्किल हो सकता है. उदाहरण के लिए, पॉइंटर सामान्य पूर्णांक के तौर पर दिखेंगे. साथ ही, यह पता नहीं चलेगा कि मेमोरी में उनके पीछे क्या स्टोर किया गया है.

मेमोरी की जांच

पहले, अलग-अलग बाइट देखने के लिए, सिर्फ़ WebAssembly मेमोरी ऑब्जेक्ट को बड़ा किया जा सकता था. यह ऑब्जेक्ट, स्कोप व्यू में env.memory से दिखाया जाता है. यह कुछ साधारण स्थितियों में काम करता था, लेकिन ऐसा नहीं था खास तौर पर, इसे बड़ा करने के लिए सुविधाजनक है. साथ ही, इसे दोबारा समझने की सुविधा नहीं है बाइट वैल्यू के अलावा अन्य फ़ॉर्मैट में. हमने आपकी मदद के लिए एक नई सुविधा जोड़ी है इसके साथ ही: एक लीनियर मेमोरी इंस्पेक्टर भी.

env.memory पर राइट क्लिक करने पर, आपको मेमोरी की जांच करें नाम का एक नया विकल्प दिखेगा:

स्कोप पैनल में, `env.memory` पर मौजूद संदर्भ मेन्यू, जिसमें &#39;मेमोरी की जांच करें&#39; आइटम दिख रहा है

क्लिक करने के बाद, आपको एक मेमोरी इंस्पेक्टर दिखेगा. इसमें, हेक्साडेसिमल और ASCII व्यू में WebAssembly मेमोरी की जांच की जा सकती है. साथ ही, खास पतों पर नेविगेट किया जा सकता है और डेटा को अलग-अलग फ़ॉर्मैट में देखा जा सकता है:

DevTools में मेमोरी इंस्पेक्टर पैनल में मेमोरी के हेक्स और ASCII व्यू दिखाए गए हैं

बेहतर स्थितियां और सावधानियां

WebAssembly कोड की प्रोफ़ाइलिंग करना

DevTools खोलने पर, WebAssembly कोड "टीयर" दिखता है से लेकर डीबग करने की सुविधा चालू करने के लिए ऑप्टिमाइज़ नहीं किया गया वर्शन. यह वर्शन काफ़ी धीमा है. इसका मतलब है कि DevTools खुले होने पर, console.time, performance.now, और कोड की स्पीड को मेज़र करने के अन्य तरीकों पर भरोसा नहीं किया जा सकता. ऐसा इसलिए, क्योंकि आपको जो संख्याएं मिलेंगी वे असल परफ़ॉर्मेंस को बिलकुल नहीं दिखाएंगी.

इसके बजाय, आपको DevTools परफ़ॉर्मेंस पैनल का इस्तेमाल करना चाहिए जो कोड को पूरी स्पीड से चलाएगा और आपको अलग-अलग फ़ंक्शन में लगने वाले समय का ब्यौरा:

Wasm के अलग-अलग फ़ंक्शन दिखा रहा प्रोफ़ाइलिंग पैनल

इसके अलावा, आपके पास DevTools बंद करके अपने ऐप्लिकेशन को चलाने का विकल्प है. साथ ही, कंसोल की जांच करने के बाद उन्हें खोलें.

हम आने वाले समय में, प्रोफ़ाइल बनाने की सुविधा को बेहतर बनाएंगे. हालांकि, फ़िलहाल इस बात का ध्यान रखें. अगर आपको WebAssembly के बारे में ज़्यादा जानना है टियर करने के लिए अलग-अलग टियर के लिए, WebAssembly कंपाइलेशन पाइपलाइन पर हमारे दस्तावेज़ देखें.

अलग-अलग मशीनों पर बनाना और डीबग करना (इसमें Docker / होस्ट शामिल है)

Docker, वर्चुअल मशीन या रिमोट बिल्ड सर्वर पर बिल्ड करते समय, आपको ऐसी स्थितियों का सामना करना पड़ सकता है जहां बिल्ड के दौरान इस्तेमाल की गई सोर्स फ़ाइलों के पाथ, आपके फ़ाइल सिस्टम के उन पाथ से मेल नहीं खाते जहां Chrome DevTools चल रहे हैं. इस स्थिति में, फ़ाइलें सोर्स पैनल, लेकिन लोड नहीं हो सका.

इस समस्या को ठीक करने के लिए, हमने इसमें पाथ मैपिंग फ़ंक्शन लागू किया है C/C++ एक्सटेंशन विकल्प चुनें. इसका इस्तेमाल करके, आर्बिट्रेरी पाथ को फिर से मैप किया जा सकता है और इससे DevTools को सोर्स ढूंढने में मदद मिलेगी.

उदाहरण के लिए, अगर आपकी होस्ट मशीन पर प्रोजेक्ट किसी पाथ के अंदर है C:\src\my_project, लेकिन इसे Docker कंटेनर के अंदर बनाया गया, जहां वह पाथ /mnt/c/src/my_project के रूप में दिखाया गया था, तो आप दोबारा मैप कर सकते हैं उन पाथ को प्रीफ़िक्स के तौर पर बताकर, डीबग करने के दौरान इसे फिर से डीबग करता है:

C/C++ डीबग करने के एक्सटेंशन के विकल्पों वाला पेज

पहला मेल खाने वाला प्रीफ़िक्स "wins". अगर आपको C++ के अन्य डीबगर के बारे में पता है, तो यह विकल्प GDB में set substitute-path कमांड या LLDB में target.source-map सेटिंग जैसा ही है.

ऑप्टिमाइज़ किए गए बिल्ड को डीबग करना

किसी भी दूसरी भाषा की तरह, डीबग करने की सुविधा सबसे अच्छी तरह से तब काम करती है, जब ऑप्टिमाइज़ेशन बंद किया गया. ऑप्टिमाइज़ेशन की मदद से, फ़ंक्शन को इनलाइन करके दूसरे फ़ंक्शन में डाला जा सकता है और फिर से क्रम में लगाया जा सकता है या कोड के कुछ हिस्सों को हटा सकता हूं-और इन सभी में डीबगर को भ्रम में डालने की संभावना है और इस कारण आपको एक उपयोगकर्ता के रूप में भी सूचित किया जा सकता है.

अगर आपको डीबग करने का सीमित अनुभव नहीं है और फिर भी आपको किसी ऑप्टिमाइज़ किए गए बिल्ड को डीबग करने, तो ज़्यादातर ऑप्टिमाइज़ेशन इस तरह से काम करेंगे फ़ंक्शन इनलाइनिंग को छोड़कर. हमारी कोशिश है कि बाकी जगहों पर भी हम आने वाले समय में समस्याएं आ सकती हैं, लेकिन अभी के लिए, कृपया -fno-inline का इस्तेमाल करके इसे किसी भी -O लेवल के ऑप्टिमाइज़ेशन के साथ कंपाइल करते समय बंद करें, उदाहरण के लिए:

emcc -g temp.c -o temp.html \
     -O3 -fno-inline

डीबग की जानकारी को अलग करना

डीबग करने की जानकारी में आपके कोड के बारे में काफ़ी जानकारी होती है टाइप, वैरिएबल, फ़ंक्शन, स्कोप, और जगहों की जानकारी-जो भी हो सकती है डीबगर के लिए उपयोगी होगी. इस वजह से, यह अक्सर कोड से बड़ा हो सकता है.

WebAssembly मॉड्यूल के लोड और कंपाइलेशन की रफ़्तार के लिए, आपको को इस डीबग जानकारी को एक अलग WebAssembly में बांटना फ़ाइल से लिए जाते हैं. Emscripten में ऐसा करने के लिए, मनचाहे फ़ाइल नाम के साथ -gseparate-dwarf=… फ़्लैग पास करें:

emcc -g temp.c -o temp.html \
     -gseparate-dwarf=temp.debug.wasm

इस स्थिति में, मुख्य ऐप्लिकेशन में सिर्फ़ फ़ाइल नाम सेव होगा temp.debug.wasm शामिल है और हेल्पर एक्सटेंशन DevTools खोलने पर इसे लोड करें.

ऊपर बताए गए ऑप्टिमाइज़ेशन के साथ इस सुविधा का इस्तेमाल, अपने ऐप्लिकेशन के ऑप्टिमाइज़ किए गए प्रोडक्शन बिल्ड को शिप करने के लिए भी किया जा सकता है. इसके बाद, स्थानीय साइड फ़ाइल की मदद से उन्हें डीबग किया जा सकता है. इस मामले में, हमें एक्सटेंशन को साइड फ़ाइल ढूंढने में मदद करने के लिए, सेव किए गए यूआरएल को बदलना होगा. उदाहरण के लिए:

emcc -g temp.c -o temp.html \
     -O3 -fno-inline \
     -gseparate-dwarf=temp.debug.wasm \
     -s SEPARATE_DWARF_URL=file://[local path to temp.debug.wasm]

जारी रखना है...

वाह, इसमें कई नई सुविधाएं थीं!

इन सभी नए इंटिग्रेशन के साथ, Chrome DevTools एक बेहतर विकल्प बन गया है. यह एक दमदार डीबगर है, जो सिर्फ़ JavaScript के लिए ही नहीं, बल्कि C और C++ ऐप्लिकेशन के लिए भी इस्तेमाल किया जा सकता है. कई अलग-अलग सुविधाओं के साथ तैयार किए गए, ऐप्लिकेशन इस्तेमाल करना अब पहले से ज़्यादा आसान हो गया है और उन्हें शेयर किए गए, क्रॉस-प्लैटफ़ॉर्म वेब पर लाया जा सकता है.

हालांकि, हमारा सफ़र अभी खत्म नहीं हुआ है. कुछ चीज़ों के बारे में हम जानेंगे मैं यहां से इस पर काम कर रहा हूं:

  • डीबग करने की प्रोसेस में, अनचाहे किनारों को हटाना.
  • कस्टम टाइप फ़ॉर्मैटर के लिए सहायता जोड़ी गई है.
  • WebAssembly ऐप्लिकेशन के लिए, प्रोफ़ाइल बनाने की सुविधा को बेहतर बनाने पर काम किया जा रहा है.
  • कोड कवरेज के लिए सहायता जोड़ी गई है, ताकि इस्तेमाल न किए गए कोड को आसानी से ढूंढा जा सके.
  • कंसोल के आकलन में एक्सप्रेशन के लिए सहायता को बेहतर बनाना.
  • अन्य भाषाओं के लिए भी यह सुविधा जोड़ी जा रही है.
  • …और ऐसे ही अन्य ट्रेंड!

इस बीच, अपने कोड पर मौजूदा बीटा वर्शन आज़माकर, हमें मदद करें. साथ ही, अगर आपको कोई समस्या मिलती है, तो https://issues.chromium.org/issues/new?noWizard=true&template=0&component=1456350 पर जाकर हमें इसकी शिकायत करें.

झलक वाले चैनल डाउनलोड करना

Chrome कैनरी, डेवलपर या बीटा वर्शन को अपने डिफ़ॉल्ट डेवलपमेंट ब्राउज़र के तौर पर इस्तेमाल करें. झलक दिखाने वाले इन चैनलों की मदद से, DevTools की नई सुविधाओं को ऐक्सेस किया जा सकता है और वेब प्लैटफ़ॉर्म के बेहतरीन एपीआई की जांच की जा सकती है. साथ ही, उपयोगकर्ताओं से पहले ही अपनी साइट की समस्याओं का पता लगाया जा सकता है!

Chrome DevTools की टीम से संपर्क करना

पोस्ट में बताई गई नई सुविधाओं और बदलावों या DevTools से जुड़ी किसी भी चीज़ के बारे में चर्चा करने के लिए, नीचे दिए गए विकल्पों का इस्तेमाल करें.