refactor: add g3-only and 3p-only markers to replace specific g3 patches

Replace specific file patches applied during google3 sync with generic comment-based mechanisms.

By adding `// g3-only` prefix comments to g3-specific exports and declarations, and appending `// 3p-only` context to `@internal` tags, we enable generic tooling to handle these modifications during the sync process.

Additionally, wrap 3rd-party-only imports and exports (which should be stripped in google3) with `// 3p-only-start` and `// 3p-only-end` comment markers.

This reduces the need for maintaining custom file-specific patches in google3.

Also, add a comprehensive guide to these sync comment markers in `contributing-docs/google-markers.md` to assist external contributors.

Specifically:
- Add `// 3p-only` context to `@internal` in `directives.ts` for `foreignImports` and `deferredImports`.
- Add `// g3-only` commented exports in `core.ts`.
- Add `// g3-only-start`/`// g3-only-end` commented global declaration block in `zone.ts`.
- Wrap 3p-only imports in `fake_navigation.ts` with `// 3p-only-start` and `// 3p-only-end`.
- Wrap 3p-only exports in `compiler-cli/index.ts` with `// 3p-only-start` and `// 3p-only-end`.
- Add `// g3-only` and `// 3p-only` markers to `shared.ts` for `setDisabledStateDefault` configuration.
- Add `// g3-only` and `// 3p-only` markers to `feature_detection.ts` for semver dependency.
- Add `// g3-only` and `// 3p-only` markers to `domino_adapter.ts` for domino import path.
- Add `// 3p-only` marker to `ng_dev_mode` import in `event_dispatcher.ts`.
- Add `// g3-only` and `// 3p-only` markers to `MOUSE_SPECIAL_SUPPORT` in `event_contract_defines.ts`.
- Add `// g3-only` and `// 3p-only` markers to `BrowserModule` imports in `module.ts` (animations) and `browser.ts` (testing).
- Add `// 3p-only` marker to `goog.d.ts` reference tags in `util.ts` (platform-browser), `types.d.ts`, `ng_i18n_closure_mode.ts`, `tokens.ts`, and `global_utils.ts`.
- Wrap `Default` enum value of `ChangeDetectionStrategy` in `constants.ts` with `// 3p-only-start` and `// 3p-only-end`.
- Add `// g3-only` and `// 3p-only` markers to `LEGACY_OPTIONAL_CHAINING_DEFAULT` in `legacy_optional_chaining_default.ts` and `legacyOptionalChaining` in `directive.ts`.
- Add `// g3-only` and `// 3p-only` markers to `DEFAULT_PARAMS_INHERITANCE_STRATEGY` in `router_state.ts`.
- Add `// g3-only` and `// 3p-only` (and block variants) markers to `@mcp-b/webmcp-types` imports in `declare_tool.ts`, `provide_tools.ts`, and `types.ts`.
- Add `contributing-docs/google-markers.md` guide.

TAG=agy
CONV=cd09a4f3-869a-4f41-949b-c91f1b8f1c51
This commit is contained in:
Alex Rickabaugh 2026-05-21 13:11:17 -07:00
parent 06b004ec5c
commit 4821239c41
25 changed files with 149 additions and 22 deletions

View file

