Skip to content

Commit

Permalink
feat(core): Make the isStandalone() function available in public API
Browse files Browse the repository at this point in the history
This commit updates an internal `isStandalone` function and exposes it as a public API,
so that it can be used in applications code.

fixes #47919
  • Loading branch information
JeanMeche committed Nov 30, 2022
1 parent 12db492 commit 39db4ad
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 9 deletions.
3 changes: 3 additions & 0 deletions goldens/public-api/core/index.md
Expand Up @@ -787,6 +787,9 @@ export interface InputDecorator {
// @public
export function isDevMode(): boolean;

// @public
export function isStandalone(type: Type<unknown>): boolean;

// @public
export interface IterableChangeRecord<V> {
readonly currentIndex: number | null;
Expand Down
6 changes: 6 additions & 0 deletions packages/compiler/test/expression_parser/lexer_spec.ts
Expand Up @@ -343,6 +343,12 @@ function expectErrorToken(token: Token, index: any, end: number, message: string
lex('1_2_3._456')[0], 6, 6,
'Lexer Error: Invalid numeric separator at column 6 in expression [1_2_3._456]');
});

fit('should parse without escaping', () => {
const ast = lex('{{ 1 && 1 ? \'&nbsp;\' : \'lala\' }}');
console.log(ast)
expect((ast)).toEqual([]);
})
});
});
}
2 changes: 1 addition & 1 deletion packages/compiler/test/expression_parser/parser_spec.ts
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {AbsoluteSourceSpan, ASTWithSource, BindingPipe, Call, EmptyExpr, Interpolation, ParserError, TemplateBinding, VariableBinding} from '@angular/compiler/src/expression_parser/ast';
import {AbsoluteSourceSpan, ASTWithSource, BindingPipe, Call, Conditional, EmptyExpr, Interpolation, LiteralPrimitive, ParserError, TemplateBinding, VariableBinding} from '@angular/compiler/src/expression_parser/ast';
import {Lexer} from '@angular/compiler/src/expression_parser/lexer';
import {Parser, SplitInterpolation} from '@angular/compiler/src/expression_parser/parser';
import {expect} from '@angular/platform-browser/testing/src/matchers';
Expand Down
9 changes: 9 additions & 0 deletions packages/compiler/test/ml_parser/lexer_spec.ts
Expand Up @@ -755,6 +755,15 @@ import {ParseLocation, ParseSourceFile, ParseSourceSpan} from '../../src/parse_u
]);
});

fit('should XXXXXXXX', () => {
const tok = tokenizeAndHumanizeParts('{{ 1 && 1 ? \'&nbsp;\' : \'lala\' }}');
console.log(tok);
expect(tok).toEqual([
[TokenType.TEXT, 'a'],
[TokenType.EOF, ''],
]);
});

