Skip to content

Slice Notation (Stage 1)#10357

Closed
JLHwung wants to merge 26 commits intobabel:masterfrom
JLHwung:slice-notation
Closed

Slice Notation (Stage 1)#10357
JLHwung wants to merge 26 commits intobabel:masterfrom
JLHwung:slice-notation

Conversation

@JLHwung
Copy link
Copy Markdown
Contributor

@JLHwung JLHwung commented Aug 20, 2019

This PR has been split into the following PRs:

They should now be reviewed individually instead of here.

@babel-bot
Copy link
Copy Markdown
Collaborator

babel-bot commented Aug 20, 2019

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/11676/

@babel-bot
Copy link
Copy Markdown
Collaborator

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/11350/

@nicolo-ribaudo nicolo-ribaudo requested review from a user and nicolo-ribaudo and removed request for a user August 20, 2019 19:40
@JLHwung JLHwung marked this pull request as ready for review August 22, 2019 19:14
}
var tIsString = isString(t);
var tIsArray = Array.isArray(t);
if (
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is too complicated for a proposal that doesn't have defined semantics yet.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This notation can be used for slice operations on primitives like String and any object that provides indexed access using [[Get]] like Array and TypedArray.

It is used to limit the slicee to string, array and typed array. Surely we can debate about whether we should loose the control here and allow any fancy objects as long as they implement indexed access.

Copy link
Copy Markdown
Member

@jridgewell jridgewell Aug 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That matches array-likes, too, eg { length: 1, 0: 'test' }. Let TypeScript handle type errors.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That matches array-likes, too, eg { length: 1, 0: 'test' }.

Yes, array-like objects is supported.

const obj = { 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 };
obj[1:3];
// → ['b', 'c']

But we should reject the following Proxy exotic object

new Proxy({} , { 
  get(target, prop) {
    if (prop === "length") { return 1 }
    if (prop == 0) { return prop }
    return undefined
  }
});

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any object that provides indexed access using [[Get]]

I think that this means that proxies should be allowed. For example, when using a properly defined proxy, [].slice works:

var obj = new Proxy({} , { 
  get(target, prop) {
    if (prop === "length") { return 1 }
    if (prop == 0) { return 3 }
  },
  has(target, prop) {
    return prop == 0;
  }
});

[].slice.call(obj); // [3]

cc @gsathya What should it do here?


var o;
if (tIsString) {
o = "";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: We can use the array path for this, and join at the end.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My major concern on implementation is memory footprint and performance. We could shorten the helper if we convert string to array, but that means given a string str with length N, str[::M] will require N byte memory while the optimal should be N/M.

if (
!expr ||
expr.type === "NumericLiteral" ||
expr.type === "Identifier" ||
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems super weird that Identifier is allowed, but normal expressions are not. 😞

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I like this design choice. If nested general expression is supported, we can expect pretty nested code and one would easily get confused with ternary operator. Think of

a[
 foo : (
   get_bar_from_qux()
 ) : (
  get_qux_from_quux()
 )
]

Surely we can open an issue on the proposal to discuss this choice.

return this.finishNode(node, "MemberExpression");
}

parseMaybeSliceExpression(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this way much better.

@JLHwung JLHwung added PR: New Feature 🚀 A type of pull request used for our changelog categories Spec: Slice Notation labels Aug 22, 2019
@@ -0,0 +1 @@
a[b:c]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add more tests?

a[b:c];
a[b:c:d]
a[b:];
a[b::];
a[:c];
a[::d];
a[b::d];
a[:];
a[::];

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Addressed in 452c6cd.

expr.operator === "-" &&
(expr.argument.type === "NumericLiteral" ||
expr.argument.type === "Identifier"))
) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need to check that expr.extra && expr.extra.parenthesized is false.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, dogfooding another stage 3 proposal. 😝


parseSliceArgument(): ?N.Expression {
let expr = null;
this.eat(tt.colon);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be this.expect, or be inside an if (this.eat(tt.colon))?
Also please add a test where this expectation is not respected, e.g. foo[1:2;3]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be this.expect

No. Because the colon step part is optional.

In the case of foo[1:2;3], parseExpression will throw unexpected token error since ; could not start an expression.

However, I think you idea of putting parseExpression inside tt.colon check is more reasonable. Once tt.colon is not matched, we should expect ] since it's the end of slice expression. I have added testcase for foo[1:2;3].

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of foo[1:2;3], parseExpression will throw unexpected token error since ; could not start an expression.

What about foo[1:2 3]?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would throw "unexpected token, expected ]" now since parseExpression is not guarded by tt.colon check.

# Conflicts:
#	packages/babel-parser/test/fixtures/experimental/slice-notation/invalid-arg-bigint-literal/input.js
#	packages/babel-parser/test/fixtures/experimental/slice-notation/invalid-arg-bigint-literal/options.json
#	packages/babel-parser/test/fixtures/experimental/slice-notation/invalid-arg-binary-expression/input.js
#	packages/babel-parser/test/fixtures/experimental/slice-notation/invalid-arg-binary-expression/options.json
#	packages/babel-parser/test/fixtures/experimental/slice-notation/invalid-arg-unary-expression-plus/input.js
#	packages/babel-parser/test/fixtures/experimental/slice-notation/invalid-arg-unary-expression-plus/options.json
@JLHwung
Copy link
Copy Markdown
Contributor Author

JLHwung commented Jul 3, 2020

Abandoning this PR due to #10596 (comment)

@JLHwung JLHwung closed this Jul 3, 2020
@JLHwung JLHwung deleted the slice-notation branch July 3, 2020 21:45
@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 Oct 3, 2020
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 3, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

outdated A closed issue/PR that is archived due to age. Recommended to make a new issue PR: New Feature 🚀 A type of pull request used for our changelog categories Spec: Slice Notation umbrella ☂️

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants