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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: rest operator produces global variables #13703

Closed
1 task
jakeye-nuvolo opened this issue Aug 25, 2021 · 9 comments
Closed
1 task

[Bug]: rest operator produces global variables #13703

jakeye-nuvolo opened this issue Aug 25, 2021 · 9 comments
Labels
i: question outdated A closed issue/PR that is archived due to age. Recommended to make a new issue

Comments

@jakeye-nuvolo
Copy link

馃捇

  • Would you like to work on a fix?

How are you using Babel?

Programmatic API (babel.transform, babel.parse)

Input code

`export const Event = (function init() {
function getsomething(){
let o = {
'siteIds':122,
'sitename':'test',
'sitecity': 'san fran'
};
return o;
}
const { siteIds, ...rest } =
getsomething();

return {getsomething};
})();

`
reproducible here https://babeljs.io/repl#?browsers=defaults%2C%20not%20ie%2011%2C%20not%20ie_mob%2011&build=&builtIns=false&corejs=3.6&spec=false&loose=false&code_lz=KYDwDg9gTgLgBAYwgOwM7wKIDdjPgXjgAoAzAV2QRgEsU5rlqYiBKOAbwChzKa6BzYDFQQAtkIAWDfqy5x5cADZC4EOITkK4AclRNgASQAmqbQC4AjACYrAGk5ademLgCG489pfpt9x7v0EJgBPcydXZDgSKAjtBy0AXwBuePkoITIoSIgUhNTEFHQOOGdDE1s4ADpq9KKE9Xz5QWExSWlWFPl49JhMyPZmkXEYKWR-ZM4Elg6gA&debug=false&forceAllTransforms=true&shippedProposals=false&circleciRepo=&evaluate=true&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=env%2Ctypescript&prettier=false&targets=&version=7.15.3&externalPlugins=&assumptions=%7B%7D

In v7.15.3 -> the compiled output creates a global variable called _excluded.
in v7.13.17 -> the compiled output does not create a global variable, instead it places the array inline.

Is this expected? is there a way to turn this off and revert to use v7.13.17 behavior?

Multiple scripts will collide with same global variable.

Configuration file name

No response

Configuration

No response

Current and expected behavior

In v7.15.3 -> the compiled output creates a global variable called _excluded.
in v7.13.17 -> the compiled output does not create a global variable, instead it places the array inline.

Is this expected? is there a way to turn this off and revert to use v7.13.17 behavior?

Multiple scripts will collide with same global variable.

Environment

see https://babeljs.io/repl#?browsers=defaults%2C%20not%20ie%2011%2C%20not%20ie_mob%2011&build=&builtIns=false&corejs=3.6&spec=false&loose=false&code_lz=KYDwDg9gTgLgBAYwgOwM7wKIDdjPgXjgAoAzAV2QRgEsU5rlqYiBKOAbwChzKa6BzYDFQQAtkIAWDfqy5x5cADZC4EOITkK4AclRNgASQAmqbQC4AjACYrAGk5ademLgCG489pfpt9x7v0EJgBPcydXZDgSKAjtBy0AXwBuePkoITIoSIgUhNTEFHQOOGdDE1s4ADpq9KKE9Xz5QWExSWlWFPl49JhMyPZmkXEYKWR-ZM4Elg6gA&debug=false&forceAllTransforms=true&shippedProposals=false&circleciRepo=&evaluate=true&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=env%2Ctypescript&prettier=false&targets=&version=7.15.3&externalPlugins=&assumptions=%7B%7D

Possible solution

No response

Additional context

No response

@babel-bot
Copy link
Collaborator

Hey @jakeye-nuvolo! We really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we're a limited number of volunteers, so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant Slack community that typically always has someone willing to help. You can sign-up here for an invite."

@jakeye-nuvolo
Copy link
Author

unexpected output

`"use strict";

Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Event = void 0;
var _excluded = ["siteIds"];

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

var Event = function init() {
function getsomething() {
var o = {
'siteIds': 122,
'sitename': 'test',
'sitecity': 'san fran'
};
return o;
}

var _getsomething = getsomething(),
siteIds = _getsomething.siteIds,
rest = _objectWithoutProperties(_getsomething, _excluded);

return {
getsomething: getsomething
};
}();

exports.Event = Event;`

Expected Output

"use strict";

Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Event = void 0;

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

var Event = function init() {
function getsomething() {
var o = {
'siteIds': 122,
'sitename': 'test',
'sitecity': 'san fran'
};
return o;
}

var _getsomething = getsomething(),
siteIds = _getsomething.siteIds,
rest = _objectWithoutProperties(_getsomething, ["siteIds"]);

return {
getsomething: getsomething
};
}();

exports.Event = Event;

@lightmare
Copy link
Contributor

Isn't that variable module-scoped? I'm wondering:

// how would this be a problem?
var _excluded = ...

// while this isn't?
var Event = ...

@jridgewell
Copy link
Member

I'm assuming OP is using multiple <script src="babel-output.js"></script> on a single page. This includes the JS script modes, and the vars names would be shared as global variables.

However, it's impossible to transform all JS features without injecting some global variables. Eg, tag`foo` must create a var _templateObject in order to work, and that would have the same conflict.

It's possible OP could wrap the outputs in an immediately invoked expression to avoid this:

(function() {
var _excluded = ["siteIds"];
})()

@jakeye-nuvolo
Copy link
Author

Thanks for the responses. This issue arises from our setup actually. We are using babel to transpile typescript back to a 3rd party SaaS platform as javascript files. The final destination of the script files are recompiled into basically a single JS file for the sake of this argument.

Are there ways or options to work around this and keep the original behavior of inline placement of the variables?

Appreciate the help and assistance on this matter.

@jridgewell
Copy link
Member

The final destination of the script files are recompiled into basically a single JS file for the sake of this argument.

If you're combining multiple files into a single one, then this is likely a bug in your build step. Eg, if this was a let excluded = [] and there were multiple files with that, it would throw a syntax error.

Are there ways or options to work around this and keep the original behavior of inline placement of the variables?

Not at the moment. This was done as a performance optimization in #13384.

@asilberschneider
Copy link

I am having exactly the same issue in a very similar setup (multiple files transpiled and used on same page with RequireJS, but also multiple transpiled files which are concatenated afterwards).

@nicolo-ribaudo
Copy link
Member

@asilberschneider Are you using Babel to compile modules to AMD, for RequrieJS?

@asilberschneider
Copy link

asilberschneider commented Sep 6, 2021

@asilberschneider Are you using Babel to compile modules to AMD, for RequrieJS?

Our babel input files are in AMD format already, we use transpilation for new ECMAScript features or proposals and React elements.
"var excluded ..." values overwrite each other when files are loaded with Dojo toolkit AMD loader.

Wrapping the outputs in an immediately invoked expression as proposed by jridgewell would produce a functional workaround most likely though.

@liuxingbaoyu liuxingbaoyu closed this as not planned Won't fix, can't repro, duplicate, stale Nov 10, 2023
@github-actions github-actions bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Feb 10, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 10, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
i: question outdated A closed issue/PR that is archived due to age. Recommended to make a new issue
Projects
None yet
Development

No branches or pull requests

7 participants