<commit_before>/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

import symbolGenerator from 'core/symbol';
import * as c from 'core/component/const';

import { getComponentRenderCtxFromVNode } from 'core/component/vnode';
import { execRenderObject } from 'core/component/render';

import { parseVNodeAsFlyweight } from 'core/component/flyweight';
import { createFakeCtx, initComponentVNode, FlyweightVNode } from 'core/component/functional';

import { applyDynamicAttrs } from 'core/component/render-function/v-attrs';
import { registerComponent } from 'core/component/register';

import type { CreateElement, VNode, VNodeData } from 'core/component/engines';
import type { FunctionalCtx, ComponentInterface, UnsafeComponentInterface } from 'core/component/interface';

export const
	$$ = symbolGenerator();

/**
 * Wraps the specified createElement function and returns a pair:
 * the wrapped function, and a list of registered render tasks.
 *
 * This method adds V4Fire specific logic (v-attrs, composites, etc.) to a simple createElement function.
 *
 * @param nativeCreateElement - original createElement function
 * @param baseCtx - base component context
 */
export function wrapCreateElement(
	nativeCreateElement: CreateElement,
	baseCtx: ComponentInterface
): [CreateElement, Function[]] {
	const
		tasks = <Function[]>[],
		engine = baseCtx.$renderEngine;

	const
		{supports} = engine;

	const wrappedCreateElement = <CreateElement>function wrappedCreateElement(
		this: Nullable<ComponentInterface>,
		tag: CanUndef<string>,
		opts?: VNodeData,
		children?: VNode[]
	): CanPromise<VNode> {
		// eslint-disable-next-line
		'use strict';

		const
			ctx = this ?? baseCtx,
			unsafe = <UnsafeComponentInterface><any>(ctx),
			attrOpts = Object.isPlainObject(opts) ? opts.attrs : undefined;

		const createElement = <typeof nativeCreateElement>function createElement(this: unknown) {
			const dontProvideContext =
				nativeCreateElement[$$.wrappedCreateElement] === true &&
				unsafe.meta.params.functional !== true;

			return nativeCreateElement.apply(dontProvideContext ? this : ctx, arguments);
		};

		let
			tagName = tag,
			flyweightComponent;

		if (attrOpts == null) {
			if (tag === 'v-render') {
				return createElement();
			}

		} else {
			if (tag === 'v-render') {
				return attrOpts.from ?? createElement();
			}

			if (tagName?.[0] === '@') {
				flyweightComponent = tagName.slice(1);
				tagName = 'span';

			} else {
				flyweightComponent = attrOpts['v4-flyweight-component'];
			}

			if (tagName != null && flyweightComponent != null) {
				tagName = tagName === 'span' ? flyweightComponent : tagName.dasherize();
				attrOpts['v4-flyweight-component'] = tagName;
			}
		}

		const
			component = registerComponent(tagName);

		if (Object.isPlainObject(opts)) {
			applyDynamicAttrs(opts, component);
		}

		let
			renderKey = '';

		if (attrOpts != null) {
			if (attrOpts['render-key'] != null) {
				renderKey = `${tagName}:${attrOpts['global-name']}:${attrOpts['render-key']}`;
			}

			if (renderKey !== '' && component == null) {
				attrOpts['data-render-key'] = renderKey;
				delete attrOpts['render-key'];
			}
		}

		let
			vnode = <CanUndef<VNode | FlyweightVNode>>unsafe.renderTmp[renderKey],
			needLinkToEl = Boolean(flyweightComponent);

		const needCreateFunctionalComponent =
			!supports.regular ||

			vnode == null &&
			flyweightComponent == null &&
			supports.functional &&
			component?.params.functional === true;

		if (component && needCreateFunctionalComponent) {
			needLinkToEl = true;

			const
				{componentName} = component;

			const
				renderObject = c.componentTemplates[componentName];

			if (renderObject == null) {
				return createElement();
			}

			const
				node = createElement('span', {...opts, tag: undefined}, children),
				renderCtx = getComponentRenderCtxFromVNode(component, node, ctx);

			let
				baseCtx = <CanUndef<FunctionalCtx>>c.renderCtxCache[componentName];

			if (baseCtx == null) {
				baseCtx = Object.create(engine.minimalCtx);

				// @ts-ignore (access)
				baseCtx.componentName = componentName;

				// @ts-ignore (access)
				baseCtx.meta = component;

				// @ts-ignore (access)
				component.params.functional = true;

				// @ts-ignore (access)
				baseCtx.instance = component.instance;

				// @ts-ignore (access)
				baseCtx.$options = {};
			}

			c.renderCtxCache[componentName] = baseCtx;

			// @ts-ignore (access)
			baseCtx._l = ctx._l;

			// @ts-ignore (access)
			baseCtx._u = ctx._u;

			const fakeCtx = createFakeCtx<ComponentInterface>(
				<CreateElement>wrappedCreateElement,
				renderCtx,
				baseCtx!,
				{initProps: true}
			);

			const createComponentVNode = () => initComponentVNode(
				execRenderObject(renderObject, fakeCtx),
				fakeCtx,
				renderCtx
			);

			if (supports.ssr && Object.isPromise(fakeCtx.unsafe.$initializer)) {
				return fakeCtx.unsafe.$initializer.then(() => patchVNode(createComponentVNode()));
			}

			vnode = createComponentVNode();
		}

		if (vnode == null) {
			vnode = createElement.apply(null, arguments);

			// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition<commit_msg>Another fix of context providing :(<commit_after>/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

import symbolGenerator from 'core/symbol';
import * as c from 'core/component/const';

import { getComponentRenderCtxFromVNode } from 'core/component/vnode';
import { execRenderObject } from 'core/component/render';

import { parseVNodeAsFlyweight } from 'core/component/flyweight';
import { createFakeCtx, initComponentVNode, FlyweightVNode } from 'core/component/functional';

import { applyDynamicAttrs } from 'core/component/render-function/v-attrs';
import { registerComponent } from 'core/component/register';

import type { CreateElement, VNode, VNodeData } from 'core/component/engines';
import type { FunctionalCtx, ComponentInterface, UnsafeComponentInterface } from 'core/component/interface';

export const
	$$ = symbolGenerator();

/**
 * Wraps the specified createElement function and returns a pair:
 * the wrapped function, and a list of registered render tasks.
 *
 * This method adds V4Fire specific logic (v-attrs, composites, etc.) to a simple createElement function.
 *
 * @param nativeCreateElement - original createElement function
 * @param baseCtx - base component context
 */
export function wrapCreateElement(
	nativeCreateElement: CreateElement,
	baseCtx: ComponentInterface
): [CreateElement, Function[]] {
	const
		tasks = <Function[]>[],
		engine = baseCtx.$renderEngine;

	const
		{supports} = engine;

	const wrappedCreateElement = <CreateElement>function wrappedCreateElement(
		this: Nullable<ComponentInterface>,
		tag: CanUndef<string>,
		opts?: VNodeData,
		children?: VNode[]
	): CanPromise<VNode> {
		// eslint-disable-next-line
		'use strict';

		const
			ctx = this ?? baseCtx,
			unsafe = <UnsafeComponentInterface><any>(ctx),
			attrOpts = Object.isPlainObject(opts) ? opts.attrs : undefined;

		const createElement = <typeof nativeCreateElement>function createElement(this: unknown) {
			const dontProvideBoundContext =
				nativeCreateElement[$$.wrappedCreateElement] === true &&
				unsafe.meta.params.functional !== true;

			return nativeCreateElement.apply(dontProvideBoundContext ? this : ctx, arguments);
		};

		let
			tagName = tag,
			flyweightComponent;

		if (attrOpts == null) {
			if (tag === 'v-render') {
				return createElement();
			}

		} else {
			if (tag === 'v-render') {
				return attrOpts.from ?? createElement();
			}

			if (tagName?.[0] === '@') {
				flyweightComponent = tagName.slice(1);
				tagName = 'span';

			} else {
				flyweightComponent = attrOpts['v4-flyweight-component'];
			}

			if (tagName != null && flyweightComponent != null) {
				tagName = tagName === 'span' ? flyweightComponent : tagName.dasherize();
				attrOpts['v4-flyweight-component'] = tagName;
			}
		}

		const
			component = registerComponent(tagName);

		if (Object.isPlainObject(opts)) {
			applyDynamicAttrs(opts, component);
		}

		let
			renderKey = '';

		if (attrOpts != null) {
			if (attrOpts['render-key'] != null) {
				renderKey = `${tagName}:${attrOpts['global-name']}:${attrOpts['render-key']}`;
			}

			if (renderKey !== '' && component == null) {
				attrOpts['data-render-key'] = renderKey;
				delete attrOpts['render-key'];
			}
		}

		let
			vnode = <CanUndef<VNode | FlyweightVNode>>unsafe.renderTmp[renderKey],
			needLinkToEl = Boolean(flyweightComponent);

		const needCreateFunctionalComponent =
			!supports.regular ||

			vnode == null &&
			flyweightComponent == null &&
			supports.functional &&
			component?.params.functional === true;

		if (component && needCreateFunctionalComponent) {
			needLinkToEl = true;

			const
				{componentName} = component;

			const
				renderObject = c.componentTemplates[componentName];

			if (renderObject == null) {
				return createElement();
			}

			const
				node = createElement('span', {...opts, tag: undefined}, children),
				renderCtx = getComponentRenderCtxFromVNode(component, node, ctx);

			let
				baseCtx = <CanUndef<FunctionalCtx>>c.renderCtxCache[componentName];

			if (baseCtx == null) {
				baseCtx = Object.create(engine.minimalCtx);

				// @ts-ignore (access)
				baseCtx.componentName = componentName;

				// @ts-ignore (access)
				baseCtx.meta = component;

				// @ts-ignore (access)
				component.params.functional = true;

				// @ts-ignore (access)
				baseCtx.instance = component.instance;

				// @ts-ignore (access)
				baseCtx.$options = {};
			}

			c.renderCtxCache[componentName] = baseCtx;

			// @ts-ignore (access)
			baseCtx._l = ctx._l;

			// @ts-ignore (access)
			baseCtx._u = ctx._u;

			const fakeCtx = createFakeCtx<ComponentInterface>(
				<CreateElement>wrappedCreateElement,
				renderCtx,
				baseCtx!,
				{initProps: true}
			);

			const createComponentVNode = () => initComponentVNode(
				execRenderObject(renderObject, fakeCtx),
				fakeCtx,
				renderCtx
			);

			if (supports.ssr && Object.isPromise(fakeCtx.unsafe.$initializer)) {
				return fakeCtx.unsafe.$initializer.then(() => patchVNode(createComponentVNode()));
			}

			vnode = createComponentVNode();
		}

		if (vnode == null) {
			vnode = createElement.apply(unsafe, arguments);

			// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
{'fraction_non_alphanumeric': 0.13252784595053804, 'fraction_numerical': 0.0015102888427411742, 'mean_word_length': 3.9096385542168677, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 35, 'https://': 4, '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': '250577', 'n_tokens_mistral': 3761, 'n_tokens_neox': 3251, 'n_words': 688}