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

Need terminology other than "non-strict" for sloppy functions #875

Open
erights opened this issue Apr 6, 2017 · 59 comments
Open

Need terminology other than "non-strict" for sloppy functions #875

erights opened this issue Apr 6, 2017 · 59 comments

Comments

@erights
Copy link

erights commented Apr 6, 2017

At #867 (comment) I wrote:

Precisely speaking, there are three kinds of functions: strict, sloppy, and built-in. I know we are trying to avoid the term "sloppy" in spec language, and I do not argue for it. I agree it sounds too judgemental and informal. But "non-strict" is too misleading because built-in functions are "not strict" but not "non-strict". This is too confusing.

@erights erights changed the title Need terminology other than "non strict" for sloppy functions Need terminology other than "non-strict" for sloppy functions Apr 6, 2017
@getify
Copy link
Contributor

getify commented Apr 7, 2017

loose?

@domenic
Copy link
Member

domenic commented Apr 7, 2017

Sloppy seems fine.

@ljharb
Copy link
Member

ljharb commented Apr 7, 2017

"loose", "legacy", "sloppy" - all have an appropriate judgmental connotation; one echoed by the committee's choice of auto-strict for class and Module code anyways.

Since "sloppy" is the widest known conventional (and precise) term for it, must we still avoid the term?

@getify
Copy link
Contributor

getify commented Apr 7, 2017

@ljharb FWIW I disagree that loose and sloppy are equally judgemental. There's no reasonable situation where calling something sloppy is anything but an insult or criticism. Loose, however, is kind of definitionally opposite of strict, and can mean "more freedom", which is IMO the more appropriate connotation.

Anyway, when I teach JS I use "loose mode" to contrast with "strict mode", but I would never use "sloppy" under any circumstances, just like I don't call code bases "bloated" or "fat".

@syg
Copy link
Contributor

syg commented Apr 7, 2017

I like sloppy. Also I thought being judgmental was the point, since we don't want people to use sloppy features for new code.

@erights
Copy link
Author

erights commented Apr 7, 2017

I am quite pleased at the positive reaction to "sloppy". My qualifications in the first comment are because I thought it would be a non-starter. Given these other reactions, I favor "sloppy".

If we can't get agreement on "sloppy" I think "loose" is fine.

@lars-t-hansen
Copy link
Contributor

"permissive" is perhaps a more precise antonym to "strict" in the sense we're using it. ("sloppy" connotes carelessness, and "loose" is itself a loose term.)

@ljharb
Copy link
Member

ljharb commented Apr 7, 2017

"permissive" imo makes it sound too good - strict mode should be encouraged, even if we don't want to actively discourage sloppy mode (more than we already are, of course, both in the spec and in the best practices of the majority of the JS community).

@rossberg
Copy link
Member

rossberg commented Apr 7, 2017 via email

@brabalan
Copy link
Contributor

brabalan commented Apr 7, 2017

I like "sloppy", but how about "legacy"?

@allenwb
Copy link
Member

allenwb commented Apr 7, 2017

I don't think that Mark's original premise and classification of functions is really correct.

The terms "strict function" and "non-strict function" are defined in 9.2 as concepts that are only applicable to functions objects that when called evaluate ECMAScript.

The specification also allows for the possibility of an implementation exposing exotic function objects that when called do something other than evaluating ECMAScript code. Such exotic functions are neither strict or non-strict because they don't have any ECMAScript code that the strict-mode code rules could be applied to.

9.3 allows built-in functions to implemented as either strict ECMAScript function objects or as implementation provided kind(s) of exotic function object. A built-in function may never be a non-strict ECMAScript function.

So, "strict function", "non-strict function", and "built-in function" do not describe disjoint sets.

I don't really understand the source of confusion as while a built-in might be implemented as a strict function it can never be a non-strict function. I don't see how replacing "non-strict" with some other term would be any more or less confusing or misleading.

@rossberg
Copy link
Member

rossberg commented Apr 7, 2017 via email

@anba
Copy link
Contributor

anba commented Apr 7, 2017

That is to say, I agree with Mark's premise.

Mark said:

But "non-strict" is too misleading because built-in functions are "not strict" but not "non-strict".

But as Allen explained above, the 'not "non-strict"' part is incorrect per https://tc39.github.io/ecma262/#sec-ecmascript-function-objects:

An ECMAScript function object whose code is strict mode code is called a strict function. One whose code is not strict mode code is called a non-strict function.

If a built-in function is implemented as an ECMAScript function object, it must be a "strict function" (https://tc39.github.io/ecma262/#sec-built-in-function-objects). If it's not implemented as an ECMAScript function object, it's still not a "non-strict function", because that classification only applies to ECMAScript function object.
So a built-in function can be a "strict function", but it's never a "non-strict function".

@rossberg
Copy link
Member

rossberg commented Apr 7, 2017 via email

@erights
Copy link
Author

erights commented Apr 7, 2017

I very much want to agree with @rossberg-chromium 's conclusion --- that there is no observable difference, and therefore it has no place in the normative spec language.

Unfortunately I see one possible exception: What would Function.prototype.toString.call(aBuiltinImplementedAsStrictJS) print? As the spec currently reads, it could print either way. Instead I would like to require all built-ins to print the way built-ins in general print, in which case built-ins would observably be neither strict nor sloppy.

@littledan
Copy link
Member

+1 to "sloppy"

Tangent, but FWIW, I think it'd be great if the ECMAScript spec made it clear (even in a note) that it exposes functions that could be exposed as strict mode JS code. This seems to have been a design goal of the spec that it's currently adhering to, and the more consistency, the easier it is to reason about, both for users and implementers.

@claudepache
Copy link
Contributor

Since the notion of strictness applies specifically to so-called ECMAScript Function Objects, we could say “strict ECMAScript function” and “non-strict ECMAScript function”.

Or we could ban the “(non-)strict function” terminology, and refer instead to the [[Strict]] internal slot of ECMAScript Function Objects instead.

@jmdyck
Copy link
Collaborator

jmdyck commented Apr 7, 2017

I don't see how replacing "non-strict" with some other term would be any more or less confusing or misleading.

The term "non-strict function" suggests the complement of "strict function". While this is correct within the domain of 'ECMAScript function objects', it is not correct within the domain of (all) function objects. So a different term, that does not make this suggestion, would be less misleading. (Is the point of this issue.)

@michaelficarra
Copy link
Member

👍 sloppy

@allenwb
Copy link
Member

allenwb commented Apr 7, 2017

@erights says:

that there is no observable difference, and therefore it has no place in the normative spec language.
Unfortunately I see one possible exception: What would ...

The possible observable differences currently only relate to the set of own properties that a built-in property exposes. There is nothing currently in the spec. (except for the forbidden extensions) that restrict an implementation from defining additional properties on exotic built-ins. And it's not clear that there should be.

@allenwb
Copy link
Member

allenwb commented Apr 7, 2017

What is the utility of defining "sloppy" (or any other term) as meaning "any function object that is not a strict mode ECMAScript function". Where is does that concept useful and exactly how does it characterize the set of function it applies to?

For example, it would be unhelpful for it to mean that "strict mode" restrictions and alternative semantics do not apply to such functions. All of those restrictions relate to the validity and semantics of actual ECMAScript code. Most of those restrictions (can't use with, no legacy octal constants, etc.) are simply irrelevant to exotic functions that are not defined in terms of ECMAScript code. Others, such as the binding of this when undefined is passed are also relate to the interpretation of ECMAScript code, but similar effects are explicitly specified for each built-in function (that might not be implemented as an ECMAScript function).

The terms "strict function", "non-strict function", and "built-in function" are all precisely defined and (I believe) consistently used within the actual specification. Any confusion about the meaning of spec. text using those terms probably comes from readers making incorrect assumptions about the meaning of the term. But any alternative terms (such as "sloppy") would also be subject to similar misinterpretation. So, what is the specification benefit to changing the terminology.

Outside the specification, in the real world, where would "sloppy" be used with any mean other than exactly the one currently defined in 9.2? BTW, this isn't a rhetorical question. I'm really interested in knowing if there are any real-world situations where is it useful to talk about the set consisting of all functions (including non-ECMAScript functions) that are not defined using strict mode ECMAScript code?

BTW-2, I'm moderately ok with the colloquial meaning of "sloppy function" and occasionally use it myself. I just don't see how introducing it into the actual specification adds any value.

@leobalter
Copy link
Member

I'm ok with sloppy as we already use it conventionally.

Getting feedback from coworkers we also agreed "relaxed" would be a nice naming that is not judgemental and probably accurate to the spec.

@jmdyck
Copy link
Collaborator

jmdyck commented Apr 7, 2017

What is the utility of defining "sloppy" (or any other term) as meaning "any function object that is not a strict mode ECMAScript function"?

I don't think anyone is proposing to do that. Rather, I believe people are suggesting a replacement for "non-strict" in the phrase "non-strict function", with no change in meaning.

(For consistency, we might also want to make the same change, if any, in the phrase "non-strict code".)

@rossberg
Copy link
Member

rossberg commented Apr 7, 2017

@allenwb, being precisely specified doesn't imply not being confusing or conflating concerns. ;)

The suggestion is to tweak the definitions such that:

  • "strict function" = ECMAScript function with strict code
  • "sloppy function" = ECMAScript function with non-strict (= sloppy) code
  • built-in function = exotic function defined by the spec

This way they are cleanly disjoint and any confusion (and implementation dependency!) about what built-ins the strict-vs-non-strict labels include is avoided.

That implementations may choose to implement some exotic functions with the same internal(!) representation as ECMAScript functions is fine, but nothing that the normative text has any business being concerned about.

@allenwb
Copy link
Member

allenwb commented Apr 7, 2017

@jmdyck but any replacement for "non-strict function" that does not explicitly include some negation of the word "strict" is masking the essential difference between those two kinds of ECMAScript functions.

If the concern is that it isn't obvious that the strict/non-strict distinction is only applicable to ECMAScript functions then to remediate that I suggest replacing in the spec. all occurrences of "strict function" with "strict ECMAScript function" and "non-strict function" with "non-strict ECMAScript function". It's wordier but more explicit.

@rossberg-chromium You are suggesting that 1) built-ins must appear to be exotic and 2) if an implementation wants to uses an ECMAScript function to implement a built-in then it must come up with someway to mask that fact. The ability to self-host builtin using ECMAScript was one of the explicit ES6 goals. The current specification language allows that without additionally requiring that an implementation make the extra effort to do such masking.

In my ideal word most built-ins would be directly implemented as ECMAScript functions. Why do we want to make it harder for implementations to do that?

@ljharb
Copy link
Member

ljharb commented Apr 7, 2017

Why does "may be exotic" obligate implementations to make them exotic?

@erights
Copy link
Author

erights commented Apr 7, 2017

any replacement for "non-strict function" that does not explicitly include some negation of the word "strict" is masking the essential difference between those two kinds of ECMAScript functions.

Whenever I see terminology "ADJ NP" for some adjective and noun, and "non-ADJ NP" I assume this is a complete disjoint partitioning of the set under discussion. In this case, we have three leaf categories:
* strict
* sloppy
* built-in

For my purposes, the distinction I most often need to refer to is between sloppy functions and non-sloppy functions. IOW, I often find the need for the two-way distinction that does not distinguish between strict and sloppy. Speaking in terms of today's terminology, I am left with "non-strict" and "not non-strict". Yuck!

If the concern is that it isn't obvious that the strict/non-strict distinction is only applicable to ECMAScript functions then to remediate that I suggest replacing in the spec. all occurrences of "strict function" with "strict ECMAScript function" and "non-strict function" with "non-strict ECMAScript function". It's wordier but more explicit.

That is a valid way to put the concern. Your suggestion for fixing it is logically fine but is indeed much too verbose. In fact it is so verbose that people will inevitably shorten it in conversation and in non-spec documents about the spec back to "strict function" and "non-strict function". I have already been in many conversations with experienced tc39 committee members where I used "non-strict functions" to mean sloppy functions and they thought I was talking about all functions other than strict functions.

