chrome-devtools-frontend 1.0.975699 → 1.0.976703

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/AUTHORS +1 -0
  2. package/config/gni/devtools_grd_files.gni +8 -0
  3. package/config/gni/devtools_image_files.gni +2 -0
  4. package/front_end/Images/src/minus_icon.svg +3 -0
  5. package/front_end/Images/src/plus_icon.svg +3 -0
  6. package/front_end/core/host/UserMetrics.ts +23 -23
  7. package/front_end/core/i18n/locales/en-US.json +6 -0
  8. package/front_end/core/i18n/locales/en-XL.json +6 -0
  9. package/front_end/core/sdk/CSSContainerQuery.ts +1 -1
  10. package/front_end/core/sdk/CSSModel.ts +13 -9
  11. package/front_end/generated/InspectorBackendCommands.js +7 -6
  12. package/front_end/generated/protocol.ts +11 -9
  13. package/front_end/models/issues_manager/Issue.ts +1 -1
  14. package/front_end/models/issues_manager/IssuesManager.ts +3 -9
  15. package/front_end/models/issues_manager/SameSiteCookieIssue.ts +74 -78
  16. package/front_end/models/issues_manager/issues_manager.ts +2 -2
  17. package/front_end/models/persistence/NetworkPersistenceManager.ts +1 -1
  18. package/front_end/panels/elements/ClassesPaneWidget.ts +1 -1
  19. package/front_end/panels/elements/ComputedStyleModel.ts +1 -1
  20. package/front_end/panels/elements/ElementsTreeElement.ts +1 -1
  21. package/front_end/panels/elements/LayersWidget.ts +4 -3
  22. package/front_end/panels/elements/MetricsSidebarPane.ts +2 -2
  23. package/front_end/panels/elements/PlatformFontsWidget.ts +1 -1
  24. package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
  25. package/front_end/panels/elements/StylesSidebarPane.ts +10 -8
  26. package/front_end/panels/emulation/MediaQueryInspector.ts +1 -1
  27. package/front_end/panels/issues/IssueView.ts +1 -1
  28. package/front_end/panels/issues/IssuesPane.ts +1 -1
  29. package/front_end/panels/network/NetworkLogView.ts +1 -1
  30. package/front_end/panels/settings/components/SyncSection.ts +5 -17
  31. package/front_end/panels/sources/CSSPlugin.ts +77 -22
  32. package/front_end/panels/sources/SourcesView.ts +23 -10
  33. package/front_end/panels/sources/components/HeadersView.css +32 -0
  34. package/front_end/panels/sources/components/HeadersView.ts +89 -0
  35. package/front_end/panels/sources/components/components.ts +9 -0
  36. package/front_end/ui/components/chrome_link/ChromeLink.ts +62 -0
  37. package/front_end/ui/components/chrome_link/chromeLink.css +12 -0
  38. package/front_end/ui/components/chrome_link/chrome_link.ts +9 -0
  39. package/package.json +1 -1
@@ -4,13 +4,17 @@
4
4
 
5
5
  import * as Common from '../../core/common/common.js';
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
+ import * as Platform from '../../core/platform/platform.js';
7
8
  import * as SDK from '../../core/sdk/sdk.js';
9
+ import type * as Protocol from '../../generated/protocol.js';
8
10
  import type * as Workspace from '../../models/workspace/workspace.js';
9
11
  import * as ColorPicker from '../../ui/legacy/components/color_picker/color_picker.js';
10
12
  import * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';
11
13
  import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
14
+ import type * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
12
15
  import * as UI from '../../ui/legacy/legacy.js';
13
16
 
17
+ import {assertNotNullOrUndefined} from '../../core/platform/platform.js';
14
18
  import {Plugin} from './Plugin.js';
15
19
 
16
20
  // Plugin to add CSS completion, shortcuts, and color/curve swatches
