Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix($parse): Preserve expensive checks when runnning $eval inside an expression #13850

Closed
wants to merge 1 commit into from

Conversation

lgalfaso
Copy link
Contributor

When running an expression with expensive checks, there is a call to $eval or $evalAsync
then that expression is also evaluated using expensive checks

@gkalpak
Copy link
Member

gkalpak commented Jan 26, 2016

Aren't $watch and $watchCollection also affected ?
LGTM otherwise.

@lgalfaso lgalfaso force-pushed the parse-expensive-eval branch from b8a785b to 157e9e7 Compare January 26, 2016 14:48
@gkalpak
Copy link
Member

gkalpak commented Jan 26, 2016

So, this works for $$postDigest(), $apply(), $watch() and $watchCollection(), but it doesn't seem to work for $applyAsync().

I would still add tests for all of those (better safe than sorry 😃). E.g.:

scope.foo = {w: $window};

expect(function() {
  scope.$eval($parse('$$postDigest($eval("foo.w && true"))', null, true));
}).toThrow();
expect(function() {
  scope.$eval($parse('$apply("foo.w && true")', null, true));
}).toThrow();

expect(function() {
  scope.$eval($parse('$applyAsync("foo.w && true")', null, true));
  scope.$digest();
}).toThrow();
expect(function() {
  scope.$eval($parse('$watch("foo.w && true")', null, true));
  scope.$digest();
}).toThrow();
expect(function() {
  scope.$eval($parse('$watchCollection("foo.w && true", $eval)', null, true));
  scope.$digest();
}).toThrow();


function expensiveChecksInterceptor(fn, expensiveChecks) {
if (!expensiveChecks) return fn;
return function expensiveCheckFn(scope, locals, assign, inputs) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Won't this break $$watchDelegate and inputs on fn?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jbedard you are right, this needs more work

@jbedard
Copy link
Collaborator

jbedard commented Jan 26, 2016

How about disallowing execution of nested $parseed statements. Would that be an option?

@lgalfaso
Copy link
Contributor Author

How about disallowing execution of nested $parseed statements. Would that be an option?

That would be too big of a breaking change

@jbedard
Copy link
Collaborator

jbedard commented Jan 26, 2016

People actually do that? I've never even thought of it. Unless there is a less obvious way that I haven't thought of...

@lgalfaso lgalfaso force-pushed the parse-expensive-eval branch 2 times, most recently from 2add0ce to 39ecc9a Compare January 27, 2016 10:05
@lgalfaso
Copy link
Contributor Author

Updated the PR and fixed the comments. PTAL

@lgalfaso lgalfaso force-pushed the parse-expensive-eval branch 2 times, most recently from d529115 to 0e7bdaa Compare January 27, 2016 10:50
@@ -1788,6 +1797,7 @@ function $ParseProvider() {
}
cache[cacheKey] = parsedExpression;
}
parsedExpression = expensiveChecksInterceptor(parsedExpression, expensiveChecks);
Copy link
Member

Choose a reason for hiding this comment

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

Couldn't we move this inside the if-block ?

Copy link
Member

Choose a reason for hiding this comment

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

Also, this would hide properties like assign, constant, inputs and literal.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, wouldn't it make sense to cache the parsedExpression that has already had the expensive checks interceptor added, if the cache is cacheExpensive?

Copy link
Member

Choose a reason for hiding this comment

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

Actually, that's what I meant by "move this inside the if-block". (Inside and before cache[cacheKey] = parsedExpression.)
Thx for making it clear, @petebacondarwin 😃

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, this would hide properties like assign, constant, inputs and literal

Given that the expensive checks is a private API, I think this is not an issue. Anyhow, made the change.

Couldn't we move this inside the if-block ?

Yep :)

@lgalfaso lgalfaso force-pushed the parse-expensive-eval branch 2 times, most recently from 997a7fd to 58e4014 Compare January 27, 2016 13:21
@petebacondarwin
Copy link
Contributor

LGTM

…expression

When running an expression with expensive checks, there is a call to `$eval` or `$evalAsync`
then that expression is also evaluated using expensive checks
@lgalfaso lgalfaso force-pushed the parse-expensive-eval branch from 58e4014 to 5dbd8de Compare January 27, 2016 13:56
@lgalfaso lgalfaso closed this in acfda10 Jan 27, 2016
@@ -1387,7 +1387,7 @@ describe('Scope', function() {
expect(child.log).toBe('child context');
}));

it('should operate only with a single queue across all child and isolate scopes', inject(function($rootScope) {
it('should operate only with a single queue across all child and isolate scopes', inject(function($rootScope, $parse) {
var childScope = $rootScope.$new();

Choose a reason for hiding this comment

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

Hi

@gkalpak
Copy link
Member

gkalpak commented Jan 28, 2016

@petebacondarwin, should this (and #13871) be backported to v1.4.x ?

@petebacondarwin
Copy link
Contributor

@gkalpak - yes I would say so. Please do make it happen :-)

gkalpak pushed a commit that referenced this pull request Jan 28, 2016
…expression

When running an expression with expensive checks, there is a call to `$eval` or `$evalAsync`
then that expression is also evaluated using expensive checks

Closes: #13850
@gkalpak
Copy link
Member

gkalpak commented Jan 28, 2016

Backported to v1.4.x as 96d62cc.

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

Successfully merging this pull request may close these issues.

6 participants