ember-source
Version:
A JavaScript framework for creating ambitious web applications
149 lines (137 loc) • 5.36 kB
JavaScript
import '../@glimmer/global-context/index.js';
import './debug-to-string-BsFOvUtQ.js';
import { isDevelopingApp } from '@embroider/macros';
import { track } from '../@glimmer/validator/index.js';
import { v as valueForRef } from './reference-B6HMX4y0.js';
const CUSTOM_TAG_FOR = new WeakMap();
function getCustomTagFor(obj) {
return CUSTOM_TAG_FOR.get(obj);
}
function setCustomTagFor(obj, customTagFn) {
CUSTOM_TAG_FOR.set(obj, customTagFn);
}
function convertToInt(prop) {
if (typeof prop === 'symbol') return null;
const num = Number(prop);
if (isNaN(num)) return null;
return num % 1 === 0 ? num : null;
}
function tagForNamedArg(namedArgs, key) {
return track(() => {
if (key in namedArgs) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
valueForRef(namedArgs[key]);
}
});
}
function tagForPositionalArg(positionalArgs, key) {
return track(() => {
if (key === '[]') {
// consume all of the tags in the positional array
positionalArgs.forEach(valueForRef);
}
const parsed = convertToInt(key);
if (parsed !== null && parsed < positionalArgs.length) {
// consume the tag of the referenced index
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
valueForRef(positionalArgs[parsed]);
}
});
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- @fixme
class NamedArgsProxy {
// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- @fixme
constructor(named) {
this.named = named;
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- @fixme
get(_target, prop) {
const ref = this.named[prop];
if (ref !== undefined) {
return valueForRef(ref);
}
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- @fixme
has(_target, prop) {
return prop in this.named;
}
ownKeys() {
return Object.keys(this.named);
}
isExtensible() {
return false;
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- @fixme
getOwnPropertyDescriptor(_target, prop) {
if (isDevelopingApp() && !(prop in this.named)) {
throw new Error(`args proxies do not have real property descriptors, so you should never need to call getOwnPropertyDescriptor yourself. This code exists for enumerability, such as in for-in loops and Object.keys(). Attempted to get the descriptor for \`${String(prop)}\``);
}
return {
enumerable: true,
configurable: true
};
}
}
class PositionalArgsProxy {
constructor(positional) {
this.positional = positional;
}
get(target, prop) {
let {
positional
} = this;
if (prop === 'length') {
return positional.length;
}
const parsed = convertToInt(prop);
if (parsed !== null && parsed < positional.length) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
return valueForRef(positional[parsed]);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
return target[prop];
}
isExtensible() {
return false;
}
has(_target, prop) {
const parsed = convertToInt(prop);
return parsed !== null && parsed < this.positional.length;
}
}
const argsProxyFor = (capturedArgs, type) => {
const {
named,
positional
} = capturedArgs;
let getNamedTag = (_obj, key) => tagForNamedArg(named, key);
let getPositionalTag = (_obj, key) => tagForPositionalArg(positional, key);
const namedHandler = new NamedArgsProxy(named);
const positionalHandler = new PositionalArgsProxy(positional);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const namedTarget = Object.create(null);
const positionalTarget = [];
if (isDevelopingApp()) {
const setHandler = function (_target, prop) {
throw new Error(`You attempted to set ${String(prop)} on the arguments of a component, helper, or modifier. Arguments are immutable and cannot be updated directly; they always represent the values that are passed down. If you want to set default values, you should use a getter and local tracked state instead.`);
};
const forInDebugHandler = () => {
throw new Error(`Object.keys() was called on the positional arguments array for a ${type}, which is not supported. This function is a low-level function that should not need to be called for positional argument arrays. You may be attempting to iterate over the array using for...in instead of for...of.`);
};
namedHandler.set = setHandler;
positionalHandler.set = setHandler;
positionalHandler.ownKeys = forInDebugHandler;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const namedProxy = new Proxy(namedTarget, namedHandler);
const positionalProxy = new Proxy(positionalTarget, positionalHandler);
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
setCustomTagFor(namedProxy, getNamedTag);
setCustomTagFor(positionalProxy, getPositionalTag);
return {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
named: namedProxy,
positional: positionalProxy
};
};
export { argsProxyFor as a, getCustomTagFor as g, setCustomTagFor as s };