<commit_before>import { OWNER } from 'ember-utils';
import {
  PrimitiveReference,
  ComponentDefinition
} from '@glimmer/runtime';
import {
  AttributeBinding,
  ClassNameBinding,
  IsVisibleBinding
} from '../utils/bindings';
import {
  ROOT_REF,
  DIRTY_TAG,
  IS_DISPATCHING_ATTRS,
  HAS_BLOCK,
  BOUNDS
} from '../component';
import {
  get,
  _instrumentStart
} from 'ember-metal';
import {
  assert
} from 'ember-debug';
import { DEBUG } from 'ember-env-flags';
import {
  dispatchLifeCycleHook,
  setViewElement
} from 'ember-views';
import { privatize as P } from 'container';
import AbstractManager from './abstract-manager';
import { processComponentArgs } from '../utils/process-args';

const DEFAULT_LAYOUT = P`template:components/-default`;

function processComponentInitializationAssertions(component, props) {
  assert(`classNameBindings must not have spaces in them: ${component.toString()}`, (() => {
    let { classNameBindings } = component;
    for (let i = 0; i < classNameBindings.length; i++) {
      let binding = classNameBindings[i];
      if (binding.split(' ').length > 1) {
        return false;
      }
    }
    return true;
  })());

  assert('You cannot use `classNameBindings` on a tag-less component: ' + component.toString(), (() => {
    let { classNameBindings, tagName } = component;
    return tagName !== '' || !classNameBindings || classNameBindings.length === 0;
  })());

  assert('You cannot use `elementId` on a tag-less component: ' + component.toString(), (() => {
    let { elementId, tagName } = component;
    return tagName !== '' || props.id === elementId || (!elementId && elementId !== '');
  })());

  assert('You cannot use `attributeBindings` on a tag-less component: ' + component.toString(), (() => {
    let { attributeBindings, tagName } = component;
    return tagName !== '' || !attributeBindings || attributeBindings.length === 0;
  })());
}

export function validatePositionalParameters(named, positional, positionalParamsDefinition) {
  if (DEBUG) {
    if (!named || !positional || !positional.length) {
      return;
    }

    let paramType = typeof positionalParamsDefinition;

    if (paramType === 'string') {
      assert(`You cannot specify positional parameters and the hash argument \`${positionalParamsDefinition}\`.`, !named.has(positionalParamsDefinition));
    } else {
      if (positional.length < positionalParamsDefinition.length) {
        positionalParamsDefinition = positionalParamsDefinition.slice(0, positional.length);
      }

      for (let i = 0; i < positionalParamsDefinition.length; i++) {
        let name = positionalParamsDefinition[i];

        assert(
          `You cannot specify both a positional param (at position ${i}) and the hash argument \`${name}\`.`,
          !named.has(name)
        );
      }
    }
  }
}

function aliasIdToElementId(args, props) {
  if (args.named.has('id')) {
    assert(`You cannot invoke a component with both 'id' and 'elementId' at the same time.`, !args.named.has('elementId'));
    props.elementId = props.id;
  }
}

// We must traverse the attributeBindings in reverse keeping track of
// what has already been applied. This is essentially refining the concated
// properties applying right to left.
function applyAttributeBindings(element, attributeBindings, component, operations) {
  let seen = [];
  let i = attributeBindings.length - 1;

  while (i !== -1) {
    let binding = attributeBindings[i];
    let parsed = AttributeBinding.parse(binding);
    let attribute = parsed[1];

    if (seen.indexOf(attribute) === -1) {
      seen.push(attribute);
      AttributeBinding.install(element, component, parsed, operations);
    }

    i--;
  }

  if (seen.indexOf('id') === -1) {
    operations.addStaticAttribute(element, 'id', component.elementId);
  }

  if (seen.indexOf('style') === -1) {
    IsVisibleBinding.install(element, component, operations);
  }
}

function NOOP() {}

class ComponentStateBucket {
  constructor(environment, component, args, finalizer) {
    this.environment = environment;
    this.component = component;
    this.classRef = null;
    this.args = args;
    this.argsRevision = args.tag.value();
    this.finalizer = finalizer;
  }

