The Wayback Machine - https://web.archive.org/web/20200716101244/https://github.com/sveltejs/svelte/issues/4694
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Max Stack Size Exceeded for huge HTML #4694

Open
siebeneicher opened this issue Apr 20, 2020 · 6 comments
Open

Max Stack Size Exceeded for huge HTML #4694

siebeneicher opened this issue Apr 20, 2020 · 6 comments

Comments

@siebeneicher
Copy link

@siebeneicher siebeneicher commented Apr 20, 2020

Describe the bug
The content of the the svelte file is a large HTML chunk, withouy any script logics or styling being involved. Max stack size exceeded error while compiling.

To Reproduce
https://svelte.dev/repl/a9dfcc17551c4aeb95e8fe748a97061d?version=3.20.1

Expected behavior
Compiling should not break

Information about your Svelte project:
Svelte 3.20.1, Rollup, Windows

Severity
Its probably an uncommon case for most people. I ran into it, when using a generated data privacy HTML template. I would not see this as a priority. Workaround for me: copy the HTML into a JS template literal variable and inject it via @html: https://svelte.dev/repl/1ab32c5a3c2c426e973512cfc8da023c?version=3.20.1

@Conduitry Conduitry added the internals label Apr 20, 2020
@pushkine
Copy link
Contributor

@pushkine pushkine commented Apr 22, 2020

the compiling process involves push spreading all nodes into another array at some point and the v8 engine does not support spreading that many items
works fine on firefox

@Conduitry
Copy link
Member

@Conduitry Conduitry commented Apr 22, 2020

Interesting. I've run into this before in V8 and ended up using an array spread and a reassignment, rather than an argument spread in .push(). Conduitry/do-not-zip@861a929 It's not very helpful that V8 gives a stack size error rather than an argument count error.

I'm not sure how many places we're doing .push(...foo) in the codebase, but this might be a way forward.

@mrbarletta
Copy link

@mrbarletta mrbarletta commented May 23, 2020

Same issue when using Tailwind UI.

In a regular svelte + tailwindcss project if I add in the tailwind.config.js the tailwind UI package plugins: [ require('@tailwindcss/ui'),] then the building breaks with the same issue.

Could we update the issue name as well to include tailwindUI word? @siebeneicher

@milahu
Copy link

@milahu milahu commented Jun 1, 2020

same here

im building a large single page app / single file app, with many many html nodes

error is

[!] (plugin svelte) RangeError: Maximum call stack size exceeded
src/Main.svelte
RangeError: Maximum call stack size exceeded
    at /tmp/x/node_modules/svelte/node_modules/code-red/dist/code-red.mjs:581:10
    at /tmp/x/node_modules/svelte/node_modules/code-red/dist/code-red.mjs:226:10
    at handle (/tmp/x/node_modules/svelte/node_modules/code-red/dist/code-red.mjs:70:17)
    at /tmp/x/node_modules/svelte/node_modules/code-red/dist/code-red.mjs:248:18
    at Array.map (<anonymous>)
    at handle_body (/tmp/x/node_modules/svelte/node_modules/code-red/dist/code-red.mjs:247:21)
    at Program (/tmp/x/node_modules/svelte/node_modules/code-red/dist/code-red.mjs:318:10)
    at handle (/tmp/x/node_modules/svelte/node_modules/code-red/dist/code-red.mjs:70:17)
    at print (/tmp/x/node_modules/svelte/node_modules/code-red/dist/code-red.mjs:1413:17)
    at Component.generate (/tmp/x/node_modules/svelte/src/compiler/compile/Component.ts:316:9)

with npm install code-red

node_modules/code-red/dist/code-red.mjs line 581

		chunks.push(
			c(') '),
			...handle(node.body, state)
		);

.... as expected, using push instead of reassign

compiles to node_modules/svelte/compiler.js line 5911

			const chunks = [c('for (')];
			//
			chunks.push(
				c(') '),
				...handle(node.body, state)
			);

todo: push ----> reassign

like

			let chunks = [c('for (')];
			//
			chunks = [
				...chunks,
				c(') '),
				...handle(node.body, state)
			];
@milahu
Copy link

@milahu milahu commented Jun 2, 2020

my svelte compiler is fixed

todo: push ----> reassign

here is a quick-and-dirty patch script

/*
  node_modules/svelte/patch-compiler.js

  replace push with reassign

  cd node_modules/svelte
  mv compiler.js compiler.js.orig
  ln -s compiler.js.new compiler.js
  node patch-compiler.js
*/

const acorn_parse = require("acorn").parse;
const estree_walk = require("estree-walker").walk;
const node_tosource = require("tosource");
const magicString = require("magic-string");
const fs = require("fs");

const input_file = "compiler.js.orig";
const output_file = "compiler.js.new";

// input
const content = fs.readFileSync(input_file, 'utf8');

// output
let code = new magicString(content);

const ast = acorn_parse(
  content, {
  // ecmaVersion: 10, // default in year 2019
  sourceType: 'module',
});

const funcName = "push";

let arrayNameList = [];

function setCharAt(str, index, chr) {
  if (index > str.length-1) return str;
  return str.substr(0,index) + chr + str.substr(index+1);
}

estree_walk( ast, {
  enter: function ( node, parent, prop, index ) {

    // filter for array.push()
    if (
      node.type !== 'CallExpression' ||
      node.callee === undefined ||
      node.callee.property === undefined ||
      node.callee.property.name !== funcName
    ) {
      return;
    }

    // filter for spread operator
    if (node.arguments.find(a => {
      return (a.type == 'SpreadElement');
    }) === undefined) {
      return;
    }

    const nodeSrc = content.substring(
      node.start, node.end);

    const arrayName = content.substring(
      node.callee.object.start,
      node.callee.object.end);
    
    arrayNameList.push(arrayName);

    // patch .push(
    let nodePatch = nodeSrc.replace(
      ".push(", " /* PATCHED */ = [..."+arrayName+", ");

    // patch closing bracket
    nodePatch = setCharAt(nodePatch, nodePatch.lastIndexOf(")"), "]");

    code.overwrite(node.start, node.end, nodePatch);

}});

code = code.toString();

function filterUnique(value, index, array) { 
  return array.indexOf(value) === index;
}

// replace const with let
arrayNameList.filter(filterUnique).forEach(arrayName => {
  console.log(`arrayName = ${arrayName}`)

  code = code.replace(
    new RegExp("const "+arrayName+" = ", 'g'), // global = replace all
    "/* PATCHED const "+arrayName+" */ let "+arrayName+" = "
  );
})

fs.writeFileSync(output_file, code);

edit: included patch by rhythm-section

@rhythm-section
Copy link

@rhythm-section rhythm-section commented Jun 4, 2020

@milahu Thank you for the compiler patch. It works great. With version 3.23.0 of svelte I still had one issue with the patch that resulted in an error because of line 6442 inside comiler.js:

const chunks = node.kind !== 'init'
  ? [c(`${node.kind} `)]
  : [];

Because of the tertiary operator the const declaration does not get replaced with let which leads to an assignment error.

Not sure if it is a good solution or if it leads to other issues with other svelte versions, but the following worked for me. I changed the regex from:

new RegExp("const "+arrayName+" = \\[", 'g'), // global = replace all
    "/* PATCHED const "+arrayName+" */ let "+arrayName+" = ["

to:

new RegExp("const "+arrayName+" = ", 'g'), // global = replace all
    "let "+arrayName+" = "

Hope this helps someone still having troubles.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants
You can’t perform that action at this time.