-
Notifications
You must be signed in to change notification settings - Fork 175
refactor(env): Extract Prototypes into separate files #1100
refactor(env): Extract Prototypes into separate files #1100
Conversation
dc5ddf3
to
7699daa
Compare
860d686
to
c73f107
Compare
a96397f
to
89c3b3c
Compare
663d1a9
to
828dd58
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you ExE-Boss! This is something that I realized I wanted to do after my big patch had been reviewed. But I never made the time to get back to it.
I have not reviewed the comments (and the types in particular) that you've added. And as we've discussed before, since this project is not configured to use a type checker, we can't guarantee that the functions will always be used in a way that is consistent with the types you've declared.
One of the reasons that I wanted to make this change is to get all the untested API code out of environment.js and move it all to the api/ subdirectory. So I'd be really interested to see how this patch affects the output of npm run test-coverage
Github does not make it easy to review a change like this that splits one file up into multiple pieces: it ends up looking like lots of new code to review. Can you confirm that all you did was split the *Prototype objects into separate modules and add comments? Were there any code changes involved?
Overall this looks great. I've made a couple of minor suggestions, and I'll be happy to merge this after you make those changes. (That is assuming you haven't made code changes to any of the API functions)
The issue with By moving it to the I’ve modified the code so that relative |
* @return {string} | ||
*/ | ||
function encode(str) { | ||
return encodeURI(str); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be changed to call encodeURIComponent(…)
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it would be safe to make that change. It probably should have been written that way to begin with, but any change now risks changing what appears on developer.mozilla.org and I don't want to risk that since we don't have a way to test that API changes here don't affect the output on any of the thousands of MDN document, I'm very very reluctant to change anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In wiki.tree(…)
: chunkify(…)
, alpanumForward(…)
and alphanumBackward(…)
are getting type errors from tsc
:
|
||
while ((i = (j = t.charAt(x++)).charCodeAt(0))) { | ||
var m = i == 46 || (i >= 48 && i <= 57); | ||
if (m !== n) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error TS2367: This condition will always return 'true' since the types 'boolean' and 'number' have no overlap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this code was a port of a C algorithm, and n=0
above was intended to be n=false
? Maybe the !== should have been a !=
But again, unless we can point to a specific content bug that is being caused by this, I don't want to go changing this legacy code for fear of causing unexpected changes to the output.
var m = i == 46 || (i >= 48 && i <= 57); | ||
if (m !== n) { | ||
tz[++y] = ''; | ||
n = m; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error TS2322: Type 'boolean' is not assignable to type 'number'.
if (aa[x] !== bb[x]) { | ||
var c = Number(aa[x]), | ||
d = Number(bb[x]); | ||
if (c == aa[x] && d == bb[x]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error TS2367: This condition will always return 'false' since the types 'number' and 'string' have no overlap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's just not true. (1 == "1")
evaluates to true in JavaScript
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this code is so old and untyped that it is not possible to apply type analysis to it without a complete rewrite. And rewrites are off the table.
if (aa[x] !== bb[x]) { | ||
var c = Number(aa[x]), | ||
d = Number(bb[x]); | ||
if (c == aa[x] && d == bb[x]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error TS2367: This condition will always return 'false' since the types 'number' and 'string' have no overlap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't mind, please put globalsAPI back in environment.js to avoid the complication of needing util.createRequire().
Also, before I can merge this I still need you to tell me whether this is purely a code move plus comments or whether you changed any of the code when you moved it into separate files. Changing any of the implementations of these API functions feels very risky to me, and I don't want to risk that.
* @return {string} | ||
*/ | ||
function encode(str) { | ||
return encodeURI(str); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it would be safe to make that change. It probably should have been written that way to begin with, but any change now risks changing what appears on developer.mozilla.org and I don't want to risk that since we don't have a way to test that API changes here don't affect the output on any of the thousands of MDN document, I'm very very reluctant to change anything.
|
||
while ((i = (j = t.charAt(x++)).charCodeAt(0))) { | ||
var m = i == 46 || (i >= 48 && i <= 57); | ||
if (m !== n) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this code was a port of a C algorithm, and n=0
above was intended to be n=false
? Maybe the !== should have been a !=
But again, unless we can point to a specific content bug that is being caused by this, I don't want to go changing this legacy code for fear of causing unexpected changes to the output.
if (aa[x] !== bb[x]) { | ||
var c = Number(aa[x]), | ||
d = Number(bb[x]); | ||
if (c == aa[x] && d == bb[x]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's just not true. (1 == "1")
evaluates to true in JavaScript
if (aa[x] !== bb[x]) { | ||
var c = Number(aa[x]), | ||
d = Number(bb[x]); | ||
if (c == aa[x] && d == bb[x]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this code is so old and untyped that it is not possible to apply type analysis to it without a complete rewrite. And rewrites are off the table.
I haven’t actually changed any code, the only thing I’ve done is add I’ve kept the |
7ed4d3c
to
461c29f
Compare
I just saw that you pushed another change... Let me know when you're done and I'll take a final look and merge. I really would prefer that you put the '.js' extensions back on the require() calls, though. |
I’d say I’m done now. |
I just noticed what you said above about keeping createRequire() in utils with a TODO comment. Please don't do that. I'd like to put KumaScript into maintenance mode and I don't think it will be worth while to make that kind of change in the future. And again, please add '.js' extensions to your require() calls, or try to convince me why we shouldn't be using them. My argument for using extensions is that without them the code is less clear and it is not clear what would happen if you were to drop a wiki.json or wiki.ts file into the api/ directory. I'd prefer to avoid code that depends on the precise behavior of the module loader and the contents of directories. |
Well, I guess I can always just change them to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple more changes, please.
Also: what conversion to typescript are you talking about? Have you discussed this with anyone? Maybe I'm just out of the loop, but I can tell you now that I would not be willing to review any such patch.
It is unclear what the future of KumaScript is. MDN documentation will probably continue to rely on it for some time, but there are not any plans to add features to KumaScript or to increase our dependency on it by adding more macros than we delete. If you have your own reasons for wanting to work on and evolve KumaScript, you might need to create your own fork.
I was hoping to merge this today, but in doing a final check, I found some more changes I'd like you to make. A couple are just nits, but one is serious.
Environment.js already has the APIs defined as object literals with methods inside them, and I was imagining that you could use those object literals exactly as they are with the nice method syntax and without having to add the I would prefer it if these api files were in that |
Turns out, the issue was trailing whitespace, which somehow didn’t get removed by my IDE. And also a trailing comma, which were used in many places before #1035. Also, I did a search, and nothing depends on the existence of |
The thing about the string API is that it is a horrible API that macro writers would be better off not using. Giving the functions better names will only make the API more attractive to use, which is the opposite of what we want. The prepareProto() function doesn't make any assumptions about the method name beginning with a lower case letter: it simply matches the legacy behavior of the old KumaScript. Since we're not actively working on KumaScript anymore, I really don't want any risk of subtle changes that could cause future maintenance issues. Changing the case of those function names converts this PR from a pure refactor with no behavior changes into something else. We'll have to get input from other team members if you want to proceed with the lower-case variants. |
7c75549
to
26e416d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ExE-Boss,
I think I have been quite clear that I'm paranoid about changes to this code and that I am unwilling to accept any changes other than breaking environment.js into new files and adding comments. Yet in this most recent patch you included two code changes. That makes me concerned that you may have made other small changes like these when you moved the code out of environment.js. Because of the way the files were reformatted, however, I have no way of determining which lines, if any were changed.
I believe that both of these change in this latest commit are equivalent to the old code, and may well be faster as well. I understand that you are a skilled programmer and can get stuff like this right. However, that doesn't reduce my burden of reviewing your changes. There are lots of things that could be improved in this code, but because it is old legacy code that no one on the team is particularly familiar with and becasue of the lack of comprehensive tests, every little improvement is risky, and every change requires me to spend time convincing myself that it is safe.
This is not a patch that is on anyone's priority list. I like the idea of it, but my manager would not be happy to know how much time I've spent this week on reviewing it.
This may sound unreasonable to you, but in order for me to approve this patch at this point, I need to have the code copied verbatim (without whitespace changes, even) from environment.js into api/.js. I want to be able to concatenate the files in api/.js (in whatever the correct order is) and then diff that concatenated file against the old version of environment.js and see only changes to comments and a few changes from lines like const mdnPrototype = {
to module.exports = {
I really would like to have the APIs broken out like this, because it is more elegant and because it improves our test coverage percentage for environment.js. But at this point I'll only accept the patch if I can mechanically verify that the code is unchanged. I will understand if you prefer to just abandon the PR at this point.
Ok, I’ll make a new PR where I don't make any changes, and then rebase this on top of it. |
I’ve now opened #1103 to do that. |
This extracts all the
*Prototype
objects into separate files insrc/api/*
, which will make testing easier.To do:
util
mdnPrototype
stringPrototype
(I’ll also apply my fixes from test(macros/DekiScript): Add tests forDekiScript:String
#1013)wikiPrototype
webPrototype
pagePrototype
Simple re‑exports:
I’m considering leaving these ones in
environment.js
, as they just re‑export functions:(reverted in 279561a)globalsPrototype
kumaPrototype
uriPrototype
I’m also adding JSDoc comments from #1077.
review?(@davidflanagan, @escattone)