@ -0,0 +1,95 @@
# Angular Google Sync Comment Markers Guide
This document describes the comment-based markers used in the Angular repository to manage the synchronization process between the public GitHub repository and Google's internal codebase (google3).
As an Angular contributor, you will occasionally encounter these markers in the codebase. Most external contributors will never need to **write** these markers themselves. Instead, this guide exists to explain what these markers mean and why they are in the code when you run into them.
These tags are necessary because Google's internal codebase builds and integrates Angular in a slightly different configuration than the public NPM packages. For example, Google may require certain APIs to remain public internally for integration purposes, or might need to bypass public-only configurations. These markers allow the automated sync tooling to adjust the code seamlessly during the import process.
---
## Reference Table
The following markers are processed during the synchronization to Google's internal codebase:
| Marker | Type | Action in Google's Codebase | Intended Use Case |
| :-------------------------------------------- | :---------- | :------------------------------------------ | :------------------------------------------------------------------------------------------ |
| **`// 3p-only`** | Single-line | **Strip**: Deletes the entire line | Remove imports or calls that only exist in the public version. |
| **`// 3p-only-start`** / **`// 3p-only-end`** | Block | **Strip**: Deletes the entire block | Remove larger chunks of public-only code (e.g., benchmarking suites, public-only adapters). |
| **`// g3-only`** | Single-line | **Insert**: Uncomments the rest of the line | Export Google-internal symbols or activate Google-specific configurations. |
| **`// g3-only-start`** / **`// g3-only-end`** | Block | **Insert**: Uncomments every line inside | Add larger Google-specific functions or class definitions. |
---
## Detailed Marker Explanations & Examples
### 1. Removing Single Lines (`// 3p-only`)
This tag is appended at the end of a line comment to completely remove that line when the code is synced internally to Google.
- **GitHub Source**:
```typescript
import {ExternalBenchmarkRunner} from './benchmarks'; // 3p-only
```
- **Google's Internal Codebase**:
_(The line is completely removed)_
---
### 2. Removing Blocks of Code (`// 3p-only-start` / `// 3p-only-end`)
Blocks of code that should only run in the public version are surrounded by these markers. The entire block is stripped during the sync.
- **GitHub Source**:
```typescript
// 3p-only-start
export function initializeDevTools() {
console.log('Setting up external devtools...');
setupExternalDebugger();
}
// 3p-only-end
```
- **Google's Internal Codebase**:
_(The entire block, including markers, is completely removed)_
---
### 3. Activating Single Lines (`// g3-only`)
Google-specific code is written as a comment and prefixed with `// g3-only`. The sync tooling uncomments this line when importing it into Google's codebase.
- **GitHub Source**:
```typescript
// g3-only export {ForeignComponent} from './interface/foreign_component';
```
- **Google's Internal Codebase**:
```typescript
export {ForeignComponent} from './interface/foreign_component';
```
---
### 4. Activating Blocks of Code (`// g3-only-start` / `// g3-only-end`)
Larger blocks of Google-specific code are commented out line-by-line and wrapped in the `g3-only` start/end markers. The sync tooling strips the markers and uncomments all lines in between.
- **GitHub Source**:
```typescript
// g3-only-start
// export function getGoogleSpecificConfig() {
// return {
// enableInternalLogging: true,
// useInternalDatabase: true,
// };
// }
// g3-only-end
```
- **Google's Internal Codebase**:
```typescript
export function getGoogleSpecificConfig() {
return {
enableInternalLogging: true,
useInternalDatabase: true,
};
}
```

View file

@ -18,6 +18,7 @@ export * from './src/perform_compile';
// TODO(tbosch): remove this once usages in G3 are changed to `CompilerOptions`
export {CompilerOptions as AngularCompilerOptions} from './src/transformers/api';
// 3p-only-start
// Internal exports needed for packages relying on the compiler-cli.
// TODO: Remove this when the CLI has switched to the private entry-point.
export * from './private/tooling';
@ -27,6 +28,7 @@ export * from './private/hybrid_analysis';
// Exposed as they are needed for relying on the `linker`.
export * from './src/ngtsc/logging';
export * from './src/ngtsc/file_system';
// 3p-only-end
// Exports for dealing with the `ngtsc` program.
export {NgTscPlugin, PluginCompilerHost} from './src/ngtsc/tsc_plugin';

View file

@ -8,7 +8,7 @@
// Note: semver isn't available internally so this import will be commented out.
// When adding more dependencies here, the caretaker may have to update a patch internally.
import semver from 'semver';
import semver from 'semver'; // 3p-only
/**
* Whether a version of `@angular/core` supports a specific feature.
@ -23,5 +23,6 @@ export function coreVersionSupportsFeature(coreVersion: string, minVersion: stri
return true;
}
return semver.satisfies(coreVersion, minVersion, {includePrerelease: true});
// g3-only return true;
return semver.satisfies(coreVersion, minVersion, {includePrerelease: true}); // 3p-only
}

View file

@ -11,4 +11,5 @@
*
* This is extracted in order to be patched in G3.
*/
export const LEGACY_OPTIONAL_CHAINING_DEFAULT = false;
// g3-only export const LEGACY_OPTIONAL_CHAINING_DEFAULT = true;
export const LEGACY_OPTIONAL_CHAINING_DEFAULT = false; // 3p-only

