mirror of
https://github.com/flynx/object.js.git
synced 2025-10-28 10:10:06 +00:00
added ASIS(..) wrapper to help prevent values returned by .__new__(..) from being intergrated into the current object prototype chain enabling constructors to return non-instance values.
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
b77550f97f
commit
077eda6fb3
13
README.md
13
README.md
@ -130,6 +130,7 @@ class B extends A {
|
||||
- [`<object>.__call__(..)`](#object__call__)
|
||||
- [Components](#components)
|
||||
- [`STOP` / `STOP(..)`](#stop--stop)
|
||||
- [`ASIS(..)`](#asis)
|
||||
- [`Constructor(..)` / `C(..)`](#constructor--c)
|
||||
- [`create(..)` / `Constructor.create(..)`](#create--constructorcreate)
|
||||
- [`sources(..)` / `Constructor.sources(..)`](#sources--constructorsources)
|
||||
@ -508,6 +509,13 @@ no instance exists yet.
|
||||
`<context>` is the _outer_ context of the call, i.e. the object from which
|
||||
`<constructor>` was referenced before it was called.
|
||||
|
||||
Any value returned by `.__new__(..)` will be integrated into the prototype
|
||||
chain of `<object>`, if this is not desired then wrap it in
|
||||
[`object.ASIS(..)`](#asis) before returning, but note that this will
|
||||
not prevent `<object>.__init__(..)` from being called. The `ASIS(..)`-wrapped
|
||||
value will be unwrapped before being returned by the constructor.
|
||||
|
||||
|
||||
For more info see:
|
||||
- [Low level constructor](#low-level-constructor),
|
||||
- [Inheriting from native constructor objects](#inheriting-from-native-constructor-objects)
|
||||
@ -564,6 +572,11 @@ to stop the search before it reaches the top of
|
||||
the prototype chain.
|
||||
|
||||
|
||||
### `ASIS(..)`
|
||||
|
||||
Can be used in [`.__new__(..)`](#object__new__) to wrap the returned object to
|
||||
prevent changing it's prototype by [`RawInstance()`](#rawinstance).
|
||||
|
||||
|
||||
### `Constructor(..)` / `C(..)`
|
||||
|
||||
|
||||
20
object.js
20
object.js
@ -241,6 +241,15 @@ function(obj){
|
||||
//---------------------------------------------------------------------
|
||||
// Helper objects/constructors...
|
||||
|
||||
var ASIS =
|
||||
module.ASIS =
|
||||
function ASIS(value){
|
||||
return {
|
||||
__proto__: ASIS.prototype,
|
||||
value,
|
||||
} }
|
||||
|
||||
|
||||
BOOTSTRAP(function(){
|
||||
|
||||
// Error with some JS quirks fixed...
|
||||
@ -647,6 +656,10 @@ function(context, constructor, ...args){
|
||||
// default object base...
|
||||
: Reflect.construct(Object, [], constructor)
|
||||
|
||||
// return wrapped object as-is...
|
||||
if(obj instanceof module.ASIS){
|
||||
return obj.value }
|
||||
|
||||
// link to prototype chain, if not done already...
|
||||
obj.__proto__ !== constructor.prototype
|
||||
&& (obj.__proto__ = constructor.prototype)
|
||||
@ -917,8 +930,11 @@ function Constructor(name, a, b, c){
|
||||
_constructor.__rawinstance__(this, ...arguments)
|
||||
: RawInstance(this, _constructor, ...arguments)
|
||||
// initialize...
|
||||
obj.__init__ instanceof Function
|
||||
&& obj.__init__(...arguments)
|
||||
// NOTE: we are using _constructor.prototype.__init__ here instead
|
||||
// of obj.__init__ as at this point object may be of a different
|
||||
// type (see RawInstance + ASIS)...
|
||||
_constructor.prototype.__init__ instanceof Function
|
||||
&& _constructor.prototype.__init__.call(obj, ...arguments)
|
||||
return obj }
|
||||
// rename the consructor...
|
||||
// NOTE: we are not using:
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ig-object",
|
||||
"version": "6.2.0",
|
||||
"version": "6.2.1",
|
||||
"description": "",
|
||||
"main": "object.js",
|
||||
"scripts": {
|
||||
|
||||
30
test.js
30
test.js
@ -205,7 +205,7 @@ var setups = test.Setups({
|
||||
|
||||
// initialization...
|
||||
init: function(assert){
|
||||
var A, B, C
|
||||
var A, B, C, D
|
||||
return {
|
||||
// init...
|
||||
A: A = assert(object.C('A', {
|
||||
@ -225,6 +225,7 @@ var setups = test.Setups({
|
||||
return o
|
||||
},
|
||||
test_new: function(){
|
||||
assert(this instanceof B, 'instanceof correct')
|
||||
assert(this.new_has_run, '.__new__() run') },
|
||||
}), 'basic .__new__(..)'),
|
||||
// new + init...
|
||||
@ -622,6 +623,33 @@ var tests = test.Tests({
|
||||
|
||||
|
||||
var cases = test.Cases({
|
||||
'as-is-new': function(assert){
|
||||
var A = object.C('A', {
|
||||
__init__: function(){
|
||||
this.init_A_did_run = true },
|
||||
})
|
||||
var B = object.C('B', {
|
||||
__new__: function(){
|
||||
return object.ASIS(A()) },
|
||||
})
|
||||
|
||||
var b = B()
|
||||
|
||||
assert(b instanceof A, 'not instance of A')
|
||||
assert(!(b instanceof B), 'not instance of B')
|
||||
|
||||
var C = object.C('C', {
|
||||
__new__: function(){
|
||||
return object.ASIS(A()) },
|
||||
__init__: function(){
|
||||
this.init_C_did_run = true },
|
||||
})
|
||||
|
||||
var c = C()
|
||||
|
||||
assert(c.init_A_did_run, 'base .__init__() ran')
|
||||
assert(c.init_C_did_run, 'constructor .__init__() ran')
|
||||
},
|
||||
'edge-cases': function(assert){
|
||||
// bad names...
|
||||
assert.error('Constructor(..): malformed name',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user