Skip to content
Snippets Groups Projects
Commit ef0e6dfb authored by Leo Balter's avatar Leo Balter Committed by Rick Waldron
Browse files

new template and cases for private methods

parent 41844c7c
No related branches found
No related tags found
No related merge requests found
// Copyright (C) 2018 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
path: language/statements/class/private-methods/
name: private method definitions in a class declaration
features: [class, class-methods-private]
info: |
ClassElement :
MethodDefinition
...
;
ClassElementName :
PropertyName
PrivateName
PrivateName ::
# IdentifierName
MethodDefinition :
ClassElementName ( UniqueFormalParameters ) { FunctionBody }
GeneratorMethod
AsyncMethod
AsyncGeneratorMethod
get ClassElementName () { FunctionBody }
set ClassElementName ( PropertySetParameterList ) { FunctionBody }
GeneratorMethod :
* ClassElementName ( UniqueFormalParameters ){GeneratorBody}
AsyncMethod :
async [no LineTerminator here] ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
AsyncGeneratorMethod :
async [no LineTerminator here]* ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
---
InitializeClassElements ( F, proto )
...
5. For each item element in order from elements,
a. Assert: If element.[[Placement]] is "prototype" or "static", then element.[[Key]] is not a Private Name.
b. If element.[[Kind]] is "method" and element.[[Placement]] is "static" or "prototype",
i. Let receiver be F if element.[[Placement]] is "static", else let receiver be proto.
ii. Perform ? DefineClassElement(receiver, element).
InitializeInstanceElements ( O, constructor )
...
3. Let elements be the value of F's [[Elements]] internal slot.
4. For each item element in order from elements,
a. If element.[[Placement]] is "own" and element.[[Kind]] is "method",
i. Perform ? DefineClassElement(O, element).
DefineClassElement (receiver, element)
...
6. If key is a Private Name,
a. Perform ? PrivateFieldDefine(receiver, key, descriptor).
PrivateFieldDefine (P, O, desc)
...
6. Append { [[PrivateName]]: P, [[PrivateFieldDescriptor]]: desc } to O.[[PrivateFieldDescriptors]].
esid: prod-MethodDefinition
---*/
/*** template notes
* method should always be #m
* the template provides c.ref() for external reference
*/
function hasOwnProperty(obj, name) {
return Object.prototype.hasOwnProperty.call(obj, name);
}
class C {
/*{ element }*/
get ref() { return this.#m; }
constructor() {
assert.sameValue(
hasOwnProperty(this, '#m'), false,
'private methods are defined in an special internal slot and cannot be found as own properties'
);
assert.sameValue(typeof this.#m, 'function');
assert.sameValue(this.ref(), this.#m, 'returns the same value');
/*{ constructor }*/
}
}
var c = new C();
var other = new C();
assert.sameValue(
hasOwnProperty(C.prototype, '#m'), false,
'method is not defined in the prototype'
);
assert.sameValue(
hasOwnProperty(C, '#m'), false,
'method is not defined in the contructor'
);
assert.sameValue(
hasOwnProperty(c, '#m'), false,
'method cannot be seen outside of the class'
);
/***
* MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
*
* 1. Let methodDef be DefineMethod of MethodDefinition with argument homeObject.
* ...
*/
assert.sameValue(c.ref, other.ref, 'The method is defined once, and reused on every new instance');
/*{ assertions }*/
// Copyright (C) 2018 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
path: language/expressions/class/private-methods/
name: private method definitions in a class expression
info: |
ClassElement :
MethodDefinition
...
;
ClassElementName :
PropertyName
PrivateName
PrivateName ::
# IdentifierName
MethodDefinition :
ClassElementName ( UniqueFormalParameters ) { FunctionBody }
GeneratorMethod
AsyncMethod
AsyncGeneratorMethod
get ClassElementName () { FunctionBody }
set ClassElementName ( PropertySetParameterList ) { FunctionBody }
GeneratorMethod :
* ClassElementName ( UniqueFormalParameters ){GeneratorBody}
AsyncMethod :
async [no LineTerminator here] ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
AsyncGeneratorMethod :
async [no LineTerminator here]* ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
---
InitializeClassElements ( F, proto )
...
5. For each item element in order from elements,
a. Assert: If element.[[Placement]] is "prototype" or "static", then element.[[Key]] is not a Private Name.
b. If element.[[Kind]] is "method" and element.[[Placement]] is "static" or "prototype",
i. Let receiver be F if element.[[Placement]] is "static", else let receiver be proto.
ii. Perform ? DefineClassElement(receiver, element).
InitializeInstanceElements ( O, constructor )
...
3. Let elements be the value of F's [[Elements]] internal slot.
4. For each item element in order from elements,
a. If element.[[Placement]] is "own" and element.[[Kind]] is "method",
i. Perform ? DefineClassElement(O, element).
DefineClassElement (receiver, element)
...
6. If key is a Private Name,
a. Perform ? PrivateFieldDefine(receiver, key, descriptor).
PrivateFieldDefine (P, O, desc)
...
6. Append { [[PrivateName]]: P, [[PrivateFieldDescriptor]]: desc } to O.[[PrivateFieldDescriptors]].
esid: prod-MethodDefinition
---*/
/***
* template notes:
* 1. method should always be #m
* 2. the template provides c.ref/other.ref for external reference
*/
function hasOwnProperty(obj, name) {
return Object.prototype.hasOwnProperty.call(obj, name);
}
var C = class {
/*{ element }*/
get ref() { return this.#m; }
constructor() {
assert.sameValue(
hasOwnProperty(this, '#m'), false,
'private methods are defined in an special internal slot and cannot be found as own properties'
);
assert.sameValue(typeof this.#m, 'function');
assert.sameValue(this.ref(), this.#m, 'returns the same value');
/*{ constructor }*/
}
}
var c = new C();
var other = new C();
assert.sameValue(
hasOwnProperty(C.prototype, '#m'), false,
'method is not defined in the prototype'
);
assert.sameValue(
hasOwnProperty(C, '#m'), false,
'method is not defined in the contructor'
);
assert.sameValue(
hasOwnProperty(c, '#m'), false,
'method cannot be seen outside of the class'
);
/***
* MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
*
* 1. Let methodDef be DefineMethod of MethodDefinition with argument homeObject.
* ...
*/
assert.sameValue(c.ref, other.ref, 'The method is defined once, and reused on every new instance');
/*{ assertions }*/
// Copyright (C) 2018 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
desc: Private Async Generator
template: private-methods
features: [async-iteration]
flags: [async]
---*/
//- setup
var ctorPromise;
//- element
async * #m() { return 42; }
//- constructor
var ctorIter = this.#m();
var p = ctorIter.next();
ctorPromise = p.then(({ value, done }) => {
assert.sameValue(value, 42, 'return from generator method, inside ctor');
assert.sameValue(done, true, 'iterator is done, inside ctor');
}, $DONE);
assert.sameValue(this.#m.name, '#m', 'function name inside constructor');
//- assertions
assert.sameValue(c.ref.name, '#m', 'function name is preserved external reference');
ctorPromise.then(() => {
var iter = c.ref();
return iter.next().then(({ value, done }) => {
assert.sameValue(value, 42, 'return from generator method');
assert.sameValue(done, true, 'iterator is done');
});
}, $DONE).then($DONE, $DONE);
// Copyright (C) 2018 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
desc: Private Async Method
template: private-methods
features: [async-functions]
flags: [async]
---*/
//- setup
var ctorPromise;
//- element
async #m() { return 42; }
//- constructor
assert.sameValue(this.#m.name, '#m', 'function name inside constructor');
ctorPromise = this.#m().then(value => {
assert.sameValue(this.#m(), 42, 'already defined in the ctor');
}, $DONE);
//- assertions
assert.sameValue(c.ref.name, '#m', 'function name is preserved external reference');
ctorPromise.then(() => {
return c.ref().then(value => {
assert.sameValue(value, 42, 'function return');
});
}, $DONE).then($DONE, $DONE);
// Copyright (C) 2018 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
desc: Private Generator
template: private-methods
features: [generators]
---*/
//- element
* #m() { return 42; }
//- constructor
var res = this.#m().next();
assert.sameValue(res.value, 42, 'return from generator method, inside ctor');
assert.sameValue(res.done, true, 'iterator is done, inside ctor');
assert.sameValue(this.#m.name, '#m', 'function name inside constructor');
//- assertions
var res = c.ref().next();
assert.sameValue(res.value, 42, 'return from generator method');
assert.sameValue(res.done, true, 'iterator is done');
assert.sameValue(c.ref.name, '#m', 'function name is preserved external reference');
// Copyright (C) 2018 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
desc: Private Method
template: private-methods
---*/
//- element
#m() { return 42; }
//- constructor
assert.sameValue(this.#m(), 42, 'already defined in the ctor');
assert.sameValue(this.#m.name, '#m', 'function name inside constructor');
//- assertions
assert.sameValue(c.ref(), 42, 'function return');
assert.sameValue(c.ref.name, '#m', 'function name is preserved external reference');
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment