<commit_before>( function _Class_s_() {

'use strict';

const Self = _global_.wTools;
const _global = _global_;
const _ = _global_.wTools;

const _ObjectHasOwnProperty = Object.hasOwnProperty;
const _ObjectPropertyIsEumerable = Object.propertyIsEnumerable;
// let _nameFielded = _.nameFielded;

_.assert( _.object.isBasic( _.props ), 'wProto needs Tools/wtools/abase/l1/FieldMapper.s' );
// _.assert( _.routineIs( _nameFielded ), 'wProto needs Tools/wtools/l3/NameTools.s' );

// --
// mixin
// --

/**
 * Make mixin which could be mixed into prototype of another object.
 * @param {object} o - options.
 * @function _mixinDelcare
 * @namespace Tools
 * @module Tools/base/Proto
 */

function _mixinDelcare( o )
{

  _.assert( arguments.length === 1, 'Expects single argument' );
  _.assert( _.mapIs( o ) || _.routineIs( o ) );
  _.assert( _.routineIs( o.onMixinApply ) || o.onMixinApply === undefined || o.onMixinApply === null, 'Expects routine {-o.onMixinApply-}, but got', _.entity.strType( o ) );
  _.assert( _.strDefined( o.name ), 'mixin should have name' );
  _.assert( _.object.isBasic( o.extend ) || o.extend === undefined || o.extend === null );
  _.assert( _.object.isBasic( o.supplementOwn ) || o.supplementOwn === undefined || o.supplementOwn === null );
  _.assert( _.object.isBasic( o.supplement ) || o.supplement === undefined || o.supplement === null );
  _.assertOwnNoConstructor( o );
  _.routine.options_( _mixinDelcare, o );

  o.mixin = function mixin( dstClass )
  {
    let md = this.__mixin__;

    _.assert( arguments.length === 1, 'Expects single argument' );
    _.assert( _.routineIs( dstClass ), 'Expects constructor' );
    _.assert( dstClass === dstClass.prototype.constructor );
    _.map.assertHasOnly( this, [ _.KnownConstructorFields, { mixin : 'mixin', __mixin__ : '__mixin__' }, this.prototype.Statics || {} ] );

    if( md.onMixinApply )
    md.onMixinApply( md, dstClass );
    else
    _.mixinApply( md, dstClass.prototype );
    if( md.onMixinEnd )
    md.onMixinEnd( md, dstClass );

    return dstClass;
  }

  /* */

  if( !o.prototype )
  {
    let got = _.workpiece.prototypeAndConstructorOf( o );

    if( got.prototype )
    o.prototype = got.prototype;
    else
    o.prototype = Object.create( null );

    _.classExtend
    ({
      cls : got.cls || null,
      prototype : o.prototype,
      extend : o.extend || null,
      supplementOwn : o.supplementOwn || null,
      supplement : o.supplement || null,
    });

  }

  _.assert( !o.prototype.mixin, 'not tested' );
  o.prototype.mixin = o.mixin;
  if( o.prototype.constructor )
  {
    _.assert( !o.prototype.constructor.mixin || o.prototype.constructor.mixin === o.mixin, 'not tested' );
    o.prototype.constructor.mixin = o.mixin;
  }

  Object.freeze( o );
  return o;
}

_mixinDelcare.defaults =
{

  name : null,
  shortName : null,
  prototype : null,

  extend : null,
  supplementOwn : null,
  supplement : null,
  functors : null,

  onMixinApply : null,
  onMixinEnd : null,

}

//

function mixinDelcare( o )
{
  let result = Object.create( null );

  _.assert( o.mixin === undefined );

  let md = result.__mixin__ = _._mixinDelcare.apply( this, arguments );
  result.name = md.name;
  result.shortName = md.shortName;
  result.prototype = md.prototype;
  result.mixin = md.mixin;

  Object.freeze( result );
  return result;
}

mixinDelcare.defaults = Object.create( _mixinDelcare.defaults );

//

/**
 * Mixin methods and fields into prototype of another object.
 * @param {object} o - options.
 * @function mixinApply
 * @namespace Tools
 * @module Tools/base/Proto
 */

function mixinApply( mixinDescriptor, dstPrototype )
{

  _.assert( arguments.length === 2, 'Expects exactly two arguments' );
  _.assert( !_.primitiveIs( dstPrototype ), () => 'Second argument {-dstPrototype-} does not look like prototype, got ' + _.entity.strType( dstPrototype ) );
  _.assert( _.routineIs( mixinDescriptor.mixin ), 'First argument does not look like mixin descriptor' );
  _.assert( _.object.isBasic( mixinDescriptor ) );
  _.assert( Object.isFrozen( mixinDescriptor ), 'First argument does not look like mixin descriptor' );
  _.map.assertHasOnly( mixinDescriptor, _.MixinDescriptorFields );

  /* mixin into routine */

  if( !_.mapIs( dstPrototype ) )
  {
    _.assert( dstPrototype.constructor.prototype === dstPrototype, 'mixin :', 'Expects prototype with own constructor field' );
    _.assert( dstPrototype.constructor.name.length > 0 || dstPrototype.constructor._name.length > 0, 'mixin :', 'constructor should has name' );
    _.assert( _.routineIs( dstPrototype.init ) );
  }

  /* extend */

  _.assert( _.mapOnlyOwnKey( dstPrototype, 'constructor' ) );
  _.assert( dstPrototype.constructor.prototype === dstPrototype );
  _.classExtend
  ({
    cls : dstPrototype.constructor,
    extend : mixinDescriptor.extend,
    supplementOwn : mixinDescriptor.supplementOwn,
    supplement : mixinDescriptor.supplement,
    functors : mixinDescriptor.functors,
  });

  /* mixins map */

  if( !_ObjectHasOwnProperty.call( dstPrototype, '_mixinsMap' ) )
  {
    dstPrototype._mixinsMap = Object.create( dstPrototype._mixinsMap || null );
    _.props.conceal( dstPrototype, '_mixinsMap' );
  }

  _.assert
  (
    !dstPrototype._mixinsMap[ mixinDescriptor.name ],
      'Attempt to mixin same mixin ' + _.strQuote( mixinDescriptor.name ) +
      ' several times into ' + _.strQuote( dstPrototype.constructor.name )
  );

  dstPrototype._mixinsMap[ mixinDescriptor.name ] = 1;
}

//

function mixinHas( proto, mixin )
{
  if( _.constructorIs( proto ) )
  proto = _.workpiece.prototypeOf( proto );

  _.assert( _.workpiece.prototypeIsStandard( proto ) );
  _.assert( arguments.length === 2, 'Expects exactly two arguments' );

  if( _.strIs( mixin ) )
  {
    return proto._mixinsMap && proto._mixinsMap[ mixin ];
  }
  else
  {
    _.assert( _.routineIs( mixin.mixin ), 'Expects mixin, but got not mixin', _.entity.strType( mixin ) );
    _.assert( _.strDefined( mixin.name ), 'Expects mixin, but got not mixin', _.entity.strType( mixin ) );
    return proto._mixinsMap && proto._mixinsMap[ mixin.name ];
  }

}

// --
// class
// --

/**
* @typedef {object} wTools~prototypeOptions
* @property {routine} [o.cls=null] - constructor for which prototype is needed.
* @property {routine} [o.parent=null] - constructor of parent class.
* @property {object} [o.extend=null] - extend prototype by this map.
* @property {object} [o.supplement=null] - supplement prototype by this map.
* @property {object} [o.static=null] - static fields of a class.
* @property {boolean} [o.usingPrimitiveExtension=false] - extends class with primitive fields from relationship descriptors.
* @property {boolean} [o.usingOriginalPrototype=false] - makes prototype using original constructor prototype.
*/

/**
 * Make prototype for constructor repairing relationship : Composes, Aggregates, Associates, Medials, Restricts.
 * Execute optional extend / supplement if such o present.
 * @param {wTools~prototypeOptions} o - options {@link wTools~prototypeOptions}.
 * @returns {object} Returns constructor's prototype based on( o.parent ) prototype and complemented by fields, static and non-static methods.
 *
 * @example
 *  const Parent = function Alpha(){ };<commit_msg>mixinHas: make routine return boolean<commit_after>( function _Class_s_() {

'use strict';

const Self = _global_.wTools;
const _global = _global_;
const _ = _global_.wTools;

const _ObjectHasOwnProperty = Object.hasOwnProperty;
const _ObjectPropertyIsEumerable = Object.propertyIsEnumerable;
// let _nameFielded = _.nameFielded;

_.assert( _.object.isBasic( _.props ), 'wProto needs Tools/wtools/abase/l1/FieldMapper.s' );
// _.assert( _.routineIs( _nameFielded ), 'wProto needs Tools/wtools/l3/NameTools.s' );

// --
// mixin
// --

/**
 * Make mixin which could be mixed into prototype of another object.
 * @param {object} o - options.
 * @function _mixinDelcare
 * @namespace Tools
 * @module Tools/base/Proto
 */

function _mixinDelcare( o )
{

  _.assert( arguments.length === 1, 'Expects single argument' );
  _.assert( _.mapIs( o ) || _.routineIs( o ) );
  _.assert( _.routineIs( o.onMixinApply ) || o.onMixinApply === undefined || o.onMixinApply === null, 'Expects routine {-o.onMixinApply-}, but got', _.entity.strType( o ) );
  _.assert( _.strDefined( o.name ), 'mixin should have name' );
  _.assert( _.object.isBasic( o.extend ) || o.extend === undefined || o.extend === null );
  _.assert( _.object.isBasic( o.supplementOwn ) || o.supplementOwn === undefined || o.supplementOwn === null );
  _.assert( _.object.isBasic( o.supplement ) || o.supplement === undefined || o.supplement === null );
  _.assertOwnNoConstructor( o );
  _.routine.options_( _mixinDelcare, o );

  o.mixin = function mixin( dstClass )
  {
    let md = this.__mixin__;

    _.assert( arguments.length === 1, 'Expects single argument' );
    _.assert( _.routineIs( dstClass ), 'Expects constructor' );
    _.assert( dstClass === dstClass.prototype.constructor );
    _.map.assertHasOnly( this, [ _.KnownConstructorFields, { mixin : 'mixin', __mixin__ : '__mixin__' }, this.prototype.Statics || {} ] );

    if( md.onMixinApply )
    md.onMixinApply( md, dstClass );
    else
    _.mixinApply( md, dstClass.prototype );
    if( md.onMixinEnd )
    md.onMixinEnd( md, dstClass );

    return dstClass;
  }

  /* */

  if( !o.prototype )
  {
    let got = _.workpiece.prototypeAndConstructorOf( o );

    if( got.prototype )
    o.prototype = got.prototype;
    else
    o.prototype = Object.create( null );

    _.classExtend
    ({
      cls : got.cls || null,
      prototype : o.prototype,
      extend : o.extend || null,
      supplementOwn : o.supplementOwn || null,
      supplement : o.supplement || null,
    });

  }

  _.assert( !o.prototype.mixin, 'not tested' );
  o.prototype.mixin = o.mixin;
  if( o.prototype.constructor )
  {
    _.assert( !o.prototype.constructor.mixin || o.prototype.constructor.mixin === o.mixin, 'not tested' );
    o.prototype.constructor.mixin = o.mixin;
  }

  Object.freeze( o );
  return o;
}

_mixinDelcare.defaults =
{

  name : null,
  shortName : null,
  prototype : null,

  extend : null,
  supplementOwn : null,
  supplement : null,
  functors : null,

  onMixinApply : null,
  onMixinEnd : null,

}

//

function mixinDelcare( o )
{
  let result = Object.create( null );

  _.assert( o.mixin === undefined );

  let md = result.__mixin__ = _._mixinDelcare.apply( this, arguments );
  result.name = md.name;
  result.shortName = md.shortName;
  result.prototype = md.prototype;
  result.mixin = md.mixin;

  Object.freeze( result );
  return result;
}

mixinDelcare.defaults = Object.create( _mixinDelcare.defaults );

//

/**
 * Mixin methods and fields into prototype of another object.
 * @param {object} o - options.
 * @function mixinApply
 * @namespace Tools
 * @module Tools/base/Proto
 */

function mixinApply( mixinDescriptor, dstPrototype )
{

  _.assert( arguments.length === 2, 'Expects exactly two arguments' );
  _.assert( !_.primitiveIs( dstPrototype ), () => 'Second argument {-dstPrototype-} does not look like prototype, got ' + _.entity.strType( dstPrototype ) );
  _.assert( _.routineIs( mixinDescriptor.mixin ), 'First argument does not look like mixin descriptor' );
  _.assert( _.object.isBasic( mixinDescriptor ) );
  _.assert( Object.isFrozen( mixinDescriptor ), 'First argument does not look like mixin descriptor' );
  _.map.assertHasOnly( mixinDescriptor, _.MixinDescriptorFields );

  /* mixin into routine */

  if( !_.mapIs( dstPrototype ) )
  {
    _.assert( dstPrototype.constructor.prototype === dstPrototype, 'mixin :', 'Expects prototype with own constructor field' );
    _.assert( dstPrototype.constructor.name.length > 0 || dstPrototype.constructor._name.length > 0, 'mixin :', 'constructor should has name' );
    _.assert( _.routineIs( dstPrototype.init ) );
  }

  /* extend */

  _.assert( _.mapOnlyOwnKey( dstPrototype, 'constructor' ) );
  _.assert( dstPrototype.constructor.prototype === dstPrototype );
  _.classExtend
  ({
    cls : dstPrototype.constructor,
    extend : mixinDescriptor.extend,
    supplementOwn : mixinDescriptor.supplementOwn,
    supplement : mixinDescriptor.supplement,
    functors : mixinDescriptor.functors,
  });

  /* mixins map */

  if( !_ObjectHasOwnProperty.call( dstPrototype, '_mixinsMap' ) )
  {
    dstPrototype._mixinsMap = Object.create( dstPrototype._mixinsMap || null );
    _.props.conceal( dstPrototype, '_mixinsMap' );
  }

  _.assert
  (
    !dstPrototype._mixinsMap[ mixinDescriptor.name ],
      'Attempt to mixin same mixin ' + _.strQuote( mixinDescriptor.name ) +
      ' several times into ' + _.strQuote( dstPrototype.constructor.name )
  );

  dstPrototype._mixinsMap[ mixinDescriptor.name ] = 1;
}

//

function mixinHas( proto, mixin )
{
  if( _.constructorIs( proto ) )
  proto = _.workpiece.prototypeOf( proto );

  _.assert( _.workpiece.prototypeIsStandard( proto ) );
  _.assert( arguments.length === 2, 'Expects exactly two arguments' );

  let result;

  if( _.strIs( mixin ) )
  {
    result = proto._mixinsMap && proto._mixinsMap[ mixin ];
  }
  else
  {
    _.assert( _.routineIs( mixin.mixin ), 'Expects mixin, but got not mixin', _.entity.strType( mixin ) );
    _.assert( _.strDefined( mixin.name ), 'Expects mixin, but got not mixin', _.entity.strType( mixin ) );
    result = proto._mixinsMap && proto._mixinsMap[ mixin.name ];
  }

  return !!result;
}

// --
// class
// --

/**
* @typedef {object} wTools~prototypeOptions
* @property {routine} [o.cls=null] - constructor for which prototype is needed.
* @property {routine} [o.parent=null] - constructor of parent class.
* @property {object} [o.extend=null] - extend prototype by this map.
* @property {object} [o.supplement=null] - supplement prototype by this map.
* @property {object} [o.static=null] - static fields of a class.
* @property {boolean} [o.usingPrimitiveExtension=false] - extends class with primitive fields from relationship descriptors.
* @property {boolean} [o.usingOriginalPrototype=false] - makes prototype using original constructor prototype.
*/

/**
 * Make prototype for constructor repairing relationship : Composes, Aggregates, Associates, Medials, Restricts.
 * Execute optional extend / supplement if such o present.
 * @param {wTools~prototypeOptions} o - options {@link wTools~prototypeOptions}.
 * @returns {object} Returns constructor's prototype based on( o.parent ) prototype and complemented by fields, static and non-static methods.
 *
 * @example
 *  const Parent = function Alpha(){ };
{'fraction_non_alphanumeric': 0.13877467105263158, 'fraction_numerical': 0.0012335526315789473, 'mean_word_length': 3.5861093651791327, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2218562', 'n_tokens_mistral': 4652, 'n_tokens_neox': 4613, 'n_words': 1162}