Another possible way to slice this is by making the two distinctions that are already in our vocabulary, but redefining them so they are cross cutting:

  • built-in function vs ECMAScript function
  • strict function vs non-strict function

Where we include built-in functions in the strict category. This would shift our terminology as follows:

Today

  built-in ECMAScript
not non-strict built-in strict
non-strict prohibited non-strict

Simple Proposal

  built-in ECMAScript
non-sloppy built-in strict
non-strict prohibited sloppy

Cross-Cutting Proposal

  built-in ECMAScript
strict built-in strict ECMAScript
non-strict prohibited non-strict ECMAScript

After laying this out, I still prefer "Simple Proposal" to "Cross-Cutting Proposal". In fact I prefer it even more. This is a case where orthogonality would subtract value.

@erights
Copy link
Author

erights commented Apr 7, 2017

Much of this boils down to a factual question we should be able to derive from the spec: Other than the behavior of Function.prototype.toString, are there any other observable differences between strict ECMAScript functions and built-in non-ECMAScript functions?

@erights
Copy link
Author

erights commented Apr 7, 2017

permissive
relaxed

Say that the opening line of a novel were "Alice is permissive. Bob is strict. Carol is relaxed. Dave is sloppy." Nevermind that it would probably be a terrible novel I should put down immediately. If I did read on, the rank order of who I would expect to like would be

  1. Relaxed Carol
  2. Permissive Alice
  3. Sloppy Dave
  4. Strict Bob

There is nothing objective about my reactions. Introspectively, ask yourself the same question.

If I could come up with a short clear acceptable word with worse connotations than "strict" I would. Of the short clear acceptable words, the one with the worst connotations so far is "sloppy". Many people, including myself, on first hearing even the "strict" vs "sloppy" distinction may still misunderstand that "sloppy" is likely to be the one they will be happier using. At least "sloppy" produces less bias in that direction than any of the alternatives so far.

(I wish that we could, at the same time, rename "strict" to "neat". But we cannot.)

@allenwb
Copy link
Member

allenwb commented Apr 7, 2017

From the spec., I believe the only observable differences is the behavior of Function.prototype.toString behavior. However, the non-standard legacy addition to caller and arguments potentially make the distinction between strict ECMAScript functions and non-strict ECMAScript functions.

I'm still puzzled about when anybody other than Mark (who has specific security concerns he needs to talk about) needs to talk about "strict"/"sloppy" distinction for anything other than ECMAScript functions. I appreciate the important distinction in the forbidden extensions spec. text, but does any real JS dev ever need to think about how a built-in is implemented. Does a JS dev ever need to think about the "strict"/"sloppy" distinction other than when they are talking looking at the source of an actual ECMAScript function.

@erights
Copy link
Author

erights commented Apr 7, 2017

However, the non-standard legacy addition to caller and arguments potentially make the distinction between strict ECMAScript functions and non-strict ECMAScript functions.

That is indeed the issue under current debate at #867 . As I read that thread, my impression is that we're in agreement that all strict and built-in functions, with the possible exception of Function.prototype, must be born in an initial state in which these are absent. If that is indeed the conclusion, then we would not find any observable difference there. IOW, I expect us to agree that an implementation is only able to endow sloppy functions with these horrible magic properties.

@ljharb
Copy link
Member

ljharb commented Apr 7, 2017

Wouldn't borrowing a builtin prototype method and .call(null) make its behavior potentially different for strict-like and sloppy-like builtin functions? (Let's say I did window.length = 0; first)

@allenwb
Copy link
Member

allenwb commented Apr 7, 2017

@ljharb no, because all standard built-ins are specified such that they handle the this argument similarly to a strict ECMAScript function. (note that as of ES5, the replacement of null/undefined with the global object happens on the callee side rather than the caller side.)

