Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@
},
"homepage": "https://github.com/tensorflow/tensorboard#readme",
"devDependencies": {
"@angular-devkit/build-angular": "^21.0.0",
"@angular/build": "^21.0.0",
"@angular-devkit/build-angular": "^22.0.0",
"@angular/build": "^22.0.0",
"@angular/build-tooling": "https://github.com/angular/dev-infra-private-build-tooling-builds.git#b87de6c1190eb38a74ce72a530331f2f184fe918",
"@angular/cli": "^21.0.0",
"@angular/compiler": "21.2.18",
"@angular/compiler-cli": "^21.0.0",
"@angular/cli": "^22.0.0",
"@angular/compiler": "22.1.1",
"@angular/compiler-cli": "^22.0.0",
"@babel/core": "^7.16.12",
"@bazel/concatjs": "5.8.1",
"@bazel/esbuild": "5.8.1",
Expand Down Expand Up @@ -62,20 +62,20 @@
"prettier-plugin-organize-imports": "2.3.4",
"requirejs": "^2.3.7",
"tslib": "^2.3.0",
"typescript": "5.9.3",
"typescript": "6.0.3",
"yarn-deduplicate": "^5.0.0"
},
"dependencies": {
"@angular/animations": "^21.0.0",
"@angular/cdk": "^21.0.0",
"@angular/common": "21.2.18",
"@angular/core": "^21.0.0",
"@angular/forms": "^21.0.0",
"@angular/localize": "^21.0.0",
"@angular/material": "^21.0.0",
"@angular/platform-browser": "^21.0.0",
"@angular/platform-browser-dynamic": "^21.0.0",
"@angular/router": "^21.0.0",
"@angular/animations": "^22.0.0",
"@angular/cdk": "^22.0.0",
"@angular/common": "22.1.1",
"@angular/core": "^22.0.0",
"@angular/forms": "^22.0.0",
"@angular/localize": "^22.0.0",
"@angular/material": "^22.0.0",
"@angular/platform-browser": "^22.0.0",
"@angular/platform-browser-dynamic": "^22.0.0",
"@angular/router": "^22.0.0",
"@ngrx/effects": "^21.0.0",
"@ngrx/store": "^21.0.0",
"@polymer/decorators": "^3.0.0",
Expand Down
73 changes: 47 additions & 26 deletions patches/@bazel+concatjs+5.8.1.patch
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,28 @@ index fed787a..377915a 100755
closure_js = closure_js_files,
devmode_js = devmode_js_files,
diff --git a/node_modules/@bazel/concatjs/internal/common/tsconfig.bzl b/node_modules/@bazel/concatjs/internal/common/tsconfig.bzl
index b01c999..86d61d4 100755
index b01c999..f9684f8 100755
--- a/node_modules/@bazel/concatjs/internal/common/tsconfig.bzl
+++ b/node_modules/@bazel/concatjs/internal/common/tsconfig.bzl
@@ -110,6 +110,48 @@ def create_tsconfig(
@@ -110,6 +110,49 @@ def create_tsconfig(
"*": node_modules_mappings,
ctx.workspace_name + "/*": base_path_mappings,
}
+
+ # Starting with Angular 21, the definition files (*.d.ts) were moved into
+ # one folder, "types/<name>.d.ts", per package; before, we found each one
+ # in its own corresponding folder. These are now resolved only via
+ # package.json "exports", which Bazel's node_modules mapping can't find,
+ # so below we map each package to their corresponding definition files.
+ #
+ # TODO: This patch is planned for removal. These mappings should move
+ # into a TensorBoard-owned ts_library rule under tensorboard/defs.
+ # Starting with Angular 21, each package's *.d.ts files moved into a single
+ # "types/<name>.d.ts" folder, resolved only through package.json "exports",
+ # which Bazel's node_modules mapping cannot follow. So map each package to its
+ # definition files here. This whole patch goes away with the rules_js / rules_ts
+ # migration, which resolves "exports" natively.
+ if node_modules_root:
+ for pkg in [
+ "@angular/cdk",
+ "@angular/common",
+ "@angular/core",
+ # TypeScript 6.0 added error TS2882 for side-effect imports whose types
+ # do not resolve, and bootstrap.ts imports "@angular/localize/init" for
+ # its side effect only.
+ "@angular/localize",
+ "@angular/material",
+ "@angular/platform-browser",
+ "@angular/platform-browser-dynamic",
Expand All @@ -69,8 +70,8 @@ index b01c999..86d61d4 100755
+ "@angular/material/icon/testing": "icon-testing",
+ "@angular/material/menu/testing": "menu-testing",
+ "@angular/material/select/testing": "select-testing",
+ # @ngrx/* uses a package-name-prefixed types filename instead
+ # of the plain "types/<entry-point>.d.ts" Angular packages use.
+ # @ngrx/* uses a package-name-prefixed types filename instead of the
+ # plain "types/<entry-point>.d.ts" that Angular packages use.
+ "@ngrx/store/testing": "ngrx-store-testing",
+ "@ngrx/effects/testing": "ngrx-effects-testing",
+ }.items():
Expand All @@ -81,17 +82,37 @@ index b01c999..86d61d4 100755
module_mappings = get_module_mappings(ctx.label, ctx.attr, srcs = srcs)

# To determine the path for auto-imports, TypeScript's language service
diff --git a/node_modules/@bazel/concatjs/package.json b/node_modules/@bazel/concatjs/package.json
index dbc7cee..1129289 100755
--- a/node_modules/@bazel/concatjs/package.json
+++ b/node_modules/@bazel/concatjs/package.json
@@ -24,7 +24,8 @@
"dependencies": {
"protobufjs": "6.8.8",
"source-map-support": "0.5.9",
- "tsutils": "3.21.0"
+ "tsutils": "3.21.0",
+ "typescript": "5.9.3"
},
"peerDependencies": {
"karma": ">=4.0.0",
diff --git a/node_modules/@bazel/concatjs/internal/tsc_wrapped/tsconfig.js b/node_modules/@bazel/concatjs/internal/tsc_wrapped/tsconfig.js
index e049d15..9ebeec4 100755
--- a/node_modules/@bazel/concatjs/internal/tsc_wrapped/tsconfig.js
+++ b/node_modules/@bazel/concatjs/internal/tsc_wrapped/tsconfig.js
@@ -66,6 +66,13 @@ function parseTsconfig(tsconfigFile, host = ts.sys) {
: existingBazelOpts.googmodule, devmodeTargetOverride: isUndefined(existingBazelOpts.devmodeTargetOverride)
? newBazelBazelOpts.devmodeTargetOverride
: existingBazelOpts.devmodeTargetOverride });
+ // Same reasoning as the bazelOptions merge above, applied to the top-level
+ // "angularCompilerOptions" block. Without this the block in the root
+ // tsconfig.json is silently dropped, because only the generated per-target
+ // tsconfig is ever inspected. The nearer config wins, like "extends" does.
+ if (config.angularCompilerOptions) {
+ mergedConfig.angularCompilerOptions = Object.assign({}, config.angularCompilerOptions, existingConfig.angularCompilerOptions || {});
+ }
}
if (config.extends) {
let extendedConfigPath = resolveNormalizedPath(path.dirname(configFile), config.extends);
@@ -145,6 +152,15 @@ function parseTsconfig(tsconfigFile, host = ts.sys) {
bazelOpts.nodeModulesPrefix =
resolveNormalizedPath(options.rootDir, bazelOpts.nodeModulesPrefix);
}
+ // NgTscPlugin is built from bazelOptions.angularCompilerOptions, so user options
+ // carried up the extends chain above must be folded in here or the Angular compiler
+ // never sees them. The guard matters: that object already existing is what marks a
+ // target as use_angular_plugin, so creating it here would load the Angular plugin
+ // for plain ts_library targets too. Bazel's own keys win, being build mechanics
+ // rather than user choice.
+ if (bazelOpts.angularCompilerOptions && config.angularCompilerOptions) {
+ bazelOpts.angularCompilerOptions = Object.assign({}, config.angularCompilerOptions, bazelOpts.angularCompilerOptions);
+ }
if (bazelOpts.angularCompilerOptions && bazelOpts.angularCompilerOptions.assets) {
bazelOpts.angularCompilerOptions.assets = bazelOpts.angularCompilerOptions.assets.map(f => resolveNormalizedPath(options.rootDir, f));
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import {State} from './store/debugger_types';
selector: 'tf-debugger-v2',
template: `
<debugger-component
[runs]="runs$ | async"
[runIds]="runsIds$ | async"
[runs]="(runs$ | async)!"
[runIds]="(runsIds$ | async)!"
[activeRunId]="activeRunId$ | async"
></debugger-component>
`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ const ALERT_TYPE_TO_DISPLAY_NAME_AND_SYMBOL: {
selector: 'tf-debugger-v2-alerts',
template: `
<alerts-component
[numAlerts]="numAlerts$ | async"
[alertsBreakdown]="alertsBreakdown$ | async"
[numAlerts]="(numAlerts$ | async)!"
[alertsBreakdown]="(alertsBreakdown$ | async)!"
[focusType]="focusType$ | async"
(onToggleFocusType)="onToggleFocusType($event)"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ export class DebugTensorHasInfOrNaNComponent {
</debug-tensor-has-inf-or-nan>
<debug-tensor-numeric-breakdown
*ngIf="debugTensorValue.size !== undefined"
size="{{ debugTensorValue.size }}"
[size]="debugTensorValue.size"
[numNegativeInfs]="debugTensorValue.numNegativeInfs"
[numPositiveInfs]="debugTensorValue.numPositiveInfs"
[numNaNs]="debugTensorValue.numNaNs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class ExecutionDataComponent {

/** Debug tensor values under non-FULL_TENSOR debug modes. */
@Input()
debugTensorValues: number[][] | null = null;
debugTensorValues: (number[] | null)[] | null = null;

/**
* Dtypes of the tensors.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ const UNKNOWN_DTYPE_NAME = 'Unknown dtype';
template: `
<execution-data-component
[focusedExecutionIndex]="focusedExecutionIndex"
[focusedExecutionData]="focusedExecutionData$ | async"
[tensorDebugMode]="tensorDebugMode$ | async"
[hasDebugTensorValues]="hasDebugTensorValues$ | async"
[focusedExecutionData]="(focusedExecutionData$ | async)!"
[tensorDebugMode]="(tensorDebugMode$ | async)!"
[hasDebugTensorValues]="(hasDebugTensorValues$ | async)!"
[debugTensorValues]="debugTensorValues$ | async"
[debugTensorDtypes]="debugTensorDtypes$ | async"
></execution-data-component>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import {State} from '../../store/debugger_types';
selector: 'tf-debugger-v2-graph',
template: `
<graph-component
[opInfo]="opInfo$ | async"
[inputOps]="inputOps$ | async"
[consumerOps]="consumerOps$ | async"
[opInfo]="(opInfo$ | async)!"
[inputOps]="(inputOps$ | async)!"
[consumerOps]="(consumerOps$ | async)!"
(onGraphOpNavigate)="onGraphOpNavigate($event)"
></graph-component>
`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ import {State} from '../../store/debugger_types';
selector: 'tf-debugger-v2-graph-executions',
template: `
<graph-executions-component
[numGraphExecutions]="numGraphExecutions$ | async"
[graphExecutionData]="graphExecutionData$ | async"
[graphExecutionIndices]="graphExecutionIndices$ | async"
[numGraphExecutions]="(numGraphExecutions$ | async)!"
[graphExecutionData]="(graphExecutionData$ | async)!"
[graphExecutionIndices]="(graphExecutionIndices$ | async)!"
[focusIndex]="focusIndex$ | async"
[focusInputIndices]="focusInputIndices$ | async"
(onScrolledIndexChange)="onScrolledIndexChange($event)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {State as DebuggerState} from '../../store/debugger_types';
<source-files-component
[focusedSourceFileContent]="focusedSourceFileContent$ | async"
[focusedSourceLineSpec]="focusedSourceLineSpec$ | async"
[useDarkMode]="useDarkMode$ | async"
[useDarkMode]="(useDarkMode$ | async)!"
></source-files-component>
`,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {StackFrameForDisplay} from './stack_trace_component';
[opName]="opName$ | async"
[executionIndex]="executionIndex$ | async"
[stickToBottommostFrameInFocusedFile]="
stickToBottommostFrameInFocusedFile$ | async
(stickToBottommostFrameInFocusedFile$ | async)!
"
[stackFramesForDisplay]="stackFramesForDisplay$ | async"
(onSourceLineClicked)="onSourceLineClicked($event)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,14 @@ function getExecutionDigestForDisplay(
template: `
<timeline-component
[activeRunId]="activeRunId$ | async"
[loadingNumExecutions]="loadingNumExecutions$ | async"
[numExecutions]="numExecutions$ | async"
[scrollBeginIndex]="scrollBeginIndex$ | async"
[scrollBeginIndexUpperLimit]="scrollBeginIndexUpperLimit$ | async"
[pageSize]="pageSize$ | async"
[displayCount]="displayCount$ | async"
[displayExecutionDigests]="displayExecutionDigests$ | async"
[displayFocusedAlertTypes]="displayFocusedAlertTypes$ | async"
[loadingNumExecutions]="(loadingNumExecutions$ | async)!"
[numExecutions]="(numExecutions$ | async)!"
[scrollBeginIndex]="(scrollBeginIndex$ | async)!"
[scrollBeginIndexUpperLimit]="(scrollBeginIndexUpperLimit$ | async)!"
[pageSize]="(pageSize$ | async)!"
[displayCount]="(displayCount$ | async)!"
[displayExecutionDigests]="(displayExecutionDigests$ | async)!"
[displayFocusedAlertTypes]="(displayFocusedAlertTypes$ | async)!"
[focusedExecutionIndex]="focusedExecutionIndex$ | async"
[focusedExecutionDisplayIndex]="focusedExecutionDisplayIndex$ | async"
(onNavigateLeft)="onNavigateLeft()"
Expand Down
4 changes: 2 additions & 2 deletions tensorboard/webapp/core/views/layout_container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {
<mat-icon svgIcon="expand_more_24px"></mat-icon>
</button>
<nav
*ngIf="(width$ | async) > 0"
*ngIf="((width$ | async) ?? 0) > 0"
class="sidebar"
[style.width.%]="width$ | async"
[style.minWidth.px]="MINIMUM_SIDEBAR_WIDTH_IN_PX"
Expand Down Expand Up @@ -70,7 +70,7 @@ import {
</div>
</nav>
<div
*ngIf="(width$ | async) > 0"
*ngIf="((width$ | async) ?? 0) > 0"
class="resizer"
(mousedown)="resizeGrabbed()"
></div>
Expand Down
2 changes: 1 addition & 1 deletion tensorboard/webapp/core/views/page_title_container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const DEFAULT_BRAND_NAME = 'TensorBoard';
standalone: false,
selector: 'page-title',
template: `
<page-title-component [title]="title$ | async"></page-title-component>
<page-title-component [title]="(title$ | async)!"></page-title-component>
`,
styles: [
`
Expand Down
10 changes: 9 additions & 1 deletion tensorboard/webapp/customization/customization_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ limitations under the License.
import {
ChangeDetectionStrategy,
Component,
Inject,
NgModule,
Optional,
Type,
} from '@angular/core';
import {TestBed} from '@angular/core/testing';
import {CustomizationModule} from './customization_module';
Expand All @@ -43,7 +45,13 @@ export class CustomizableComponentType {}
})
export class ParentComponent {
constructor(
@Optional() readonly customizableComponent: CustomizableComponentType
// CustomizableComponentType is only an injection token here. What gets
// provided for it is a component class, via useValue, so the injected
// value is a Type rather than an instance of the marker class. The
// explicit @Inject is required once the annotation stops naming the token.
@Inject(CustomizableComponentType)
@Optional()
readonly customizableComponent: Type<unknown>
) {}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@ See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

import {HttpClient, HttpHeaders, HTTP_INTERCEPTORS} from '@angular/common/http';
import {
HttpClientTestingModule,
HttpClient,
HttpHeaders,
HTTP_INTERCEPTORS,
provideHttpClient,
withInterceptorsFromDi,
} from '@angular/common/http';
import {
provideHttpClientTesting,
HttpTestingController,
} from '@angular/common/http/testing';
import {TestBed} from '@angular/core/testing';
Expand All @@ -35,8 +41,13 @@ describe('FeatureFlagHttpInterceptor', () => {

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
// This suite does not go through TBHttpClientModule, so it has to
// supply HttpClient itself. withInterceptorsFromDi() is what lets the
// HTTP_INTERCEPTORS entry below actually run, which is the whole point
// of these tests.
provideHttpClient(withInterceptorsFromDi()),
provideHttpClientTesting(),
provideMockActions(() => of()),
provideMockTbStore(),
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ <h2 class="warning">WARNING: EXPERIMENTAL FEATURES AHEAD!</h2>
</mat-select>
</ng-template>
<ng-template #unsupportedBlock>
<td>Unsupported By UI {{formatFlagValue(flagStatus.value)}}</td>
<td>
Unsupported By UI {{formatFlagValue(flagStatus.defaultValue)}}
</td>
</ng-template>
</tr>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ import {
standalone: false,
selector: 'feature-flag-dialog',
template: `<feature-flag-dialog-component
[featureFlagStatuses]="featureFlags$ | async"
[hasFlagsSentToServer]="hasFlagsSentToServer$ | async"
[showFlagsFilter]="showFlagsFilter$ | async"
[featureFlagStatuses]="(featureFlags$ | async)!"
[hasFlagsSentToServer]="(hasFlagsSentToServer$ | async)!"
[showFlagsFilter]="(showFlagsFilter$ | async)!"
(flagChanged)="onFlagChanged($event)"
(allFlagsReset)="onAllFlagsReset()"
></feature-flag-dialog-component>`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,10 @@ describe('feature_flag_dialog_container', () => {
expect(dataCells.length).toEqual(3);
const selectors = component.querySelectorAll('mat-select');
expect(selectors.length).toEqual(1);
expect(dataCells[2].innerText).toBe('Unsupported By UI - null');
// The template used to read flagStatus.value, which does not exist on
// FeatureFlagStatus, so every unsupported flag rendered 'null'. It now
// reads defaultValue, which for enabledExperimentalPlugins is [].
expect(dataCells[2].innerText).toBe('Unsupported By UI - []');
});

describe('formatFlagValue', () => {
Expand Down
Loading
Loading