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

SyntaxError: Identifier 'frames' has already been declared #72

Closed
ato opened this issue Jul 26, 2021 · 3 comments
Closed

SyntaxError: Identifier 'frames' has already been declared #72

ato opened this issue Jul 26, 2021 · 3 comments

Comments

@ato
Copy link

ato commented Jul 26, 2021

The preamble added by Wombat.wrapScriptTextJsProxy to every JavaScript file declares the following locals:

let window = _____WB$wombat$assign$function_____("window");
let self = _____WB$wombat$assign$function_____("self");
let document = _____WB$wombat$assign$function_____("document");
let location = _____WB$wombat$assign$function_____("location");
let top = _____WB$wombat$assign$function_____("top");
let parent = _____WB$wombat$assign$function_____("parent");
let frames = _____WB$wombat$assign$function_____("frames");
let opener = _____WB$wombat$assign$function_____("opener");

If the script itself uses any of those names as locals then it causes an error:

SyntaxError: Identifier 'frames' has already been declared

Discovered in the wild on the wild on a pywb replay of https://gladybird.com/ in which game.js tries to declare a frame counter with:

let frames = 0;
ato added a commit to nla/nla-pywb that referenced this issue Jul 26, 2021
@ato
Copy link
Author

ato commented Jul 26, 2021

We're trying a workaround nla/pywb@fe97e7e for this by wrapping the script in additional block after wombat's locals are declared. Effectively:

let frames = _____WB$wombat$assign$function_____("frames");
{
   let frames = 0;
   // .. the rest of the original script
}

This solves it for the particular case we had reported, although this is far from a perfect solution as it'll still throw SyntaxError if the script uses var frames instead of let frames. I also worried it would also have the side effect of breaking code like this:

test.js

let x = "Hello world!"

test.html

<script src="test.js"></script>
<script>
document.write(x);
</script>

However it turns out pywb is already wrapping rewritten scripts in a block so I guess the workaround doesn't make that any worse than it already is.

@ikreymer
Copy link
Member

That's a pretty good workaround.. yes, there is an issue with globals being wrapped. Luckily, this type of use with globals is not as is not as common, and less so with modern websites.

As far as var, it appears that var with self, parent, opener, frames, is allowed but not with window, location, documentandtop`.

Perhaps it could be worth adding a check for, say var frames or var opener and skipping if found. Then again, it'll need to be a regex and could slow down processing, so perhaps not needed until it is found 'in the wild'.

(I guess this issue is shared between wombat/pywb/wabac.js since this wrapping happens in all 3 places currently).

ikreymer added a commit that referenced this issue Aug 12, 2021
#74)

* eval fix: 
- instead of 'WB_wombat_eval', ensure window proxy adds rewriting to 'self.eval' to allow direct assignment
- if 'obj.eval' is a custom eval, add a passthrough function that calls original (part of fix for webrecorder/pywb#663)
- add check in otherEvalRewrite to ensure string
* script rewrite: add extra { } to avoid potential collision, as per #72

* xhr rewrite for sw:
- import warcio for post-to-get conversion, to ensure consistent implementation
- disable post-to-get conversion for now, seems to no longer be required in chrome!
- convert to sync xhr if not Firefox and print warning -- only FF supports sync xhr at the moment

* build: update rollup, supporting resolving dependencies (eg. warcio)

* bump to 3.3.0
ikreymer added a commit to webrecorder/pywb that referenced this issue Aug 12, 2021
…recorder/wombat#72

eval rewrite: exclude ',eval' as more likely than not causing a false positive, as per #643
update to latest wombat
ikreymer added a commit to webrecorder/pywb that referenced this issue Aug 12, 2021
* eval fix: instead of rewriting to 'WB_wombat_eval', rewrite to 'self.eval' for non-top-level eval
the wombat object will handle rewriting the eval arg on 'self.eval'
tighten rewriting for top-level 'eval', add additional tests
part of fix for #663

* rewrite wrap: add extra {, } to avoid collisions, as suggested in webrecorder/wombat#72
eval rewrite: exclude ',eval' as more likely than not causing a false positive, as per #643

* update to latest wombat 3.3.0 with corresponding fixes
ikreymer added a commit to webrecorder/wabac.js that referenced this issue Aug 13, 2021
- more efficient html parsing: ensure parse5 receives buffers upto 256k
- remove extra buffer cache for raw text, instead set parse5 to keep buffers upto 256k instead of 64k
- remove PassThrough stream, just use existing stream directly
- can stream very large html!

js rewriting: eval() improvements
- update eval() regexs to match pywb
- prefix non-top-level eval with 'self.' instead of 'WB_wombat_', consistent with wombat 3.3.0 and webrecorder/pywb#668
- add extra '{', '}' for rewriting JS, as per webrecorder/wombat#72

jsonp rewriting:
- more lenient check for JSONP, use existing regex, remove second contains check

fuzzy matcher:
- different heurstic for status >200 to avoid negative scores

bump wombat to 3.3.0: disable POST-to-get rewriting, now support in Chrome!

bump to 2.8.0-beta.0
@ikreymer
Copy link
Member

Mostly fixed in 3.3.0 release by implementing the workaround suggested by @ato in #72 (comment)

Other name collisions still possible in theory, but current issue is addressed.

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

No branches or pull requests

2 participants