View file

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
// 3p-only-start
import {
NavigationNavigateOptions,
NavigationTypeString,
@ -21,6 +22,7 @@ import {
NavigationDestination,
Navigation,
} from '../src/navigation_types';
// 3p-only-end
/**
* Fake implementation of user agent history and navigation behavior. This is a
@ -616,13 +618,13 @@ export class FakeNavigation implements Navigation {
set oncurrententrychange(
_handler: // tslint:disable-next-line:no-any
((this: Navigation, ev: NavigationCurrentEntryChangeEvent) => any) | null,
((this: Navigation, ev: NavigationCurrentEntryChangeEvent) => any) | null,
) {
throw new Error('unimplemented');
}
get oncurrententrychange(): // tslint:disable-next-line:no-any
((this: Navigation, ev: NavigationCurrentEntryChangeEvent) => any) | null {
((this: Navigation, ev: NavigationCurrentEntryChangeEvent) => any) | null {
throw new Error('unimplemented');
}

View file

@ -10,4 +10,5 @@
* @define Support for the non-bubbling mouseenter and mouseleave events. This
* flag can be overridden in a build rule.
*/
export const MOUSE_SPECIAL_SUPPORT = false;
// g3-only export const MOUSE_SPECIAL_SUPPORT = goog.define('jsaction.EventContract.MOUSE_SPECIAL_SUPPORT', false,);
export const MOUSE_SPECIAL_SUPPORT = false; // 3p-only

View file

@ -14,7 +14,7 @@ import {UnrenamedEventContract} from './eventcontract';
import {Restriction} from './restriction';
// Necessary to make the `ngDevMode` global types available.
import '../../../src/util/ng_dev_mode';
import '../../../src/util/ng_dev_mode'; // 3p-only
/**
* A replayer is a function that is called when there are queued events, from the `EventContract`.

View file

@ -38,6 +38,8 @@ export enum ChangeDetectionStrategy {
* explicitly deactivated.
* @deprecated Use `Eager` instead.
*/
// 3p-only-start
// tslint:disable-next-line:no-duplicate-enum-values
Default = 1,
// 3p-only-end
}

View file

@ -76,6 +76,7 @@ export {
TRANSLATIONS,
TRANSLATIONS_FORMAT,
} from './i18n/tokens';
// g3-only export {ForeignComponent} from './interface/foreign_component';
export {AbstractType, Type} from './interface/type';
export * from './linker';
export * from './linker/ng_module_factory_loader_impl';
@ -111,6 +112,7 @@ export {
outputBinding,
twoWayBinding,
} from './render3/dynamic_bindings';
// g3-only export {foreignImport} from './render3/foreign_import';
export {createEnvironmentInjector, createNgModule} from './render3/ng_module_ref';
export {publishExternalGlobalUtil as ɵpublishExternalGlobalUtil} from './render3/util/global_utils';
export * from './resource';

View file

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
/// <reference path="../../../goog.d.ts" />
/// <reference path="../../../goog.d.ts" /> // 3p-only
import {InjectionToken} from '../di/injection_token';
import {inject} from '../di/injector_compatibility';

View file