@@ -29,17 +33,6 @@ const UIStrings = {
29
33
  const str_ = i18n.i18n.registerUIStrings('panels/sources/CSSPlugin.ts', UIStrings);
30
34
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
31
35
 
32
- export function completion(): CodeMirror.Extension {
33
- const {cssCompletionSource} = CodeMirror.css;
34
- return CodeMirror.autocompletion({
35
- override:
36
- [async(cx: CodeMirror.CompletionContext):
37
- Promise<CodeMirror.CompletionResult|null> => {
38
- return (await specificCssCompletion(cx)) || cssCompletionSource(cx);
39
- }],
40
- });
41
- }
42
-
43
36
  const dontCompleteIn = new Set(['ColorLiteral', 'NumberLiteral', 'StringLiteral', 'Comment', 'Important']);
44
37
 
45
38
  function findPropertyAt(node: CodeMirror.SyntaxNode, pos: number): CodeMirror.SyntaxNode|null {
@@ -57,18 +50,43 @@ function findPropertyAt(node: CodeMirror.SyntaxNode, pos: number): CodeMirror.Sy
57
50
  return null;
58
51
  }
59
52
 
60
- function specificCssCompletion(cx: CodeMirror.CompletionContext): CodeMirror.CompletionResult|null {
53
+ function getCurrentStyleSheet(
54
+ url: Platform.DevToolsPath.UrlString, cssModel: SDK.CSSModel.CSSModel): Protocol.CSS.StyleSheetId {
55
+ const currentStyleSheet = cssModel.getStyleSheetIdsForURL(url);
56
+ if (currentStyleSheet.length === 0) {
57
+ Platform.DCHECK(() => currentStyleSheet.length !== 0, 'Can\'t find style sheet ID for current URL');
58
+ }
59
+
60
+ return currentStyleSheet[0];
61
+ }
62
+
63
+ async function specificCssCompletion(
64
+ cx: CodeMirror.CompletionContext, uiSourceCode: Workspace.UISourceCode.UISourceCode,
65
+ cssModel: SDK.CSSModel.CSSModel|undefined): Promise<CodeMirror.CompletionResult|null> {
61
66
  const node = CodeMirror.syntaxTree(cx.state).resolveInner(cx.pos, -1);
67
+ if (node.name === 'ClassName') {
68
+ // Should never happen, but let's code defensively here
69
+ assertNotNullOrUndefined(cssModel);
70
+
71
+ const currentStyleSheet = getCurrentStyleSheet(uiSourceCode.url(), cssModel);
72
+ const existingClassNames = await cssModel.getClassNames(currentStyleSheet);
73
+
74
+ return {
75
+ from: node.from,
76
+ options: existingClassNames.map(value => ({type: 'constant', label: value})),
77
+ };
78
+ }
62
79
  const property = findPropertyAt(node, cx.pos);
63
- if (!property) {
64
- return null;
80
+ if (property) {
81
+ const propertyValues =
82
+ SDK.CSSMetadata.cssMetadata().getPropertyValues(cx.state.sliceDoc(property.from, property.to));
83
+ return {
84
+ from: node.name === 'ValueName' ? node.from : cx.pos,
85
+ options: propertyValues.map(value => ({type: 'constant', label: value})),
86
+ span: /^[\w\P{ASCII}\-]+$/u,
87
+ };
65
88
  }
66
- const propertyValues = SDK.CSSMetadata.cssMetadata().getPropertyValues(cx.state.sliceDoc(property.from, property.to));
67
- return {
68
- from: node.name === 'ValueName' ? node.from : cx.pos,
69
- options: propertyValues.map(value => ({type: 'constant', label: value})),
70
- span: /^[\w\P{ASCII}\-]+$/u,
71
- };
89
+ return null;
72
90
  }
73
91
 
74
92
  function findColorsAndCurves(
@@ -380,12 +398,49 @@ export function cssBindings(): CodeMirror.Extension {
380
398
  });
381
399
  }
382
400
 
383
- export class CSSPlugin extends Plugin {
401
+ export class CSSPlugin extends Plugin implements SDK.TargetManager.SDKModelObserver<SDK.CSSModel.CSSModel> {
402
+ #cssModel?: SDK.CSSModel.CSSModel;
403
+
404
+ constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode, _transformer?: SourceFrame.SourceFrame.Transformer) {
405
+ super(uiSourceCode, _transformer);
406
+ SDK.TargetManager.TargetManager.instance().observeModels(SDK.CSSModel.CSSModel, this);
407
+ }
408
+
384
409
  static accepts(uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean {
385
410
  return uiSourceCode.contentType().isStyleSheet();
386
411
  }
387
412
 
413
+ modelAdded(cssModel: SDK.CSSModel.CSSModel): void {
414
+ if (this.#cssModel) {
415
+ return;
416
+ }
417
+ this.#cssModel = cssModel;
418
+ }
419
+ modelRemoved(cssModel: SDK.CSSModel.CSSModel): void {
420
+ if (this.#cssModel === cssModel) {
421
+ this.#cssModel = undefined;
422
+ }
423
+ }
424
+
388
425
  editorExtension(): CodeMirror.Extension {
389
- return [cssBindings(), completion(), cssSwatches()];
426
+ return [cssBindings(), this.#cssCompletion(), cssSwatches()];
427
+ }
428
+
429
+ #cssCompletion(): CodeMirror.Extension {
430
+ const {cssCompletionSource} = CodeMirror.css;
431
+
432
+ // CodeMirror binds the function below to the state object.
433
+ // Therefore, we can't access `this` and retrieve the following properties.
434
+ // Instead, retrieve them up front to bind them to the correct closure.
435
+ const uiSourceCode = this.uiSourceCode;
436
+ const cssModel = this.#cssModel;
437
+
438
+ return CodeMirror.autocompletion({
439
+ override:
440
+ [async(cx: CodeMirror.CompletionContext):
441
+ Promise<CodeMirror.CompletionResult|null> => {
442
+ return (await specificCssCompletion(cx, uiSourceCode, cssModel)) || cssCompletionSource(cx);
443
+ }],
444
+ });
390
445
  }
391
446
  }
@@ -12,6 +12,7 @@ import * as QuickOpen from '../../ui/legacy/components/quick_open/quick_open.js'
12
12
  import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
13
13
  import * as UI from '../../ui/legacy/legacy.js';
14
14
 
15
+ import * as Components from './components/components.js';
15
16
  import {EditingLocationHistoryManager} from './EditingLocationHistoryManager.js';
16
17
  import sourcesViewStyles from './sourcesView.css.js';
17
18
 
@@ -377,6 +378,10 @@ export class SourcesView extends Common.ObjectWrapper.eventMixin<EventTypes, typ
377
378
  sourceView = new SourceFrame.ImageView.ImageView(uiSourceCode.mimeType(), uiSourceCode);
378
379
  } else if (contentType === Common.ResourceType.resourceTypes.Font) {
379
380
  sourceView = new SourceFrame.FontView.FontView(uiSourceCode.mimeType(), uiSourceCode);
381
+ } else if (
382
+ uiSourceCode.name() === HEADER_OVERRIDES_FILENAME &&
383
+ Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.HEADER_OVERRIDES)) {
384
+ sourceView = new Components.HeadersView.HeadersView(uiSourceCode);
380
385
  } else {
381
386
  sourceFrame = new UISourceCodeFrame(uiSourceCode);
382
387
  }
@@ -399,10 +404,18 @@ export class SourcesView extends Common.ObjectWrapper.eventMixin<EventTypes, typ
399
404
  if (widget instanceof SourceFrame.FontView.FontView) {
400
405
  return SourceViewType.FontView;
401
406
  }
407
+ if (widget instanceof Components.HeadersView.HeadersView) {
408
+ return SourceViewType.HeadersView;
409
+ }
402
410
  return SourceViewType.SourceView;
403
411
  }
