Files
Donny/강동윤andGitHub 3a5b73d2d6 perf(turbopack): Remove ImportBinding fragments (#78470)
### What?

Make the `ImportBinding` node a phantom node.

### Why?

Because they are not used. We have to import directly from the original
module because of the static analysis like `next/dynamic`. So I modified
the tree shaking to import directly with
https://github.com/vercel/next.js/pull/71704. But #71704 didn't remove
the concept of `ImportBinding`. This PR finishes the work of using
direct imports.

Additionally, this PR introduces `ReexportBinding` fragments because
these are not phantom nodes. I'll check if it would be possible to
remove `ReexportBinding` fragments with follow-up PRs.

### How?

 - Closes PACK-4366
2025-04-28 15:10:59 +00:00

17 KiB

Items

Count: 6

Item 1: Stmt 0, ImportOfModule

import { IPC } from "./index";

  • Hoisted
  • Side effects

Item 2: Stmt 0, ImportBinding(0)

import { IPC } from "./index";

  • Hoisted
  • Declares: IPC

Item 3: Stmt 1, VarDeclarator(0)

const ipc = IPC;

  • Declares: ipc
  • Reads: IPC
  • Write: ipc

Item 4: Stmt 2, VarDeclarator(0)

const queue = [];

  • Declares: queue
  • Write: queue

Item 5: Stmt 3, VarDeclarator(0)

export const run = async (moduleFactory)=>{
    let nextId = 1;
    const requests = new Map();
    const internalIpc = {
        sendInfo: (message)=>ipc.send({
                type: "info",
                data: message
            }),
        sendRequest: (message)=>{
            const id = nextId++;
            let resolve, reject;
            const promise = new Promise((res, rej)=>{
                resolve = res;
                reject = rej;
            });
            requests.set(id, {
                resolve,
                reject
            });
            return ipc.send({
                type: "request",
                id,
                data: message
            }).then(()=>promise);
        },
        sendError: (error)=>{
            return ipc.sendError(error);
        }
    };
    let getValue;
    try {
        const module = await moduleFactory();
        if (typeof module.init === "function") {
            await module.init();
        }
        getValue = module.default;
        await ipc.sendReady();
    } catch (err) {
        await ipc.sendReady();
        await ipc.sendError(err);
    }
    let isRunning = false;
    const run = async ()=>{
        while(queue.length > 0){
            const args = queue.shift();
            try {
                const value = await getValue(internalIpc, ...args);
                await ipc.send({
                    type: "end",
                    data: value === undefined ? undefined : JSON.stringify(value, null, 2),
                    duration: 0
                });
            } catch (e) {
                await ipc.sendError(e);
            }
        }
        isRunning = false;
    };
    while(true){
        const msg = await ipc.recv();
        switch(msg.type){
            case "evaluate":
                {
                    queue.push(msg.args);
                    if (!isRunning) {
                        isRunning = true;
                        run();
                    }
                    break;
                }
            case "result":
                {
                    const request = requests.get(msg.id);
                    if (request) {
                        requests.delete(msg.id);
                        if (msg.error) {
                            request.reject(new Error(msg.error));
                        } else {
                            request.resolve(msg.data);
                        }
                    }
                    break;
                }
            default:
                {
                    console.error("unexpected message type", msg.type);
                    process.exit(1);
                }
        }
    }
};

  • Side effects
  • Declares: run
  • Reads: ipc, queue
  • Write: ipc, queue, run

Phase 1

graph TD
    Item1;
    Item2;
    Item3;
    Item4;
    Item5;
    Item6;
    Item6["export run"];

Phase 2

graph TD
    Item1;
    Item2;
    Item3;
    Item4;
    Item5;
    Item6;
    Item6["export run"];
    Item3 --> Item2;
    Item5 --> Item3;
    Item5 --> Item4;
    Item5 --> Item1;
    Item6 --> Item5;

Phase 3

graph TD
    Item1;
    Item2;
    Item3;
    Item4;
    Item5;
    Item6;
    Item6["export run"];
    Item3 --> Item2;
    Item5 --> Item3;
    Item5 --> Item4;
    Item5 --> Item1;
    Item6 --> Item5;

Phase 4

graph TD
    Item1;
    Item2;
    Item3;
    Item4;
    Item5;
    Item6;
    Item6["export run"];
    Item3 --> Item2;
    Item5 --> Item3;
    Item5 --> Item4;
    Item5 --> Item1;
    Item6 --> Item5;

Final

graph TD
    N0["Items: [ItemId(0, ImportOfModule)]"];
    N1["Items: [ItemId(0, ImportBinding(0))]"];
    N2["Items: [ItemId(1, VarDeclarator(0)), ItemId(2, VarDeclarator(0)), ItemId(3, VarDeclarator(0)), ItemId(Export(("run", #2), "run"))]"];
    N1 --> N0;
    N2 --> N0;

Entrypoints

{
    ModuleEvaluation: 2,
    Export(
        "run",
    ): 2,
    Exports: 3,
}

Modules (dev)

Part 0

import "./index";

Part 1

import "__TURBOPACK_PART__" assert {
    __turbopack_part__: 0
};

Part 2

import "__TURBOPACK_PART__" assert {
    __turbopack_part__: 0
};
import { IPC } from "./index";
import "__TURBOPACK_PART__" assert {
    __turbopack_part__: 0
};
const ipc = IPC;
const queue = [];
const run = async (moduleFactory)=>{
    let nextId = 1;
    const requests = new Map();
    const internalIpc = {
        sendInfo: (message)=>ipc.send({
                type: "info",
                data: message
            }),
        sendRequest: (message)=>{
            const id = nextId++;
            let resolve, reject;
            const promise = new Promise((res, rej)=>{
                resolve = res;
                reject = rej;
            });
            requests.set(id, {
                resolve,
                reject
            });
            return ipc.send({
                type: "request",
                id,
                data: message
            }).then(()=>promise);
        },
        sendError: (error)=>{
            return ipc.sendError(error);
        }
    };
    let getValue;
    try {
        const module = await moduleFactory();
        if (typeof module.init === "function") {
            await module.init();
        }
        getValue = module.default;
        await ipc.sendReady();
    } catch (err) {
        await ipc.sendReady();
        await ipc.sendError(err);
    }
    let isRunning = false;
    const run = async ()=>{
        while(queue.length > 0){
            const args = queue.shift();
            try {
                const value = await getValue(internalIpc, ...args);
                await ipc.send({
                    type: "end",
                    data: value === undefined ? undefined : JSON.stringify(value, null, 2),
                    duration: 0
                });
            } catch (e) {
                await ipc.sendError(e);
            }
        }
        isRunning = false;
    };
    while(true){
        const msg = await ipc.recv();
        switch(msg.type){
            case "evaluate":
                {
                    queue.push(msg.args);
                    if (!isRunning) {
                        isRunning = true;
                        run();
                    }
                    break;
                }
            case "result":
                {
                    const request = requests.get(msg.id);
                    if (request) {
                        requests.delete(msg.id);
                        if (msg.error) {
                            request.reject(new Error(msg.error));
                        } else {
                            request.resolve(msg.data);
                        }
                    }
                    break;
                }
            default:
                {
                    console.error("unexpected message type", msg.type);
                    process.exit(1);
                }
        }
    }
};
export { run };
export { ipc as a } from "__TURBOPACK_VAR__" assert {
    __turbopack_var__: true
};
export { queue as b } from "__TURBOPACK_VAR__" assert {
    __turbopack_var__: true
};
export { run as c } from "__TURBOPACK_VAR__" assert {
    __turbopack_var__: true
};
export { };

Part 3

export { run } from "__TURBOPACK_PART__" assert {
    __turbopack_part__: "export run"
};

Merged (module eval)

import "__TURBOPACK_PART__" assert {
    __turbopack_part__: 0
};
import { IPC } from "./index";
const ipc = IPC;
const queue = [];
const run = async (moduleFactory)=>{
    let nextId = 1;
    const requests = new Map();
    const internalIpc = {
        sendInfo: (message)=>ipc.send({
                type: "info",
                data: message
            }),
        sendRequest: (message)=>{
            const id = nextId++;
            let resolve, reject;
            const promise = new Promise((res, rej)=>{
                resolve = res;
                reject = rej;
            });
            requests.set(id, {
                resolve,
                reject
            });
            return ipc.send({
                type: "request",
                id,
                data: message
            }).then(()=>promise);
        },
        sendError: (error)=>{
            return ipc.sendError(error);
        }
    };
    let getValue;
    try {
        const module = await moduleFactory();
        if (typeof module.init === "function") {
            await module.init();
        }
        getValue = module.default;
        await ipc.sendReady();
    } catch (err) {
        await ipc.sendReady();
        await ipc.sendError(err);
    }
    let isRunning = false;
    const run = async ()=>{
        while(queue.length > 0){
            const args = queue.shift();
            try {
                const value = await getValue(internalIpc, ...args);
                await ipc.send({
                    type: "end",
                    data: value === undefined ? undefined : JSON.stringify(value, null, 2),
                    duration: 0
                });
            } catch (e) {
                await ipc.sendError(e);
            }
        }
        isRunning = false;
    };
    while(true){
        const msg = await ipc.recv();
        switch(msg.type){
            case "evaluate":
                {
                    queue.push(msg.args);
                    if (!isRunning) {
                        isRunning = true;
                        run();
                    }
                    break;
                }
            case "result":
                {
                    const request = requests.get(msg.id);
                    if (request) {
                        requests.delete(msg.id);
                        if (msg.error) {
                            request.reject(new Error(msg.error));
                        } else {
                            request.resolve(msg.data);
                        }
                    }
                    break;
                }
            default:
                {
                    console.error("unexpected message type", msg.type);
                    process.exit(1);
                }
        }
    }
};
export { run };
export { ipc as a } from "__TURBOPACK_VAR__" assert {
    __turbopack_var__: true
};
export { queue as b } from "__TURBOPACK_VAR__" assert {
    __turbopack_var__: true
};
export { run as c } from "__TURBOPACK_VAR__" assert {
    __turbopack_var__: true
};
export { };

Entrypoints

{
    ModuleEvaluation: 2,
    Export(
        "run",
    ): 2,
    Exports: 3,
}

Modules (prod)

Part 0

import "./index";

Part 1

import "__TURBOPACK_PART__" assert {
    __turbopack_part__: 0
};

Part 2

import "__TURBOPACK_PART__" assert {
    __turbopack_part__: 0
};
import { IPC } from "./index";
import "__TURBOPACK_PART__" assert {
    __turbopack_part__: 0
};
const ipc = IPC;
const queue = [];
const run = async (moduleFactory)=>{
    let nextId = 1;
    const requests = new Map();
    const internalIpc = {
        sendInfo: (message)=>ipc.send({
                type: "info",
                data: message
            }),
        sendRequest: (message)=>{
            const id = nextId++;
            let resolve, reject;
            const promise = new Promise((res, rej)=>{
                resolve = res;
                reject = rej;
            });
            requests.set(id, {
                resolve,
                reject
            });
            return ipc.send({
                type: "request",
                id,
                data: message
            }).then(()=>promise);
        },
        sendError: (error)=>{
            return ipc.sendError(error);
        }
    };
    let getValue;
    try {
        const module = await moduleFactory();
        if (typeof module.init === "function") {
            await module.init();
        }
        getValue = module.default;
        await ipc.sendReady();
    } catch (err) {
        await ipc.sendReady();
        await ipc.sendError(err);
    }
    let isRunning = false;
    const run = async ()=>{
        while(queue.length > 0){
            const args = queue.shift();
            try {
                const value = await getValue(internalIpc, ...args);
                await ipc.send({
                    type: "end",
                    data: value === undefined ? undefined : JSON.stringify(value, null, 2),
                    duration: 0
                });
            } catch (e) {
                await ipc.sendError(e);
            }
        }
        isRunning = false;
    };
    while(true){
        const msg = await ipc.recv();
        switch(msg.type){
            case "evaluate":
                {
                    queue.push(msg.args);
                    if (!isRunning) {
                        isRunning = true;
                        run();
                    }
                    break;
                }
            case "result":
                {
                    const request = requests.get(msg.id);
                    if (request) {
                        requests.delete(msg.id);
                        if (msg.error) {
                            request.reject(new Error(msg.error));
                        } else {
                            request.resolve(msg.data);
                        }
                    }
                    break;
                }
            default:
                {
                    console.error("unexpected message type", msg.type);
                    process.exit(1);
                }
        }
    }
};
export { run };
export { ipc as a } from "__TURBOPACK_VAR__" assert {
    __turbopack_var__: true
};
export { queue as b } from "__TURBOPACK_VAR__" assert {
    __turbopack_var__: true
};
export { run as c } from "__TURBOPACK_VAR__" assert {
    __turbopack_var__: true
};
export { };

Part 3

export { run } from "__TURBOPACK_PART__" assert {
    __turbopack_part__: "export run"
};

Merged (module eval)

import "__TURBOPACK_PART__" assert {
    __turbopack_part__: 0
};
import { IPC } from "./index";
const ipc = IPC;
const queue = [];
const run = async (moduleFactory)=>{
    let nextId = 1;
    const requests = new Map();
    const internalIpc = {
        sendInfo: (message)=>ipc.send({
                type: "info",
                data: message
            }),
        sendRequest: (message)=>{
            const id = nextId++;
            let resolve, reject;
            const promise = new Promise((res, rej)=>{
                resolve = res;
                reject = rej;
            });
            requests.set(id, {
                resolve,
                reject
            });
            return ipc.send({
                type: "request",
                id,
                data: message
            }).then(()=>promise);
        },
        sendError: (error)=>{
            return ipc.sendError(error);
        }
    };
    let getValue;
    try {
        const module = await moduleFactory();
        if (typeof module.init === "function") {
            await module.init();
        }
        getValue = module.default;
        await ipc.sendReady();
    } catch (err) {
        await ipc.sendReady();
        await ipc.sendError(err);
    }
    let isRunning = false;
    const run = async ()=>{
        while(queue.length > 0){
            const args = queue.shift();
            try {
                const value = await getValue(internalIpc, ...args);
                await ipc.send({
                    type: "end",
                    data: value === undefined ? undefined : JSON.stringify(value, null, 2),
                    duration: 0
                });
            } catch (e) {
                await ipc.sendError(e);
            }
        }
        isRunning = false;
    };
    while(true){
        const msg = await ipc.recv();
        switch(msg.type){
            case "evaluate":
                {
                    queue.push(msg.args);
                    if (!isRunning) {
                        isRunning = true;
                        run();
                    }
                    break;
                }
            case "result":
                {
                    const request = requests.get(msg.id);
                    if (request) {
                        requests.delete(msg.id);
                        if (msg.error) {
                            request.reject(new Error(msg.error));
                        } else {
                            request.resolve(msg.data);
                        }
                    }
                    break;
                }
            default:
                {
                    console.error("unexpected message type", msg.type);
                    process.exit(1);
                }
        }
    }
};
export { run };
export { ipc as a } from "__TURBOPACK_VAR__" assert {
    __turbopack_var__: true
};
export { queue as b } from "__TURBOPACK_VAR__" assert {
    __turbopack_var__: true
};
export { run as c } from "__TURBOPACK_VAR__" assert {
    __turbopack_var__: true
};
export { };