  destroy() {
    let { component, environment } = this;

    if (environment.isInteractive) {
      component.trigger('willDestroyElement');
      component.trigger('willClearRender');
    }

    environment.destroyedComponents.push(component);
  }

  finalize() {
    let { finalizer } = this;
    finalizer();
    this.finalizer = NOOP;
  }
}

function initialRenderInstrumentDetails(component) {
  return component.instrumentDetails({ initialRender: true });
}

function rerenderInstrumentDetails(component) {
  return component.instrumentDetails({ initialRender: false });
}

class CurlyComponentManager extends AbstractManager {
  prepareArgs(definition, args) {
    return null;
  }

  create(environment, definition, args, dynamicScope, callerSelfRef, hasBlock) {
    if (DEBUG) {
      this._pushToDebugStack(`component:${definition.name}`, environment)
    }

    let parentView = dynamicScope.view;

    let factory = definition.ComponentClass;

    let capturedArgs = args.named.capture();
    let props = processComponentArgs(capturedArgs);

    aliasIdToElementId(args, props);

    props.parentView = parentView;
    props[HAS_BLOCK] = hasBlock;

    props._targetObject = callerSelfRef.value();

    let component = factory.create(props);

    let finalizer = _instrumentStart('render.component', initialRenderInstrumentDetails, component);

    dynamicScope.view = component;
<commit_msg>Initial pass at supporting "rest arg" style positionals.<commit_after>import { OWNER } from 'ember-utils';
import {
  PrimitiveReference,
  ComponentDefinition
} from '@glimmer/runtime';
import {
  AttributeBinding,
  ClassNameBinding,
  IsVisibleBinding
} from '../utils/bindings';
import {
  ROOT_REF,
  DIRTY_TAG,
  IS_DISPATCHING_ATTRS,
  HAS_BLOCK,
  BOUNDS
} from '../component';
import {
  get,
  _instrumentStart
} from 'ember-metal';
import {
  assert
} from 'ember-debug';
import { DEBUG } from 'ember-env-flags';
import {
  dispatchLifeCycleHook,
  setViewElement
} from 'ember-views';
import { privatize as P } from 'container';
import AbstractManager from './abstract-manager';
import { processComponentArgs } from '../utils/process-args';

const DEFAULT_LAYOUT = P`template:components/-default`;

function processComponentInitializationAssertions(component, props) {
  assert(`classNameBindings must not have spaces in them: ${component.toString()}`, (() => {
    let { classNameBindings } = component;
    for (let i = 0; i < classNameBindings.length; i++) {
      let binding = classNameBindings[i];
      if (binding.split(' ').length > 1) {
        return false;
      }
    }
    return true;
  })());

  assert('You cannot use `classNameBindings` on a tag-less component: ' + component.toString(), (() => {
    let { classNameBindings, tagName } = component;
    return tagName !== '' || !classNameBindings || classNameBindings.length === 0;
  })());

  assert('You cannot use `elementId` on a tag-less component: ' + component.toString(), (() => {
    let { elementId, tagName } = component;
    return tagName !== '' || props.id === elementId || (!elementId && elementId !== '');
  })());

  assert('You cannot use `attributeBindings` on a tag-less component: ' + component.toString(), (() => {
    let { attributeBindings, tagName } = component;
    return tagName !== '' || !attributeBindings || attributeBindings.length === 0;
  })());
}

export function validatePositionalParameters(named, positional, positionalParamsDefinition) {
  if (DEBUG) {
    if (!named || !positional || !positional.length) {
      return;
    }

    let paramType = typeof positionalParamsDefinition;

    if (paramType === 'string') {
      assert(`You cannot specify positional parameters and the hash argument \`${positionalParamsDefinition}\`.`, !named.has(positionalParamsDefinition));
    } else {
      if (positional.length < positionalParamsDefinition.length) {
        positionalParamsDefinition = positionalParamsDefinition.slice(0, positional.length);
      }

      for (let i = 0; i < positionalParamsDefinition.length; i++) {
        let name = positionalParamsDefinition[i];

        assert(
          `You cannot specify both a positional param (at position ${i}) and the hash argument \`${name}\`.`,
          !named.has(name)
        );
      }
    }
  }
}

function aliasIdToElementId(args, props) {
  if (args.named.has('id')) {
    assert(`You cannot invoke a component with both 'id' and 'elementId' at the same time.`, !args.named.has('elementId'));
    props.elementId = props.id;
  }
}

// We must traverse the attributeBindings in reverse keeping track of
// what has already been applied. This is essentially refining the concated
// properties applying right to left.
function applyAttributeBindings(element, attributeBindings, component, operations) {
  let seen = [];
  let i = attributeBindings.length - 1;

  while (i !== -1) {
    let binding = attributeBindings[i];
    let parsed = AttributeBinding.parse(binding);
    let attribute = parsed[1];

    if (seen.indexOf(attribute) === -1) {
      seen.push(attribute);
      AttributeBinding.install(element, component, parsed, operations);
    }

    i--;
  }

  if (seen.indexOf('id') === -1) {
    operations.addStaticAttribute(element, 'id', component.elementId);
  }

  if (seen.indexOf('style') === -1) {
    IsVisibleBinding.install(element, component, operations);
  }
}

function NOOP() {}

class ComponentStateBucket {
  constructor(environment, component, args, finalizer) {
    this.environment = environment;
    this.component = component;
    this.classRef = null;
    this.args = args;
    this.argsRevision = args.tag.value();
    this.finalizer = finalizer;
  }

  destroy() {
    let { component, environment } = this;

    if (environment.isInteractive) {
      component.trigger('willDestroyElement');
      component.trigger('willClearRender');
    }

    environment.destroyedComponents.push(component);
  }

  finalize() {
    let { finalizer } = this;
    finalizer();
    this.finalizer = NOOP;
  }
}

function initialRenderInstrumentDetails(component) {
  return component.instrumentDetails({ initialRender: true });
}

function rerenderInstrumentDetails(component) {
  return component.instrumentDetails({ initialRender: false });
}

class CurlyComponentManager extends AbstractManager {
  prepareArgs(definition, args) {
    let componentPositionalParamsDefinition = definition.ComponentClass.class.positionalParams;

    if (DEBUG && componentPositionalParamsDefinition) {
      validatePositionalParameters(args.named, args.positional.values, componentPositionalParamsDefinition);
    }

    // merging positional params should be PAYGO
    if (args.positional.length === 0 || !componentPositionalParamsDefinition) {
      return null;
    }

    let capturedArgs = args.capture();
    let positional = capturedArgs.positional;
    let named = capturedArgs.named.map || {};

    if (typeof componentPositionalParamsDefinition === 'string') {
      named[componentPositionalParamsDefinition] = positional;
      positional = [];
    } else {
      //named = mergePositionalParams(named, positionalValues, positionalParamsDefinition);
    }

    return { positional, named };
  }

  create(environment, definition, args, dynamicScope, callerSelfRef, hasBlock) {
    if (DEBUG) {
      this._pushToDebugStack(`component:${definition.name}`, environment)
    }

    let parentView = dynamicScope.view;

    let factory = definition.ComponentClass;

    let capturedArgs = args.named.capture();
    let props = processComponentArgs(capturedArgs);

    aliasIdToElementId(args, props);

    props.parentView = parentView;
    props[HAS_BLOCK] = hasBlock;

    props._targetObject = callerSelfRef.value();

    let component = factory.create(props);

    let finalizer = _instrumentStart('render.component', initialRenderInstrumentDetails, component);

    dynamicScope.view = component;

{'fraction_non_alphanumeric': 0.12750680861599406, 'fraction_numerical': 0.002063216967896344, 'mean_word_length': 3.7973079968329375, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, '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': '5623598', 'n_tokens_mistral': 3466, 'n_tokens_neox': 3348, 'n_words': 858}