* @param {Identifier} node * @param {State} state * @param {any[]} path
(node, state, path)
| 1850 | * @param {any[]} path |
| 1851 | */ |
| 1852 | function handle_identifier(node, state, path) { |
| 1853 | const parent = path.at(-1); |
| 1854 | if (parent?.type === 'MemberExpression' && parent.property === node) return; |
| 1855 | |
| 1856 | if (state.analysis.uses_props && node.name !== '$$slots') { |
| 1857 | if (node.name === '$$props' || node.name === '$$restProps') { |
| 1858 | // not 100% correct for $$restProps but it'll do |
| 1859 | state.str.update( |
| 1860 | /** @type {number} */ (node.start), |
| 1861 | /** @type {number} */ (node.end), |
| 1862 | state.names.props |
| 1863 | ); |
| 1864 | } else { |
| 1865 | const binding = state.scope.get(node.name); |
| 1866 | if (binding?.kind === 'bindable_prop' && binding.node !== node) { |
| 1867 | state.str.prependLeft(/** @type {number} */ (node.start), `${state.names.props}.`); |
| 1868 | } |
| 1869 | } |
| 1870 | } else if (node.name === '$$restProps' && state.analysis.uses_rest_props) { |
| 1871 | state.str.update( |
| 1872 | /** @type {number} */ (node.start), |
| 1873 | /** @type {number} */ (node.end), |
| 1874 | state.names.rest |
| 1875 | ); |
| 1876 | } else if (node.name === '$$slots' && state.analysis.uses_slots) { |
| 1877 | if (parent?.type === 'MemberExpression') { |
| 1878 | if (state.analysis.custom_element) return; |
| 1879 | |
| 1880 | let name = parent.property.type === 'Literal' ? parent.property.value : parent.property.name; |
| 1881 | let slot_name = name; |
| 1882 | const existing_prop = state.props.find((prop) => prop.slot_name === name); |
| 1883 | if (existing_prop) { |
| 1884 | name = existing_prop.local; |
| 1885 | } else if (name !== 'default') { |
| 1886 | let new_name = state.scope.generate(name); |
| 1887 | if (new_name !== name) { |
| 1888 | throw new MigrationError( |
| 1889 | `This migration would change the name of a slot (${name} to ${new_name}) making the component unusable` |
| 1890 | ); |
| 1891 | } |
| 1892 | } |
| 1893 | |
| 1894 | name = name === 'default' ? 'children' : name; |
| 1895 | |
| 1896 | if (!existing_prop) { |
| 1897 | state.props.push({ |
| 1898 | local: name, |
| 1899 | exported: name, |
| 1900 | init: '', |
| 1901 | bindable: false, |
| 1902 | optional: true, |
| 1903 | slot_name, |
| 1904 | // if it's the first time we encounter this slot |
| 1905 | // we start with any and delegate to when the slot |
| 1906 | // is actually rendered (it might not happen in that case) |
| 1907 | // any is still a safe bet |
| 1908 | type: `import('svelte').Snippet<[any]>`, |
| 1909 | needs_refine_type: true |
no test coverage detected