3 puntos por GN⁺ 2024-08-30 | 1 comentarios | Compartir por WhatsApp
  • Mientras navegaba por internet, encontré un interesante componente de arte ASCII. Se veía genial, pero era difícil entender cómo estaba implementado
  • Revisé el código fuente, pero el código estaba minificado

Ejemplo de código minificado

  • Parte del código era la siguiente:
    const { floor: ra, abs: KE, min: QE } = Math,  
      O5 = ["reactive.network REACTIVE.NETWORK", "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ"],  
      G7 = Date.now() % 3 ? O5[1] : O5[0],  
      V5 = G7.length,  
      JE = { fps: 60 };  
    

Solicitud a ChatGPT para explicar el código

  • Le pedí a ChatGPT: "explícame el código"
  • Respuesta de ChatGPT:

    El código proporcionado es bastante complejo, pero voy a explicar cada parte y su función de una manera fácil de entender.

Resumen general

  • Define varias funciones y componentes usando JavaScript
  • Genera contenido de texto dinámico en una aplicación React
  • Crea efectos visuales usando arte ASCII o conjuntos de caracteres predefinidos

Componentes y funciones principales

  1. Selección del conjunto de caracteres:
const { floor: ra, abs: KE, min: QE } = Math;  
const O5 = ["reactive.network REACTIVE.NETWORK", "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ"];  
const G7 = Date.now() % 3 ? O5[1] : O5[0];  
const V5 = G7.length;  
  • Toma funciones de Math y define dos conjuntos de caracteres
  • Selecciona un conjunto de caracteres según la hora actual
  • Guarda la longitud del conjunto de caracteres seleccionado
  1. Función de selección dinámica de caracteres:
function eT(e, t, n, r) {  
  const i = t.time * 8e-5;  
  const s = QE(t.cols, t.rows);  
  const o = t.metrics.aspect * 0.2;  
  const l = { x: ((4 * (e.x - t.cols / 6.25)) / s) * o, y: (5 * (e.y - t.rows / 4)) / s };  
  const u = ra(KE(YE(l) - i) * V5 + (ra(e.x / 1) % 2) * 2) % V5;  
  return G7[u];  
}  
  • La función eT genera un carácter según la posición de entrada y la hora actual
  • Ajusta la posición y selecciona un carácter del conjunto de caracteres
  1. Componente de React que muestra contenido dinámico (tT):
const tT = () => {  
  const e = j.useRef(null);  
  const [t, n] = j.useState({ height: null, width: null });  
  j.useEffect(() => {  
    function r() {  
      n({ height: window.innerHeight, width: window.innerWidth });  
    }  
    if (typeof window < "u") {  
      n({ height: window.innerHeight, width: window.innerWidth });  
      window.addEventListener("resize", r);  
      return () => window.removeEventListener("resize", r);  
    }  
  }, []);  
  j.useEffect(() => {  
    const r = e.current;  
    if (!r) return;  
    const i = 12;  
    const s = ra(t.width / i) * 1.6;  
    const o = ra(t.height / i);  
    const l = { aspect: s / o };  
    const u = setInterval(() => {  
      let c = "";  
      for (let d = 0; d < o; d++) {  
        for (let f = 0; f < s; f++) c += eT({ x: f, y: d }, { cols: s, rows: o, metrics: l, time: Date.now() });  
        c += `  `;  
      }  
      r.textContent = c;  
    }, 1e3 / JE.fps);  
    return () => clearInterval(u);  
  }, [t]);  
  return a.jsx("div", { style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }, children: a.jsx("div", { ref: e, style: { width: "100%", height: "100%", whiteSpace: "pre", overflow: "hidden" } }) });  
};  
  • Este componente de React actualiza periódicamente el contenido de un elemento div con caracteres generados dinámicamente
  • Calcula la cantidad de columnas y filas según el tamaño de la ventana y llena el div con caracteres