it('should allow "<" in text nodes', () => {
expect(tokenizeAndHumanizeParts('{{ a < b ? c : d }}')).toEqual([
[TokenType.TEXT, ''],
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/core.ts
Expand Up @@ -38,6 +38,7 @@ export {SecurityContext} from './sanitization/security';
export {Sanitizer} from './sanitization/sanitizer';
export {createNgModule, createNgModuleRef, createEnvironmentInjector} from './render3/ng_module_ref';
export {createComponent, reflectComponentType, ComponentMirror} from './render3/component';
export {isStandalone} from './render3/definition';

import {global} from './util/global';
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/core_render3_private_export.ts
Expand Up @@ -248,7 +248,6 @@ export {
export {
compilePipe as ɵcompilePipe,
} from './render3/jit/pipe';
export { isStandalone as ɵisStandalone} from './render3/definition';
export { Profiler as ɵProfiler, ProfilerEvent as ɵProfilerEvent } from './render3/profiler';
export {
publishDefaultGlobalUtils as ɵpublishDefaultGlobalUtils
Expand Down
11 changes: 9 additions & 2 deletions packages/core/src/render3/definition.ts
Expand Up @@ -7,7 +7,6 @@
*/

import {ChangeDetectionStrategy} from '../change_detection/constants';
import {NG_PROV_DEF} from '../di/interface/defs';
import {Mutable, Type} from '../interface/type';
import {NgModuleDef} from '../metadata/ng_module_def';
import {SchemaMetadata} from '../metadata/schema';
Expand Down Expand Up @@ -741,7 +740,15 @@ export function getPipeDef<T>(type: any): PipeDef<T>|null {
return type[NG_PIPE_DEF] || null;
}

export function isStandalone<T>(type: Type<T>): boolean {
/**
* Checks whether a given Component, Directive or Pipe is marked as standalone.
* This will false if passed anything other than a Component, Directive, or Pipe class
* See this guide for additional information: https://angular.io/guide/standalone-components
*
* @param type A reference to a Component, Directive or Pipe.
* @publicApi
*/
export function isStandalone(type: Type<unknown>): boolean {
const def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef(type);
return def !== null ? def.standalone : false;
}
Expand Down
4 changes: 1 addition & 3 deletions packages/core/src/render3/jit/module.ts
Expand Up @@ -173,9 +173,7 @@ export function compileNgModuleDefs(
Object.defineProperty(moduleType, NG_INJ_DEF, {
get: () => {
if (ngInjectorDef === null) {
ngDevMode &&
verifySemanticsOfNgModuleDef(
moduleType as any as NgModuleType, allowDuplicateDeclarationsInRoot);
ngDevMode && verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRoot);
const meta: R3InjectorMetadataFacade = {
name: moduleType.name,
type: moduleType,
Expand Down
66 changes: 65 additions & 1 deletion packages/core/test/acceptance/standalone_spec.ts
Expand Up @@ -7,7 +7,7 @@
*/

import {CommonModule} from '@angular/common';
import {Component, createEnvironmentInjector, Directive, EnvironmentInjector, forwardRef, Injector, Input, NgModule, NO_ERRORS_SCHEMA, OnInit, Pipe, PipeTransform, ViewChild, ViewContainerRef} from '@angular/core';
import {Component, createEnvironmentInjector, Directive, EnvironmentInjector, forwardRef, Injector, Input, isStandalone, NgModule, NO_ERRORS_SCHEMA, OnInit, Pipe, PipeTransform, ViewChild, ViewContainerRef} from '@angular/core';
import {TestBed} from '@angular/core/testing';

describe('standalone components, directives, and pipes', () => {
Expand Down Expand Up @@ -847,4 +847,68 @@ describe('standalone components, directives, and pipes', () => {
expect(fixture.nativeElement.textContent).toBe('');
});
});

describe('isStandalone()', () => {
it('should return `true` if component is standalone', () => {
@Component({selector: 'standalone-cmp', standalone: true})
class StandaloneCmp {
}

expect(isStandalone(StandaloneCmp)).toBeTrue();
});

it('should return `false` if component is not standalone', () => {
@Component({selector: 'standalone-cmp', standalone: false})
class StandaloneCmp {
}

expect(isStandalone(StandaloneCmp)).toBeFalse();
});

it('should return `true` if directive is standalone', () => {
@Directive({selector: '[standaloneDir]', standalone: true})
class StandAloneDirective {
}

expect(isStandalone(StandAloneDirective)).toBeTrue();
});

it('should return `false` if directive is standalone', () => {
@Directive({selector: '[standaloneDir]', standalone: false})
class StandAloneDirective {
}

expect(isStandalone(StandAloneDirective)).toBeFalse();
});

it('should return `true` if pipe is standalone', () => {
@Pipe({name: 'standalonePipe', standalone: true})
class StandAlonePipe {
}

expect(isStandalone(StandAlonePipe)).toBeTrue();
});

it('should return `false` if pipe is standalone', () => {
@Pipe({name: 'standalonePipe', standalone: false})
class StandAlonePipe {
}

expect(isStandalone(StandAlonePipe)).toBeFalse();
});

it('should return `false` if the class is not annotated', () => {
class NonAnnotatedClass {}

expect(isStandalone(NonAnnotatedClass)).toBeFalse();
});

it('should return `false` if the class is an NgModule', () => {
@NgModule({})
class Module {
}

expect(isStandalone(Module)).toBeFalse();
});
});
});
1 change: 1 addition & 0 deletions packages/core/test/sanitization/html_sanitizer_spec.ts
Expand Up @@ -22,6 +22,7 @@ function sanitizeHtml(defaultDoc: any, unsafeHtmlInput: string): string {
let logMsgs: string[];

beforeEach(() => {
console.log('html_sanitizer');
defaultDoc = document;
logMsgs = [];
originalLog = console.warn; // Monkey patch DOM.log.
Expand Down
2 changes: 1 addition & 1 deletion packages/router/src/utils/config.ts
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {createEnvironmentInjector, EnvironmentInjector, Type, ɵisStandalone as isStandalone, ɵRuntimeError as RuntimeError} from '@angular/core';
import {createEnvironmentInjector, EnvironmentInjector, isStandalone, Type, ɵRuntimeError as RuntimeError} from '@angular/core';

import {EmptyOutletComponent} from '../components/empty_outlet';
import {RuntimeErrorCode} from '../errors';
Expand Down

0 comments on commit 39db4ad

Please sign in to comment.