@erights
Copy link
Author

erights commented Apr 7, 2017

@allenwb asks

I'm still puzzled about when anybody other than Mark ... needs to talk about "strict"/"sloppy" distinction for anything other than ECMAScript functions.

And then, without irony, immediately afterwards @allenwb states:

note that as of ES5, the replacement of null/undefined with the global object happens on the callee side rather than the caller side

That replacement, magically revealing the global, is only done by sloppy functions. It is never done by either strict or built-in functions. All built-ins, called with a null value for their this-argument, either:
* ignore it
* use the null
* throw
All these are unsurprising behaviors for strict functions as well.

@allenwb
Copy link
Member

allenwb commented Apr 7, 2017

Mark, I guess I miss why my second statement could be seen as ironic? The fact that the algorithmic specifications of the built-ins handle null this values in an manner that enable their implementation using a strict function is certainly not an accident. What's important is what they actually do with those null values similarly to what you just enumerated. But those behaviors aren't a strict/sloppy distinction.

@erights
Copy link
Author

erights commented Apr 8, 2017

But those behaviors aren't a strict/sloppy distinction.

You asked about what users need to talk about and think about. To a user trying to reason about what the language does, it is an oddball fact that sloppy functions might magically produce the global object. Likewise, only sloppy functions retain the oddball legacy caller/arguments behaviors. The simplest user model for understanding the implications of the three different kinds of functions is to group built-in and strict together, distinguishing these from the oddball: sloppy functions. Sloppy functions have magical oddball behaviors inviting trouble. Better to avoid them and program only with built-ins and strict. (With difficulty, I restrain myself from suggesting "oddball" as an alternative to "sloppy".)

If you want to expand the "strict" category to include built-ins, I would be sympathetic, as in the cross-cutting proposal above. Then "sloppy" could be called "non-strict" without confusion. But I still prefer the Simple Proposal.

@domenic
Copy link
Member

domenic commented Apr 8, 2017

@allenwb

1) built-ins must appear to be exotic and 2) if an implementation wants to uses an ECMAScript function to implement a built-in then it must come up with someway to mask that fact. The ability to self-host builtin using ECMAScript was one of the explicit ES6 goals. The current specification language allows that without additionally requiring that an implementation make the extra effort to do such masking.

Can you explain what masking would be required? What observable consequences would them being exotic include?

@ljharb
Copy link
Member

ljharb commented Jan 3, 2020

@erights the title of the issue seems to be answered; but it seems like #875 (comment) is still a change you'd like to make. If so, would you be able to put together a PR?

@allenwb
Copy link
Member

allenwb commented Jan 3, 2020

I still object to #875 (comment) as I believe it muddling the fact that strictness/non-strictness is only defined as a characteristic of ECMAScript functions.

The ES spec does not place any requirements upon what implementation language may be used for built-in functions other than that if an ECMAScript function is used to implement a built-in then it must be strict-mode ECMAScript function. This requirement exists because strict ECMAScript functions have a number of specific characteristics and a few of them (such an the interpretation of undefined passed the this value) are also requirements for built-ins.

But most of the characteristics of strict-mode ECMAScript functions, such as whether a with statement may used are irrelevant to built-ins and in particular are meaningless if the built-in's implementation language is not ECMAScript.

If the consensus is that the meaning of strict/non-strict still needs further clarification then I suggest following my suggestion from #875 (comment) :

If the concern is that it isn't obvious that the strict/non-strict distinction is only applicable to ECMAScript functions then to remediate that I suggest replacing in the spec. all occurrences of "strict function" with "strict ECMAScript function" and "non-strict function" with "non-strict ECMAScript function". It's wordier but more explicit.

@jmdyck
Copy link
Collaborator

jmdyck commented Jan 3, 2020

@allenwb:

I still object to #875 (comment)

That's your own comment (the same one you quote from later), so I'm doubtful that it's the one you object to.

@allenwb
Copy link
Member

