mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 15:12:12 +00:00
Support 'this' in static functions, fixes #45; Fix propagation of 'ambient' flag
This commit is contained in:
parent
fea8e65a41
commit
2c0ddf4f80
2
dist/assemblyscript.js
vendored
2
dist/assemblyscript.js
vendored
File diff suppressed because one or more lines are too long
2
dist/assemblyscript.js.map
vendored
2
dist/assemblyscript.js.map
vendored
File diff suppressed because one or more lines are too long
@ -2457,6 +2457,8 @@ function evaluateConstantOffset(compiler: Compiler, expression: Expression): i32
|
||||
return value;
|
||||
}
|
||||
|
||||
const allocateInternalName = "allocate_memory";
|
||||
|
||||
/** Compiles a memory allocation for an instance of the specified class. */
|
||||
export function compileAllocate(
|
||||
compiler: Compiler,
|
||||
@ -2468,11 +2470,11 @@ export function compileAllocate(
|
||||
var module = compiler.module;
|
||||
var options = compiler.options;
|
||||
|
||||
var prototype = program.elementsLookup.get(options.allocateImpl);
|
||||
var prototype = program.elementsLookup.get(allocateInternalName);
|
||||
if (!prototype) {
|
||||
program.error(
|
||||
DiagnosticCode.Cannot_find_name_0,
|
||||
reportNode.range, options.allocateImpl
|
||||
reportNode.range, allocateInternalName
|
||||
);
|
||||
return module.createUnreachable();
|
||||
}
|
||||
@ -2498,6 +2500,8 @@ export function compileAllocate(
|
||||
);
|
||||
}
|
||||
|
||||
const abortInternalName = "abort";
|
||||
|
||||
/** Compiles an abort wired to the conditionally imported 'abort' function. */
|
||||
export function compileAbort(
|
||||
compiler: Compiler,
|
||||
@ -2510,7 +2514,7 @@ export function compileAbort(
|
||||
var stringType = program.typesLookup.get("string"); // might be intended
|
||||
if (!stringType) return module.createUnreachable();
|
||||
|
||||
var abortPrototype = program.elementsLookup.get("abort"); // might be intended
|
||||
var abortPrototype = program.elementsLookup.get(abortInternalName); // might be intended
|
||||
if (!abortPrototype || abortPrototype.kind != ElementKind.FUNCTION_PROTOTYPE) return module.createUnreachable();
|
||||
|
||||
var abortInstance = (<FunctionPrototype>abortPrototype).resolve(); // reports
|
||||
|
@ -142,10 +142,6 @@ export class Options {
|
||||
importMemory: bool = false;
|
||||
/** Static memory start offset. */
|
||||
memoryBase: u32 = 0;
|
||||
/** Memory allocation implementation to use. */
|
||||
allocateImpl: string = "allocate_memory";
|
||||
/** Memory freeing implementation to use. */
|
||||
freeImpl: string = "free_memory";
|
||||
/** If true, generates information necessary for source maps. */
|
||||
sourceMap: bool = false;
|
||||
|
||||
@ -513,7 +509,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var isConstant = global.isAny(CommonFlags.CONST) || global.is(CommonFlags.STATIC | CommonFlags.READONLY);
|
||||
|
||||
// handle imports
|
||||
if (global.is(CommonFlags.DECLARE)) {
|
||||
if (global.is(CommonFlags.AMBIENT)) {
|
||||
|
||||
// constant global
|
||||
if (isConstant) {
|
||||
@ -818,14 +814,14 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var declaration = instance.prototype.declaration;
|
||||
var body = declaration.body;
|
||||
if (body) {
|
||||
if (instance.is(CommonFlags.DECLARE)) {
|
||||
if (instance.is(CommonFlags.AMBIENT)) {
|
||||
this.error(
|
||||
DiagnosticCode.An_implementation_cannot_be_declared_in_ambient_contexts,
|
||||
declaration.name.range
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (!instance.is(CommonFlags.DECLARE)) {
|
||||
if (!instance.is(CommonFlags.AMBIENT)) {
|
||||
this.error(
|
||||
DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration,
|
||||
declaration.name.range
|
||||
@ -4231,7 +4227,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var trampolineSignature = new Signature(trampolineParameterTypes, commonReturnType, commonThisType);
|
||||
var trampolineName = originalName + "|trampoline";
|
||||
trampolineSignature.requiredParameters = maxArguments + 1;
|
||||
trampoline = new Function(original.prototype, trampolineName, trampolineSignature, original.instanceMethodOf);
|
||||
trampoline = new Function(original.prototype, trampolineName, trampolineSignature, original.memberOf);
|
||||
trampoline.flags = original.flags;
|
||||
trampoline.set(CommonFlags.COMPILED);
|
||||
original.trampoline = trampoline;
|
||||
@ -4463,7 +4459,9 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case NodeKind.THIS: {
|
||||
let currentFunction = this.currentFunction;
|
||||
if (currentFunction.is(CommonFlags.INSTANCE)) {
|
||||
let thisType = assert(currentFunction.instanceMethodOf).type;
|
||||
let parent = assert(currentFunction.memberOf);
|
||||
assert(parent.kind == ElementKind.CLASS);
|
||||
let thisType = (<Class>parent).type;
|
||||
this.currentType = thisType;
|
||||
return module.createGetLocal(0, thisType.toNativeType());
|
||||
}
|
||||
@ -4477,7 +4475,9 @@ export class Compiler extends DiagnosticEmitter {
|
||||
case NodeKind.SUPER: {
|
||||
let currentFunction = this.currentFunction;
|
||||
if (currentFunction.is(CommonFlags.INSTANCE)) {
|
||||
let base = assert(currentFunction.instanceMethodOf).base;
|
||||
let parent = assert(currentFunction.memberOf);
|
||||
assert(parent.kind == ElementKind.CLASS);
|
||||
let base = (<Class>parent).base;
|
||||
if (base) {
|
||||
let superType = base.type;
|
||||
this.currentType = superType;
|
||||
@ -4971,10 +4971,12 @@ export class Compiler extends DiagnosticEmitter {
|
||||
)) {
|
||||
return module.createUnreachable();
|
||||
}
|
||||
if (instance.instanceMethodOf) {
|
||||
if (instance.is(CommonFlags.INSTANCE)) {
|
||||
let parent = assert(instance.memberOf);
|
||||
assert(parent.kind == ElementKind.CLASS);
|
||||
targetExpr = this.compileExpression(
|
||||
<Expression>resolved.targetExpression,
|
||||
instance.instanceMethodOf.type
|
||||
(<Class>parent).type
|
||||
);
|
||||
this.currentType = signature.returnType;
|
||||
return this.compileCallDirect(instance, [], propertyAccess, targetExpr);
|
||||
|
@ -87,10 +87,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
backlog: string[] = new Array();
|
||||
/** Log of source file names already processed. */
|
||||
seenlog: Set<string> = new Set();
|
||||
|
||||
currentDeclareStart: i32 = 0;
|
||||
currentDeclareEnd: i32 = 0;
|
||||
|
||||
/** Optional handler to intercept comments while tokenizing. */
|
||||
onComment: CommentHandler | null = null;
|
||||
|
||||
/** Constructs a new parser. */
|
||||
@ -145,7 +142,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
/** Parses a top-level statement. */
|
||||
parseTopLevelStatement(
|
||||
tn: Tokenizer,
|
||||
isNamespaceMember: bool = false
|
||||
namespace: Node | null = null
|
||||
): Statement | null {
|
||||
var flags = CommonFlags.NONE;
|
||||
var startPos: i32 = -1;
|
||||
@ -188,11 +185,18 @@ export class Parser extends DiagnosticEmitter {
|
||||
|
||||
var declareStart: i32 = 0;
|
||||
var declareEnd: i32 = 0;
|
||||
var contextIsAmbient = namespace != null && namespace.is(CommonFlags.AMBIENT);
|
||||
if (tn.skip(Token.DECLARE)) {
|
||||
if (startPos < 0) startPos = tn.tokenPos;
|
||||
flags |= CommonFlags.DECLARE;
|
||||
this.currentDeclareStart = declareStart = tn.tokenPos;
|
||||
this.currentDeclareEnd = declareEnd = tn.pos;
|
||||
if (contextIsAmbient) {
|
||||
this.error(
|
||||
DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context,
|
||||
tn.range()
|
||||
); // recoverable
|
||||
}
|
||||
flags |= CommonFlags.DECLARE | CommonFlags.AMBIENT;
|
||||
} else if (contextIsAmbient) {
|
||||
flags |= CommonFlags.AMBIENT;
|
||||
}
|
||||
|
||||
// parse the statement
|
||||
@ -293,9 +297,9 @@ export class Parser extends DiagnosticEmitter {
|
||||
tn.range(declareStart, declareEnd), "declare"
|
||||
); // recoverable
|
||||
}
|
||||
if (!isNamespaceMember) {
|
||||
if (!namespace) {
|
||||
statement = this.parseStatement(tn, true);
|
||||
}
|
||||
} // TODO: else?
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -761,7 +765,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
if (!initializer) return null;
|
||||
} else {
|
||||
if (flags & CommonFlags.CONST) {
|
||||
if (!(flags & CommonFlags.DECLARE)) {
|
||||
if (!(flags & CommonFlags.AMBIENT)) {
|
||||
this.error(
|
||||
DiagnosticCode._const_declarations_must_be_initialized,
|
||||
identifier.range
|
||||
@ -1173,17 +1177,6 @@ export class Parser extends DiagnosticEmitter {
|
||||
tn.range(signatureStart, tn.pos)
|
||||
);
|
||||
|
||||
if (flags & CommonFlags.DECLARE) {
|
||||
if (flags & CommonFlags.AMBIENT) {
|
||||
this.error(
|
||||
DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context,
|
||||
tn.range(this.currentDeclareStart, this.currentDeclareEnd)
|
||||
); // recoverable
|
||||
} else {
|
||||
flags |= CommonFlags.AMBIENT;
|
||||
}
|
||||
}
|
||||
|
||||
var body: Statement | null = null;
|
||||
if (tn.skip(Token.OPENBRACE)) {
|
||||
if (flags & CommonFlags.AMBIENT) {
|
||||
@ -1393,17 +1386,6 @@ export class Parser extends DiagnosticEmitter {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (flags & CommonFlags.DECLARE) {
|
||||
if (flags & CommonFlags.AMBIENT) {
|
||||
this.error(
|
||||
DiagnosticCode.A_declare_modifier_cannot_be_used_in_an_already_ambient_context,
|
||||
tn.range(this.currentDeclareStart, this.currentDeclareEnd)
|
||||
); // recoverable
|
||||
} else {
|
||||
flags |= CommonFlags.AMBIENT;
|
||||
}
|
||||
}
|
||||
|
||||
var members = new Array<DeclarationStatement>();
|
||||
if (!tn.skip(Token.CLOSEBRACE)) {
|
||||
do {
|
||||
@ -1744,20 +1726,21 @@ export class Parser extends DiagnosticEmitter {
|
||||
let identifier = Node.createIdentifierExpression(tn.readIdentifier(), tn.range());
|
||||
if (tn.skip(Token.OPENBRACE)) {
|
||||
let members = new Array<Statement>();
|
||||
while (!tn.skip(Token.CLOSEBRACE)) {
|
||||
let member = this.parseTopLevelStatement(tn, true);
|
||||
if (!member) return null;
|
||||
members.push(member);
|
||||
}
|
||||
let ret = Node.createNamespaceDeclaration(
|
||||
let ns = Node.createNamespaceDeclaration(
|
||||
identifier,
|
||||
members,
|
||||
decorators,
|
||||
flags,
|
||||
tn.range(startPos, tn.pos)
|
||||
);
|
||||
while (!tn.skip(Token.CLOSEBRACE)) {
|
||||
let member = this.parseTopLevelStatement(tn, ns);
|
||||
if (!member) return null;
|
||||
member.parent = ns;
|
||||
members.push(member);
|
||||
}
|
||||
tn.skip(Token.SEMICOLON);
|
||||
return ret;
|
||||
return ns;
|
||||
} else {
|
||||
this.error(
|
||||
DiagnosticCode._0_expected,
|
||||
|
@ -579,7 +579,7 @@ export class Program extends DiagnosticEmitter {
|
||||
simpleName,
|
||||
internalName,
|
||||
declaration,
|
||||
null
|
||||
classPrototype
|
||||
);
|
||||
classPrototype.members.set(simpleName, prototype);
|
||||
this.elementsLookup.set(internalName, prototype);
|
||||
@ -1748,7 +1748,7 @@ export class Program extends DiagnosticEmitter {
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
// or inherited instance members on the cbase class while target is a class instance
|
||||
// or inherited instance members on the base class while target is a class instance
|
||||
} else if (target.kind == ElementKind.CLASS) {
|
||||
if ((<Class>target).base) {
|
||||
target = <Class>(<Class>target).base;
|
||||
@ -1836,11 +1836,11 @@ export class Program extends DiagnosticEmitter {
|
||||
case NodeKind.BINARY: { // TODO: string concatenation, mostly
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
case NodeKind.THIS: { // -> Class
|
||||
let classType = contextualFunction.instanceMethodOf;
|
||||
if (classType) {
|
||||
case NodeKind.THIS: { // -> Class / ClassPrototype
|
||||
let parent = contextualFunction.memberOf;
|
||||
if (parent) {
|
||||
if (!resolvedElement) resolvedElement = new ResolvedElement();
|
||||
return resolvedElement.set(classType);
|
||||
return resolvedElement.set(parent);
|
||||
}
|
||||
this.error(
|
||||
DiagnosticCode._this_cannot_be_referenced_in_current_location,
|
||||
@ -1849,10 +1849,10 @@ export class Program extends DiagnosticEmitter {
|
||||
return null;
|
||||
}
|
||||
case NodeKind.SUPER: { // -> Class
|
||||
let classType = contextualFunction.instanceMethodOf;
|
||||
if (classType && (classType = classType.base)) {
|
||||
let parent = contextualFunction.memberOf;
|
||||
if (parent && parent.kind == ElementKind.CLASS && (parent = (<Class>parent).base)) {
|
||||
if (!resolvedElement) resolvedElement = new ResolvedElement();
|
||||
return resolvedElement.set(classType);
|
||||
return resolvedElement.set(parent);
|
||||
}
|
||||
this.error(
|
||||
DiagnosticCode._super_can_only_be_referenced_in_a_derived_class,
|
||||
@ -2294,6 +2294,7 @@ export class FunctionPrototype extends Element {
|
||||
|
||||
var declaration = this.declaration;
|
||||
var isInstance = this.is(CommonFlags.INSTANCE);
|
||||
var classPrototype = this.classPrototype;
|
||||
|
||||
// inherit contextual type arguments as provided. might be be overridden.
|
||||
var inheritedTypeArguments = contextualTypeArguments;
|
||||
@ -2310,7 +2311,8 @@ export class FunctionPrototype extends Element {
|
||||
// override with class type arguments if a partially resolved instance method
|
||||
var classTypeArguments = this.classTypeArguments;
|
||||
if (classTypeArguments) { // set only if partially resolved
|
||||
let classDeclaration = (<ClassPrototype>assert(this.classPrototype)).declaration;
|
||||
assert(this.is(CommonFlags.INSTANCE));
|
||||
let classDeclaration = assert(classPrototype).declaration;
|
||||
let classTypeParameters = classDeclaration.typeParameters;
|
||||
let numClassTypeParameters = classTypeParameters.length;
|
||||
assert(numClassTypeParameters == classTypeArguments.length);
|
||||
@ -2344,12 +2346,9 @@ export class FunctionPrototype extends Element {
|
||||
var classInstance: Class | null = null;
|
||||
var thisType: Type | null = null;
|
||||
if (isInstance) {
|
||||
let classPrototype = assert(this.classPrototype);
|
||||
classInstance = classPrototype.resolve(classTypeArguments, contextualTypeArguments); // reports
|
||||
classInstance = assert(classPrototype).resolve(classTypeArguments, contextualTypeArguments); // reports
|
||||
if (!classInstance) return null;
|
||||
thisType = classInstance.type;
|
||||
} else {
|
||||
assert(!this.classPrototype);
|
||||
}
|
||||
|
||||
// resolve signature node
|
||||
@ -2386,7 +2385,7 @@ export class FunctionPrototype extends Element {
|
||||
|
||||
var internalName = this.internalName;
|
||||
if (instanceKey.length) internalName += "<" + instanceKey + ">";
|
||||
instance = new Function(this, internalName, signature, classInstance);
|
||||
instance = new Function(this, internalName, signature, classInstance ? classInstance : classPrototype);
|
||||
instance.contextualTypeArguments = contextualTypeArguments;
|
||||
this.instances.set(instanceKey, instance);
|
||||
return instance;
|
||||
@ -2394,6 +2393,7 @@ export class FunctionPrototype extends Element {
|
||||
|
||||
/** Resolves this prototype partially by applying the specified inherited class type arguments. */
|
||||
resolvePartial(classTypeArguments: Type[] | null): FunctionPrototype | null {
|
||||
assert(this.is(CommonFlags.INSTANCE));
|
||||
assert(this.classPrototype);
|
||||
if (classTypeArguments && classTypeArguments.length) {
|
||||
let partialPrototype = new FunctionPrototype(
|
||||
@ -2465,8 +2465,8 @@ export class Function extends Element {
|
||||
prototype: FunctionPrototype;
|
||||
/** Function signature. */
|
||||
signature: Signature;
|
||||
/** If an instance method, the concrete class it is a member of. */
|
||||
instanceMethodOf: Class | null;
|
||||
/** If a member of another namespace-like element, the concrete element it is a member of. */
|
||||
memberOf: Element | null;
|
||||
/** Map of locals by name. */
|
||||
locals: Map<string,Local> = new Map();
|
||||
/** List of additional non-parameter locals. */
|
||||
@ -2494,16 +2494,16 @@ export class Function extends Element {
|
||||
prototype: FunctionPrototype,
|
||||
internalName: string,
|
||||
signature: Signature,
|
||||
instanceMethodOf: Class | null = null
|
||||
memberOf: Element | null = null
|
||||
) {
|
||||
super(prototype.program, prototype.simpleName, internalName);
|
||||
this.prototype = prototype;
|
||||
this.signature = signature;
|
||||
this.instanceMethodOf = instanceMethodOf;
|
||||
this.memberOf = memberOf;
|
||||
this.flags = prototype.flags;
|
||||
if (!(prototype.is(CommonFlags.BUILTIN) || prototype.is(CommonFlags.DECLARE))) {
|
||||
let localIndex = 0;
|
||||
if (instanceMethodOf) {
|
||||
if (memberOf && memberOf.kind == ElementKind.CLASS) {
|
||||
assert(this.is(CommonFlags.INSTANCE));
|
||||
this.locals.set(
|
||||
"this",
|
||||
@ -2514,11 +2514,12 @@ export class Function extends Element {
|
||||
assert(signature.thisType)
|
||||
)
|
||||
);
|
||||
if (instanceMethodOf.contextualTypeArguments) {
|
||||
let contextualTypeArguments = (<Class>memberOf).contextualTypeArguments;
|
||||
if (contextualTypeArguments) {
|
||||
if (!this.contextualTypeArguments) {
|
||||
this.contextualTypeArguments = new Map();
|
||||
}
|
||||
for (let [inheritedName, inheritedType] of instanceMethodOf.contextualTypeArguments) {
|
||||
for (let [inheritedName, inheritedType] of contextualTypeArguments) {
|
||||
this.contextualTypeArguments.set(inheritedName, inheritedType);
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ declare const externalConstant: i32;
|
||||
externalFunction();
|
||||
assert(externalConstant == 1);
|
||||
|
||||
namespace my {
|
||||
export declare function externalFunction(): void;
|
||||
export declare const externalConstant: i32;
|
||||
declare namespace my {
|
||||
function externalFunction(): void;
|
||||
const externalConstant: i32;
|
||||
}
|
||||
|
||||
my.externalFunction();
|
||||
|
31
tests/compiler/static-this.optimized.wat
Normal file
31
tests/compiler/static-this.optimized.wat
Normal file
@ -0,0 +1,31 @@
|
||||
(module
|
||||
(type $i (func (result i32)))
|
||||
(type $iiiiv (func (param i32 i32 i32 i32)))
|
||||
(type $v (func))
|
||||
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
|
||||
(global $static-this/Foo.bar (mut i32) (i32.const 42))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\0e\00\00\00s\00t\00a\00t\00i\00c\00-\00t\00h\00i\00s\00.\00t\00s")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $static-this/Foo.getBar (; 1 ;) (type $i) (result i32)
|
||||
(get_global $static-this/Foo.bar)
|
||||
)
|
||||
(func $start (; 2 ;) (type $v)
|
||||
(if
|
||||
(i32.ne
|
||||
(call $static-this/Foo.getBar)
|
||||
(i32.const 42)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 8)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
8
tests/compiler/static-this.ts
Normal file
8
tests/compiler/static-this.ts
Normal file
@ -0,0 +1,8 @@
|
||||
class Foo {
|
||||
static bar: i32 = 42;
|
||||
static getBar(): i32 {
|
||||
return this.bar;
|
||||
}
|
||||
}
|
||||
|
||||
assert(Foo.getBar() == 42);
|
36
tests/compiler/static-this.untouched.wat
Normal file
36
tests/compiler/static-this.untouched.wat
Normal file
@ -0,0 +1,36 @@
|
||||
(module
|
||||
(type $i (func (result i32)))
|
||||
(type $iiiiv (func (param i32 i32 i32 i32)))
|
||||
(type $v (func))
|
||||
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
|
||||
(global $static-this/Foo.bar (mut i32) (i32.const 42))
|
||||
(global $HEAP_BASE i32 (i32.const 36))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\0e\00\00\00s\00t\00a\00t\00i\00c\00-\00t\00h\00i\00s\00.\00t\00s\00")
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $static-this/Foo.getBar (; 1 ;) (type $i) (result i32)
|
||||
(return
|
||||
(get_global $static-this/Foo.bar)
|
||||
)
|
||||
)
|
||||
(func $start (; 2 ;) (type $v)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(call $static-this/Foo.getBar)
|
||||
(i32.const 42)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 8)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
@ -2,10 +2,15 @@ declare namespace A {
|
||||
namespace B {
|
||||
export namespace C {
|
||||
var aVar: i32;
|
||||
const aConst: i32 = 0;
|
||||
function aFunc(): void {}
|
||||
const aConst: i32;
|
||||
const aConstInvalid: i32 = 0; // 1039: Initializers are not allowed in ambient contexts.
|
||||
function aFunc(): void;
|
||||
function aFuncInvalid(): void {} // 1183: An implementation cannot be declared in ambient contexts.
|
||||
enum AnEnum {}
|
||||
class AClass {}
|
||||
}
|
||||
namespace D {
|
||||
var aVar: i32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,17 @@ declare namespace A {
|
||||
namespace B {
|
||||
export namespace C {
|
||||
var aVar: i32;
|
||||
const aConst: i32 = 0;
|
||||
function aFunc(): void {}
|
||||
const aConst: i32;
|
||||
const aConstInvalid: i32 = 0;
|
||||
function aFunc(): void;
|
||||
function aFuncInvalid(): void {}
|
||||
enum AnEnum {}
|
||||
class AClass {}
|
||||
}
|
||||
namespace D {
|
||||
var aVar: i32;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ERROR 1039: "Initializers are not allowed in ambient contexts." in namespace.ts:6:31
|
||||
// ERROR 1183: "An implementation cannot be declared in ambient contexts." in namespace.ts:8:36
|
||||
|
Loading…
x
Reference in New Issue
Block a user