404
412
 
405
- #sourceViewTypeForContentType(contentType: Common.ResourceType.ResourceType): SourceViewType {
413
+ #sourceViewTypeForUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode): SourceViewType {
414
+ if (uiSourceCode.name() === HEADER_OVERRIDES_FILENAME &&
415
+ Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.HEADER_OVERRIDES)) {
416
+ return SourceViewType.HeadersView;
417
+ }
418
+ const contentType = uiSourceCode.contentType();
406
419
  switch (contentType) {
407
420
  case Common.ResourceType.resourceTypes.Image:
408
421
  return SourceViewType.ImageView;
@@ -417,8 +430,7 @@ export class SourcesView extends Common.ObjectWrapper.eventMixin<EventTypes, typ
417
430
  const uiSourceCode = event.data;
418
431
  const widget = this.sourceViewByUISourceCode.get(uiSourceCode);
419
432
  if (widget) {
420
- const contentType = uiSourceCode.contentType();
421
- if (this.#sourceViewTypeForWidget(widget) !== this.#sourceViewTypeForContentType(contentType)) {
433
+ if (this.#sourceViewTypeForWidget(widget) !== this.#sourceViewTypeForUISourceCode(uiSourceCode)) {
422
434
  // Remove the exisiting editor tab and create a new one of the correct type.
423
435
  this.removeUISourceCodes([uiSourceCode]);
424
436
  this.showSourceLocation(uiSourceCode);
@@ -602,20 +614,18 @@ export class SourcesView extends Common.ObjectWrapper.eventMixin<EventTypes, typ
602
614
  }
603
615
 
604
616
  save(): void {
605
- this.saveSourceFrame(this.currentSourceFrame());
617
+ this.saveSourceView(this.visibleView());
606
618
  }
607
619
 
608
620
  saveAll(): void {
609
621
  const sourceFrames = this.editorContainer.fileViews();
610
- sourceFrames.forEach(this.saveSourceFrame.bind(this));
622
+ sourceFrames.forEach(this.saveSourceView.bind(this));
611
623
  }
612
624
 
613
- private saveSourceFrame(sourceFrame: UI.Widget.Widget|null): void {
614
- if (!(sourceFrame instanceof UISourceCodeFrame)) {
615
- return;
625
+ private saveSourceView(sourceView: UI.Widget.Widget|null): void {
626
+ if (sourceView instanceof UISourceCodeFrame || sourceView instanceof Components.HeadersView.HeadersView) {
627
+ sourceView.commitEditing();
616
628
  }
617
- const uiSourceCodeFrame = (sourceFrame as UISourceCodeFrame);
618
- uiSourceCodeFrame.commitEditing();
619
629
  }
620
630
 
621
631
  toggleBreakpointsActiveState(active: boolean): void {
@@ -764,9 +774,12 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
764
774
  }
765
775
  }
766
776
 
777
+ const HEADER_OVERRIDES_FILENAME = '.headers';
778
+
767
779
  // eslint-disable-next-line rulesdir/const_enum
768
780
  enum SourceViewType {
769
781
  ImageView = 'ImageView',
770
782
  FontView = 'FontView',
783
+ HeadersView = 'HeadersView',
771
784
  SourceView = 'SourceView',
772
785
  }
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Copyright 2022 The Chromium Authors. All rights reserved.
3
+ * Use of this source code is governed by a BSD-style license that can be
4
+ * found in the LICENSE file.
5
+ */
6
+
7
+ :host {
8
+ flex-grow: 1;
9
+ }
10
+
11
+ .center-wrapper {
12
+ height: 100%;
13
+ display: flex;
14
+ justify-content: center;
15
+ align-items: center;
16
+ }
17
+
18
+ .centered {
19
+ margin: 1em;
20
+ max-width: 300px;
21
+ text-align: center;
22
+ }
23
+
24
+ .error-header {
25
+ font-weight: bold;
26
+ margin-bottom: 1em;
27
+ }
28
+
29
+ .error-body {
30
+ line-height: 1.5em;
31
+ color: var(--color-text-secondary);
32
+ }
@@ -0,0 +1,89 @@
1
+ // Copyright 2022 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as i18n from '../../../core/i18n/i18n.js';
6
+ import * as Persistence from '../../../models/persistence/persistence.js';
7
+ import type * as Workspace from '../../../models/workspace/workspace.js';
8
+ import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
9
+ import * as UI from '../../../ui/legacy/legacy.js';
10
+ import * as LitHtml from '../../../ui/lit-html/lit-html.js';
11
+
12
+ import HeadersViewStyles from './HeadersView.css.js';
13
+
14
+ const UIStrings = {
15
+ /**
16
+ *@description Error message for files which cannot not be parsed.
17
+ *@example {.headers} PH1
18
+ */
19
+ errorWhenParsing: 'Error when parsing \'\'{PH1}\'\'.',
20
+ /**
21
+ *@description Explainer for files which cannot be parsed.
22
+ *@example {.headers} PH1
23
+ */
24
+ parsingErrorExplainer:
25
+ 'This is most likely due to a syntax error in \'\'{PH1}\'\'. Try opening this file in an external editor to fix the error or delete the file and re-create the override.',
26
+ };
27
+ const str_ = i18n.i18n.registerUIStrings('panels/sources/components/HeadersView.ts', UIStrings);
28
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
29
+
30
+ export class HeadersView extends UI.View.SimpleView {
31
+ readonly #headersViewComponent = new HeadersViewComponent();
32
+ #uiSourceCode: Workspace.UISourceCode.UISourceCode;
33
+
34
+ constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode) {
35
+ super('HeadersView');
36
+ this.#uiSourceCode = uiSourceCode;
37
+ this.element.appendChild(this.#headersViewComponent);
38
+ this.#headersViewComponent.data = {
39
+ uiSourceCode: this.#uiSourceCode,
40
+ };
41
+ }
42
+
43
+ commitEditing(): void {
44
+ this.#uiSourceCode.commitWorkingCopy();
45
+ Persistence.NetworkPersistenceManager.NetworkPersistenceManager.instance().updateInterceptionPatterns();
46
+ }
47
+ }
48
+
49
+ export interface HeadersViewComponentData {
50
+ uiSourceCode: Workspace.UISourceCode.UISourceCode;
51
+ }
52
+
53
+ export class HeadersViewComponent extends HTMLElement {
54
+ static readonly litTagName = LitHtml.literal`devtools-sources-headers-view`;
55
+ readonly #shadow = this.attachShadow({mode: 'open'});
56
+ #uiSourceCode: Workspace.UISourceCode.UISourceCode|null = null;
57
+
58
+ connectedCallback(): void {
59
+ this.#shadow.adoptedStyleSheets = [HeadersViewStyles];
60
+ }
61
+
62
+ set data(data: HeadersViewComponentData) {
63
+ this.#uiSourceCode = data.uiSourceCode;
64
+ this.#render();
65
+ }
66
+
67
+ #render(): void {
68
+ const fileName = this.#uiSourceCode?.name() || '.headers';
69
+ // clang-format off
70
+ LitHtml.render(LitHtml.html`
71
+ <div class="center-wrapper">
72
+ <div class="centered">
73
+ <div class="error-header">${i18nString(UIStrings.errorWhenParsing, {PH1: fileName})}</div>
74
+ <div class="error-body">${i18nString(UIStrings.parsingErrorExplainer, {PH1: fileName})}</div>
75
+ </div>
76
+ </div>
77
+ `, this.#shadow, {host: this});
78
+ // clang-format on
79
+ }
80
+ }
81
+
82
+ ComponentHelpers.CustomElements.defineComponent('devtools-sources-headers-view', HeadersViewComponent);
83
+
84
+ declare global {
85
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
86
+ interface HTMLElementTagNameMap {
87
+ 'devtools-sources-headers-view': HeadersViewComponent;
88
+ }
89
+ }
@@ -0,0 +1,9 @@
1
+ // Copyright 2022 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as HeadersView from './HeadersView.js';
6
+
7
+ export {
8
+ HeadersView,
9
+ };
@@ -0,0 +1,62 @@
1
+ // Copyright 2022 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as SDK from '../../../core/sdk/sdk.js';
6
+ import * as LitHtml from '../../lit-html/lit-html.js';
7
+ import * as ComponentHelpers from '../helpers/helpers.js';
8
+
9
+ import chromeLinkStyles from './chromeLink.css.js';
10
+
11
+ declare global {
12
+ interface HTMLElementTagNameMap {
13
+ 'devtools-chrome-link': ChromeLink;
14
+ }
15
+ }
16
+
17
+ // Use this component to render links to 'chrome://...'-URLs
18
+ // (for which regular <x-link>s do not work).
19
+ export class ChromeLink extends HTMLElement {
20
+ static readonly litTagName = LitHtml.literal`devtools-chrome-link`;
21
+ readonly #shadow = this.attachShadow({mode: 'open'});
22
+ readonly #boundRender = this.#render.bind(this);
23
+ #href: string = '';
24
+
25
+ connectedCallback(): void {
26
+ this.#shadow.adoptedStyleSheets = [chromeLinkStyles];
27
+ void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
28
+ }
29
+
30
+ set href(href: string) {
31
+ if (!href.startsWith('chrome://')) {
32
+ throw new Error('ChromeLink href needs to start with \'chrome://\'');
33
+ }
34
+ this.#href = href;
35
+ void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
36
+ }
37
+
38
+ // Navigating to a chrome:// link via a normal anchor doesn't work, so we "navigate"
39
+ // there using CDP.
40
+ openSettingsTab(event: Event): void {
41
+ if (event.type === 'click' || (event.type === 'keydown' && self.isEnterOrSpaceKey(event))) {
42
+ const mainTarget = SDK.TargetManager.TargetManager.instance().mainTarget();
43
+ mainTarget && mainTarget.targetAgent().invoke_createTarget({url: this.#href});
44
+ event.consume(true);
45
+ }
46
+ }
47
+
48
+ #render(): void {
49
+ // clang-format off
50
+ LitHtml.render(
51
+ /* x-link doesn't work with custom click/keydown handlers */
52
+ /* eslint-disable rulesdir/ban_a_tags_in_lit_html */
53
+ LitHtml.html`
54
+ <a href=${this.#href} class="link" target="_blank"
55
+ @click=${this.openSettingsTab}
56
+ @keydown=${this.openSettingsTab}><slot></slot></a>
57
+ `, this.#shadow, {host: this});
58
+ // clang-format on
59
+ }
60
+ }
61
+
62
+ ComponentHelpers.CustomElements.defineComponent('devtools-chrome-link', ChromeLink);
@@ -0,0 +1,12 @@
1
+ /*
2
+ * Copyright 2022 The Chromium Authors. All rights reserved.
3
+ * Use of this source code is governed by a BSD-style license that can be
4
+ * found in the LICENSE file.
5
+ */
6
+
7
+ .link {
8
+ color: var(--color-link);
9
+ text-decoration: underline;
10
+ cursor: pointer;
11
+ padding: 2px 0; /* adjust focus ring size */
12
+ }
@@ -0,0 +1,9 @@
1
+ // Copyright 2022 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as ChromeLink from './ChromeLink.js';
6
+
7
+ export {
8
+ ChromeLink,
9
+ };
package/package.json CHANGED
@@ -54,5 +54,5 @@
54
54
  "unittest": "scripts/test/run_unittests.py --no-text-coverage",
55
55
  "watch": "third_party/node/node.py --output scripts/watch_build.js"
56
56
  },
57
- "version": "1.0.975699"
57
+ "version": "1.0.976703"
58
58
  }