allenwb commented Jan 3, 2020

@jmdyck
corrected, now reverences #875 (comment)

@erights
Copy link
Author

erights commented Jan 3, 2020

I don't understand what you're objecting to or proposing. Is it just a renaming? Why use the confusing term "non-strict ECMAScript function" instead of "sloppy ECMAScript function"? Only an ECMAScript function can be sloppy, so non-sloppy would unambiguously include both "strict ECMAScript function" and "builtin function".

Alternatively, if we just include builtin functions in the "strict" category, then we have

  • strict functions
    • strict ECMAScript functions
    • builtin functions
  • non-strict ECMAScript functions.

Since the distinction I usually need is between sloppy and non-sloppy, by including builtins in the strict category, we could indeed use "strict function" vs "non-strict function" to label the same difference. But we need to do this clearly and immediately, because today "non-strict function" would seem to include builtin functions, which is a fatal mistake.

See https://github.com/Jack-Works/proposal-strict-built-in-functions
Attn @Jack-Works

@allenwb
Copy link
Member

allenwb commented Jan 3, 2020

@erights
I have two objections.

  1. "sloppy" implies a value judgement that is not appropriate or necessary to include in an international standard.

The ECMAScript specifications uses various categorization to help in specifying the semantics of the language. But value judgements are irrelevant to those semantics. In addition, the categorization
strict ECMAScript function/non-strict ECMAScript function is more precise than the categorization strict ECMAScript function/sloppy ECMAScript function. It seems clear that the first categorization covers all ECMAScript functions while the second categorization leaves open the possibility that there may be ECMAScript functions that are neither strict or sloppy.

  1. "Strict mode" is a useful way to distinguish the two alternative ways that an ECMAScript functions maybe parsed and associated with static and runtime semantics. "Strict mode" has never been defined for non-ECMAScript functions. Attempting to expand the category "strict functions" to include non-ECMAScript functions dilutes the useful of the strict/non-strict categorization of ECMAScript functions.

