MCPcopy Create free account
hub / github.com/LuanRT/YouTube.js / renderNode

Method renderNode

src/utils/javascript/JsExtractor.ts:248–321  ·  view source on GitHub ↗

* Renders an AST node to JavaScript source code, with special handling for variable declarators. * @param node - The ESTree node to render. * @param preDeclared - Whether the variable has been previously declared. * @param options - Configuration options for the emitter.

(
    node: ESTree.Node,
    preDeclared: boolean,
    options: EmitterOptions = {}
  )

Source from the content-addressed store, hash-verified

246 * @param options - Configuration options for the emitter.
247 */
248 private renderNode(
249 node: ESTree.Node,
250 preDeclared: boolean,
251 options: EmitterOptions = {}
252 ) {
253 const source = this.analyzer.getSource();
254 const declaredVariables = this.analyzer.declaredVariables;
255
256 const sideEffectPolicy = options.disallowSideEffectInitializers;
257 const sideEffectMode = typeof sideEffectPolicy === 'object' && sideEffectPolicy !== null ?
258 sideEffectPolicy.mode ?? 'strict' : 'strict';
259 const canDisallow = Boolean(sideEffectPolicy);
260
261 const assignmentTarget =
262 node.type === 'AssignmentExpression'
263 ? node
264 : node.type === 'ExpressionStatement' && node.expression.type === 'AssignmentExpression'
265 ? node.expression
266 : null;
267
268 const init = assignmentTarget && assignmentTarget.operator === '=' ? assignmentTarget.right : node.type === 'VariableDeclarator' ? node.init : null;
269 const forceRemove = canDisallow && init && !this.isSafeInitializer(init, sideEffectMode);
270 const initializerFallback = this.getInitializerFallback(init);
271
272 let initSource = initializerFallback;
273
274 if (!forceRemove && init) {
275 // e.g. `var someVar = document;`
276 if (!preDeclared && init.type === 'Identifier' && !declaredVariables.has(init.name)) {
277 initSource = initializerFallback;
278 } else {
279 const left = assignmentTarget?.left;
280 const isPrototypeAlias = init?.type === 'MemberExpression' && !init.computed && init.property.type === 'Identifier' && init.property.name === 'prototype';
281
282 // Skip things we don't need.
283 if (!isPrototypeAlias && left?.type === 'MemberExpression' && init) {
284 if (
285 canDisallow &&
286 left.object.type === 'Identifier' &&
287 init.type !== 'FunctionExpression' &&
288 init.type !== 'ArrowFunctionExpression' &&
289 init.type !== 'LogicalExpression' &&
290 init.type !== 'ClassExpression'
291 ) {
292 return `${indent}// Skipped ${memberToString(left, source)} assignment.`;
293 }
294 }
295
296 // e.g. `someVar = someOtherVarFuncOrCall`
297 initSource = extractNodeSource(init, source)
298 ?.trim()
299 .replace(/;\s*$/, '') || 'undefined // [JsExtractor] Failed to extract initializer source.';
300 }
301 }
302
303 // Wrap sequence expressions in parens to avoid syntax issues.
304 if (!forceRemove && init && init.type === 'SequenceExpression' && !initSource.startsWith('(')) {
305 initSource = `(${initSource})`;

Callers 2

visitMethod · 0.95
buildScriptMethod · 0.95

Calls 5

isSafeInitializerMethod · 0.95
memberToStringFunction · 0.85
extractNodeSourceFunction · 0.85
getSourceMethod · 0.80

Tested by

no test coverage detected