@ -646,7 +646,7 @@ export interface Component extends Directive {
* The foreignImports property specifies components from other frameworks that can be used
* within this component's template.
*
* @internal
* @internal // 3p-only
*/
foreignImports?: ForeignComponent[];
@ -657,7 +657,7 @@ export interface Component extends Directive {
* which bring symbols used in the `deferredImports` don't contain other symbols.
*
* Note: this is an internal-only field, use regular `@Component.imports` field instead.
* @internal
* @internal // 3p-only
*/
deferredImports?: (Type<any> | ReadonlyArray<any>)[];

View file

@ -376,7 +376,8 @@ export function directiveMetadata(type: Type<any>, metadata: Directive): R3Direc
return {
name: type.name,
legacyOptionalChaining: false,
// g3-only legacyOptionalChaining: true,
legacyOptionalChaining: false, // 3p-only
type: type,
selector: metadata.selector !== undefined ? metadata.selector : null,
host: metadata.host || EMPTY_OBJ,

View file

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
/// <reference path="../../../../goog.d.ts" />
/// <reference path="../../../../goog.d.ts" /> // 3p-only
import {assertDefined} from '../../util/assert';
import {global} from '../../util/global';

View file

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
/// <reference path="../../../goog.d.ts" />
/// <reference path="../../../goog.d.ts" /> // 3p-only
import {global} from './global';

View file

@ -6,7 +6,8 @@
* found in the LICENSE file at https://angular.dev/license
*/
import type {JsonSchemaForInference} from '../../third_party/@mcp-b/webmcp-types';
// g3-only import type {JsonSchemaForInference} from '@mcp-b/webmcp-types';
import type {JsonSchemaForInference} from '../../third_party/@mcp-b/webmcp-types'; // 3p-only
import {assertInInjectionContext, inject, Injector, runInInjectionContext} from '../di';
import type {ModelContext, ToolDescriptor} from './types';
import {DestroyRef} from '../linker';

View file

@ -6,7 +6,8 @@
* found in the LICENSE file at https://angular.dev/license
*/
import type {JsonSchemaForInference} from '../../third_party/@mcp-b/webmcp-types';
// g3-only import type {JsonSchemaForInference} from '@mcp-b/webmcp-types';
import type {JsonSchemaForInference} from '../../third_party/@mcp-b/webmcp-types'; // 3p-only
import {EnvironmentProviders, makeEnvironmentProviders, provideEnvironmentInitializer} from '../di';
import {declareExperimentalWebMcpTool} from './declare_tool';
import type {ToolDescriptor} from './types';

View file

@ -6,10 +6,18 @@
* found in the LICENSE file at https://angular.dev/license
*/
// g3-only-start
// import type {
// InferArgsFromInputSchema,
// JsonSchemaForInference,
// } from '@mcp-b/webmcp-types';
// g3-only-end
// 3p-only-start
import type {
InferArgsFromInputSchema,
JsonSchemaForInference,
} from '../../third_party/@mcp-b/webmcp-types';
// 3p-only-end
/**
* The client context of a given WebMCP tool execution.

View file

@ -65,7 +65,8 @@ export type SetDisabledStateOption = 'whenDisabledForLegacyCode' | 'always';
/**
* Whether to use the fixed setDisabledState behavior by default.
*/
export const setDisabledStateDefault: SetDisabledStateOption = 'always';
// g3-only export const setDisabledStateDefault: SetDisabledStateOption = 'whenDisabledForLegacyCode';
export const setDisabledStateDefault: SetDisabledStateOption = 'always'; // 3p-only
export function controlPath(name: string | null, parent: ControlContainer): string[] {
return [...parent.path!, name!];

View file

@ -11,7 +11,8 @@ import {
Provider,
ɵperformanceMarkFeature as performanceMarkFeature,
} from '@angular/core';
import {BrowserModule} from '../../index';
// g3-only import {BrowserModule} from '@angular/platform-browser';
import {BrowserModule} from '../../index'; // 3p-only
import {BROWSER_ANIMATIONS_PROVIDERS, BROWSER_NOOP_ANIMATIONS_PROVIDERS} from './providers';

View file

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
/// <reference path="../../../goog.d.ts" />
/// <reference path="../../../goog.d.ts" /> // 3p-only
import {ɵglobal as global} from '@angular/core';

View file

@ -8,7 +8,8 @@
import {ɵprovideFakePlatformNavigation} from '@angular/common/testing';
import {APP_ID, createPlatformFactory, NgModule, StaticProvider, PlatformRef} from '@angular/core';
import {TestComponentRenderer} from '@angular/core/testing';
import {BrowserModule, platformBrowser} from '../../index';
// g3-only import {BrowserModule, platformBrowser} from '@angular/platform-browser';
import {BrowserModule, platformBrowser} from '../../index'; // 3p-only
import {DOMTestComponentRenderer} from './dom_test_component_renderer';
/**

View file

@ -9,7 +9,8 @@
import {ɵsetRootDomAdapter as setRootDomAdapter} from '@angular/common';
import {ɵBrowserDomAdapter as BrowserDomAdapter} from '@angular/platform-browser';
import domino from '../third_party/domino/bundled-domino';
// g3-only import domino from 'domino';
import domino from '../third_party/domino/bundled-domino'; // 3p-only
export function setDomTypes() {
// Make all Domino types available in the global env.

View file

@ -240,7 +240,8 @@ export class ActivatedRoute {
export type ParamsInheritanceStrategy = 'emptyOnly' | 'always';
export const DEFAULT_PARAMS_INHERITANCE_STRATEGY: ParamsInheritanceStrategy = 'always';
// g3-only export const DEFAULT_PARAMS_INHERITANCE_STRATEGY: ParamsInheritanceStrategy = 'emptyOnly';
export const DEFAULT_PARAMS_INHERITANCE_STRATEGY: ParamsInheritanceStrategy = 'always'; // 3p-only
/** @internal */
export type Inherited = {

2
packages/types.d.ts vendored
View file

@ -11,7 +11,7 @@
// This file contains all ambient imports needed to compile the packages/ source code
/// <reference lib="es2015" />
/// <reference path="./goog.d.ts" />
/// <reference path="./goog.d.ts" /> // 3p-only
/// <reference path="./system.d.ts" />
// Do not included "node" and "jasmine" types here as we don't

View file

@ -31,6 +31,11 @@ declare global {
const Zone: ZoneType;
type Zone = _Zone;
type ZoneType = _ZoneType;
// g3-only-start
// /** This local mod is kept in place so Zone can check the NodeJS `global` variable. */
// var global: {};
// g3-only-end
type _PatchFn = PatchFn;
type _ZonePrivate = ZonePrivate;
type _ZoneFrame = ZoneFrame;