From its inception, "strict mode" has been about the interpretation of the source code of ECMAScript functions and scripts. Different subsets of the possible grammar productions and semantics rules are applied to the processing of ECMAScript code depending upon whether that code is "strict" or "non-strict". Annex C enumerates (but it isn't clear whether it has been kept update to date) these rules and it is easy to see that they are meaningful for ECMAScript functions but few, if any, could be applicable to functions that are not implemented using ECMAScript.

Turing the question around, what would be the list of requirements that a "strict" non-ECMAScript functions needs to meet? This list will undoubtably be different from Annex C. If that is the case what is the value in applying the term "strict" to both? Is there a need for a term that refers to the intersection of those two lists?

I agree that there have been a few cases that came later where we were sloppy and applied a more expansive (and unspecified) meaning to "strict". @Jack-Works' proposal addresses one of these situations:

If an implementation extends any function object with an own property named "caller" the value of that property, as observed using [[Get]] or [[GetOwnProperty]], must not be a strict function object. If it is an accessor property, the function that is the value of the property's [[Get]] attribute must never return a strict function when called.

He proposes changing the definition of "strict function" so that the phrase "must not be a strict function" can be read as meaning "must not be a strict ECMAScript function or a built-in function".

My suggestion is to leave the definition of "strict function" alone and simply substitute the phrasing I used in the preceding paragraph to explain its meaning. Similar phrasing could be using an any similar occurrences, if there are any.

Finally, it is apparent that some readers have missed the intention that "strict function"/"non-strict function" always is in reference to an ECMAScript function. To remediate this, in #875 (comment) I suggest systematically replacing all occurrences of those phrases with "strict ECMAScript function" and "non-strict ECMAScript function".

@allenwb
Copy link
Member

allenwb commented Jan 3, 2020

Follow-up to #875 (comment)

I forgot to include that it isn't clear that either the @Jack-Works change to Forbidden Extensions or my alternative is web compatible as they both expand the specified set of functions that must censor what they return from their caller method, if they have one.

@erights
Copy link
Author

erights commented Jan 3, 2020

It is web compat. Old browsers generally already censor this.

@erights
Copy link
Author

erights commented Jan 3, 2020

"sloppy" implies a value judgement that is not appropriate or necessary to include in an international standard.

Fine. Then choose a term other than "sloppy" or "non-X" for any X. It is the "non-X" phrasing than makes it impossible to speak clearly.

@allenwb
Copy link
Member

allenwb commented Jan 3, 2020

@erights
I'm perfectly happy for you to speak the term "sloppy" as long as the listener understands that it means the same things as "non-strict". I just don't think that term belongs in the specification (which generally isn't recited).

The other issue is that with phrases like "a foo bar" and "a non-foo bar" it is clear that the set of bars is fully covered. Such coverage is not at all obvious with "a foo bar" and "a baz bar".

@erights
Copy link
Author

erights commented Jan 3, 2020

The other issue is that with phrases like "a foo bar" and "a non-foo bar" it is clear that the set of bars is fully covered. Such coverage is not at all obvious with "a foo bar" and "a baz bar".

This makes no sense to me when we need to speak about three categories.

@erights
Copy link
Author

erights commented Jan 3, 2020

Come up with a normative term other than "sloppy" or "non-strict". Otherwise, I suggest we proceed with "sloppy". A "non-X" for a label in a three way taxonomy is unacceptable.

@allenwb
Copy link
Member

allenwb commented Jan 3, 2020

This makes no sense to me when we need to speak about three categories.

But with regard to "strict mode" we are not talking about three categories. As I said:

From its inception, "strict mode" has been about the interpretation of the source code of ECMAScript functions and scripts.

From that perspective, "strict" defines two categories that covers the set of all ECMAScript functions. What you seem to be trying to do is to repurpose (or reinterpret) the "strict" category to define a subset of the set of all functions (probably more precisely the set of call callable objects). That destroys the simple utility of "strict" as a binary categorization of ECMAScript functions.

To further quote myself:

what would be the list of requirements that a "strict" non-ECMAScript functions needs to meet?

and what name would you give to that subset of the callables? It presumably is a superset of the category "strict ECMAScript functions as ECMAScript function is a subset of all callables.

@ljharb
Copy link
Member

ljharb commented Jan 3, 2020

For a non-ECMAScript function, is there anything you can observe that would make it non-strict? If not, what's wrong with saying "everything is strict except sloppy ecmascript functions"? (or "non-strict")

@allenwb
Copy link
Member

allenwb commented Jan 3, 2020

@ljharb

I'm essentially asking @erights to defined what observable characteristic of a non-ECMAScript function would make it "non-strict" according to his interpretation of "strict". It isn't clear which, if any, of the item (or their negation) in Annex C apply.

@devsnek
Copy link
Member

devsnek commented Jan 3, 2020

I'm pretty sure the only visible item in annex C for built-ins would be the "caller" and "arguments" properties.

@erights
Copy link
Author

erights commented Jan 3, 2020

I'm pretty sure the only visible item in annex C for built-ins would be the "caller" and "arguments" properties.

The caller and arguments properties are indeed my concern. They have been a core concern since we first worked together to define ES5. The security guarantees follow from censoring them on all functions other than sloppy ECMAScript functions. Both in terms of poisoning, and in terms of censoring the revelation of callers. The security guarantees follow from the ability to prohibit admission of sloppy ECMAScript functions, which is why we have a "use strict"; and no "use sloppy"; or "use non-strict"; or anything to turn off a "use strict";. Going back to Caja in the ES5 era, all implementations of SES or anything like SES made use of this to prohibit the introduction of sloppy ECMAScript code.

If builtin functions expose caller or arguments, or are exposed to caller, then all these SES-like systems would be insecure.

Thus, the reasoning depends on a further abstract grouping: strict ECMAScript functions and builtin functions follow ocap principles. They have no spooky action-at-a-distance. Sloppy ECMAScript functions behave in spooky ways that threaten security, and so must be quarantined.

Hence https://github.com/Jack-Works/proposal-strict-built-in-functions

@erights
Copy link
Author

erights commented Jan 3, 2020

@erights
Copy link
Author

erights commented Jan 3, 2020

Regarding your desire for binary X vs non-X terminology, notice that if we had a simple name for "sloppy", then we wouldn't need a name for "strict". The two remaining categories would be "builtins" and "non-sloppy ECMAScript functions". The term "non-sloppy functions" would, without ambiguity, refer to both of those other categories together.

@allenwb
Copy link
Member

allenwb commented Jan 4, 2020

The caller and arguments properties are indeed my concern.

As I thought. So, if you say built-ins (including non-ECMAScript built-ins) must be "strict" that means you are really talking about only one out of the seventeen listed requirements of strict-mode functions in Annex C and doing so without explicitly identifying the requirement that concerns you. That requirement is:

An implementation may not extend, beyond that defined in this specification, the meanings within strict functions of properties named "caller" or "arguments" of function instances.

It is far from clear what "extend, beyond that defined in this specification, the meanings ... of properties named caller or arguments of function instances" actually is supposed to mean —particularly for non-ECMAScript functions (sorry, I know I'm partially responsible for this text). Also, it only applies to the explicitly named properties (caller and arguments) so it does not restrict somebody defining violating your OCAP concerns by defining a built-in with, for example, a Caller property that reveals without restriction the actual last caller of the function.

I think you will be better-off being explicit about what you really meaning rather than depending upon the poorly stated last item in Annex C. For example, building upon your "es legacy function proposal" we might call functions that are restricted in the manner you care about "non-leakable functions" (or perhaps OCAP functions if you prefer). The prose definition of non-leakable function might be: A callable object that does not expose any properties whose access directly or indirectly exposes a non-leakable caller of the the object.

Then we could say that built-in functions must be non-leakable functions and that strict ECMAScript function are also non-leakable functions.

You might even go as far as saying that all callable objects, with the exception of non-strict ECMAScript functions, must be non-leakable functions. This would cover a concern about the meaning of "built-in function" that I will address in a separate message.

@allenwb
Copy link
Member

allenwb commented Jan 4, 2020

About built-ins

4.3.9 defines "built-in object" as:

object specified and supplied by an ECMAScript implementation

and 4.3.32 says that a "built-in function" is a built-in object that a built-in function.

9.3 further clarifies this as:

The built-in function objects defined in this specification may be implemented as either ECMAScript function objects (9.2) whose behaviour is provided using ECMAScript code or as implementation provided function exotic objects whose behaviour is provided in some other manner. In either case, the effect of calling such functions must conform to their specifications. An implementation may also provide additional built-in function objects that are not defined in this specification. (emphasis added)

Does the set of all functions consist exclusively of built-in functions and ECMAScript functions (and callable Proxy objects)? What about functions that are not specified and supplied by an ECMAScript implementation —for example, C functions invoked via an implementation specific foreign-function interface or an imported module containing functions defined using WASM?

It seems to me that these definitions are just not precise or inclusive enough to base any OCAP guarantees upon.

@claudepache
Copy link
Contributor

Ideally, it should not be detectable from outside whether a function is implemented in strict ES, sloppy ES, C++, or TeX. AFAICS, the only occasion where we’ve needed such an externally observable distinction, is for limiting the power of Function#caller and Function#arguments (currently via the “Forbidden extensions” clause), because it wasn’t reasonable to outright disable them for existing code. I think that, if the neutering of those legacy features is made correctly, we won’t ever need to make any further observable distinction, and therefore to give names.

(Even, the operation “IsLeakableFunction” used in https://github.com/claudepache/es-legacy-function-reflection is intended to be used only in the scope of that proposal; therefore I’m considering to give it a less generic name, like “IsAllowedTargetForThoseTwoLegacyBlunders”. BTW, the proposal contains a second – unnamed – dichotomy distinct from IsLeakableFunction, namely: whether a function may be returned by .caller.)

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