Código convertido a TypeScript

  • Le pedí a ChatGPT el código convertido a TypeScript
  • Respuesta de ChatGPT:
    import React, { useEffect, useRef, useState } from 'react';  
    const selectedCharacterSet = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,^`'. .:â–‘â–’â–“â–ˆ";  
    const characterSetLength = selectedCharacterSet.length;  
    
    const calculateCharacter = (  
      x: number,  
      y: number,  
      cols: number,  
      rows: number,  
      aspect: number,  
      time: number,  
    ): string => {  
      const timeFactor = time * 0.000_08;  
      const size = Math.min(cols, rows);  
      const aspectRatio = aspect * 0.2;  
      const position = {  
        x: ((4 * (x - cols / 6.25)) / size) * aspectRatio,  
        y: (5 * (y - rows / 4)) / size,  
      };  
      const index = Math.floor(  
        Math.abs(  
          Math.cos(position.x * position.x - position.y * position.y) - timeFactor,  
        ) * characterSetLength + (Math.floor(x) % 2) * 2,  
      ) % characterSetLength;  
      return selectedCharacterSet[index];  
    };  
    
    type Size = {  
      height: null | number;  
      width: null | number;  
    };  
    
    const AsciiArtGenerator: React.FC = () => {  
      const textRef = useRef(null);  
      const [size, setSize] = useState({ height: null, width: null });  
    
      useEffect(() => {  
        const handleResize = () => {  
          setSize({ height: window.innerHeight, width: window.innerWidth });  
        };  
        handleResize();  
        window.addEventListener('resize', handleResize);  
        return () => {  
          window.removeEventListener('resize', handleResize);  
        };  
      }, []);  
    
      useEffect(() => {  
        const element = textRef.current;  
        if (!element || !size.width || !size.height) return undefined;  
    
        const cols = Math.floor(size.width / 12) * 1.6;  
        const rows = Math.floor(size.height / 12);  
        const aspectRatio = cols / rows;  
    
        const intervalId = setInterval(() => {  
          let content = '';  
          for (let y = 0; y < rows; y++) {  
            for (let x = 0; x < cols; x++) {  
              content += calculateCharacter(x, y, cols, rows, aspectRatio, Date.now());  
            }  
            content += '\n';  
          }  
          element.textContent = content;  
        }, 1_000 / 60);  
    
        return () => {  
          clearInterval(intervalId);  
        };  
      }, [size]);  
    
      return (  
    
      );  
    };  
    
    export default () => {  
      return ;  
    };  
    

Resumen de GN⁺

  • Este artículo explica cómo entender y restaurar código minificado
  • Muestra el proceso de usar ChatGPT para explicar código complejo y convertirlo a TypeScript
  • Presenta una forma de aprovechar herramientas de IA para ayudar a restaurar y entender código
  • Proyectos con funciones similares incluyen Prettier y UglifyJS

1 comentarios

 
GN⁺ 2024-08-30
Opiniones en Hacker News
  • El autor de HumanifyJS desarrolló una herramienta basada en LLM. Esta herramienta usa LLM a nivel de AST para garantizar que el código siga funcionando después de la desminificación

  • La minificación de JS es mecánica y relativamente simple. Es tediosa de hacer manualmente, pero la transformación en sí es limitada, así que se puede leer siguiendo los identificadores con algunas notas

  • La desminificación o desofuscación general sigue siendo un problema sin resolver. En el pasado escribí un programa ofuscado intencionalmente, y ChatGPT no pudo entenderlo ni siquiera a nivel superficial

    • Ejemplo: GPT-4 intentó explicar un intérprete de Brainfuck de 160 bytes, pero no se parecía en nada al código original
    • Enlace al código de ejemplo
  • Algunos desarrolladores podrían molestarse porque usan la minificación para ofuscar. La herramienta de "cifrado" de código incluida en versiones anteriores de ColdFusion era un algoritmo débil, pero aun así hubo gente que la consideró segura y la usó

  • En el título, podría ser más apropiado usar ChatGPT o gpt-4 en lugar de OpenAI

  • Este trabajo es un ejemplo de desempeño intelectual superior al humano. Los LLM entienden la desminificación y, en este tema específico, superan a los humanos

  • Los LLM destacan en la transformación de texto. Esa es su fortaleza central

  • Hace aproximadamente un año, intenté usar GPT para desofuscar malware, pero fue mejor analizar el código directamente. Cuando lo intenté de nuevo recientemente, sí logró entenderlo en cierta medida

    • Ejemplo: identificó la lógica para detectar la carga de la página, realizar cálculos y redirigir a un sitio malicioso
    • Enlace al reporte
  • Usar LLM para hacer más legible código complejo se siente muy liberador. A veces se les escapan detalles, pero eso se puede verificar por cuenta propia

    • Puedes entender el propósito del código, pero si no entiendes por qué fue escrito de cierta manera, puedes preguntarle al LLM y obtener nuevas ideas
    • Enlace al ejemplo de uso
  • Si el código desminificado no coincide con el código minificado, su utilidad se reduce mucho. En muchos casos no es posible verificar las diferencias después de ejecutar el código

  • Cuando quieres conocer el algoritmo de cálculo de un sitio web, podías pegar el JS minificado en ChatGPT y entenderlo fácilmente. Es posible imaginar un futuro en el que un LLM pueda clonar una app SAAS completa

    • Ejemplo: para crear un clon de HubSpot, un LLM podría interactuar con el navegador, analizar la UI y proponer una arquitectura de backend
    • La IA será un fuerte factor deflacionario en el futuro