brownplt / lambdas5 Goto Github PK
View Code? Open in Web Editor NEWSemantics for ES5
License: BSD 3-Clause "New" or "Revised" License
Semantics for ES5
License: BSD 3-Clause "New" or "Revised" License
Semantics for ECMAScript 5.0 ============================ Install and Usage ----------------- See `INSTALL` for installation instruction. s5 options are implemented as stack manipulation so the order of options matters. Here are a few examples (in `src/` directory, and a js file `test.js` exists): Desugar a Javascript program and print the S5 source. $ ./s5.d.byte -desugar test.js -print-src Desugar a Javascript program, wrap with an Environment and do evaluation. $ ./s5.d.byte -desugar test.js -env ../envs/es5.env -apply -eval Desugar a Javascript program, wrap with an Environment, apply optimizations and finally print out the optimized code (excluding the environment). $ ./s5.d.byte -desugar test.js -env ../envs/es5-optimization.env -apply -opt-restore-id -opt-restore-function -opt-propagate-const -opt-clean-deadcode -print-user-s5 Slimming Language Options ------------------------- All optimization options start with "-opt-". There are a few options not compatible with the optimization flags: 1. `-internal-env env-vars`. This option introduces identifiers of es5.env in the nested environment for `eval`. It has a huge negative impact on the constant propagation. 2. `-env es5.env`. There are several `env` files in env/ directory. Optimization flags only work on `es5-optimization.env`, which is similar to `es5.env`. The only difference is that it excludes built-in `eval` support (-opt-restore-id would not work if `es5.env` is used). See previous usage examples for how to pass a correct environment.
Bodies need undefined on the end --- currently they take the value of their last expression.
Odd... The test reports an error but I think it's wrong:
test: function testcase() {
if (x == undefined) {
$ERROR("x == undefined, but actual is "+ x);
}
var x = true;
var y = true
}
I think that x should be undefined up top.
Handle them
Something in this text in console/harness/testIntl.js:
var numberingSystemDigits = {
arab: "٠١٢٣٤٥٦٧٨٩",
arabext: "۰۱۲۳۴۵۶۷۸۹",
beng: "০১২৩৪৫৬৭৮৯",
deva: "०१२३४५६७८९",
fullwide: "0123456789",
gujr: "૦૧૨૩૪૫૬૭૮૯",
guru: "੦੧੨੩੪੫੬੭੮੯",
hanidec: "〇一二三四五六七八九",
khmr: "០១២៣៤៥៦៧៨៩",
knda: "೦೧೨೩೪೫೬೭೮೯",
laoo: "໐໑໒໓໔໕໖໗໘໙",
latn: "0123456789",
mlym: "൦൧൨൩൪൫൬൭൮൯",
mong: "᠐᠑᠒᠓᠔᠕᠖᠗᠘᠙",
mymr: "၀၁၂၃၄၅၆၇၈၉",
orya: "୦୧୨୩୪୫୬୭୮୯",
tamldec: "௦௧௨௩௪௫௬௭௮௯",
telu: "౦౧౨౩౪౫౬౭౮౯",
thai: "๐๑๒๓๔๕๖๗๘๙",
tibt: "༠༡༢༣༤༥༦༧༨༩"
};
Is breaking our limited Unicode support.
The single_test.sh script says we fail this test:
test262/test/suite/sputnik_converted/15_Native/15.2_Object_Objects/S15.2_A1.js
When I made an identical unit test, it seems to pass. Maybe it's something with our harness integration. The unit test I made:
var obj=Object;
var thisobj=this.Object;
if (obj!==thisobj) {
print("fail");
}
"zxy"[1] === "x"
Make it happen.
We need to either change the parser (hard), or pretty print the JS as we desugar (easier).
It seems to me that S5 does not conform to ES5.1, Section 10.5 Declaration Binding Instantiation, Step 5.e.iv.
For the following test program:
// 10.5 Declaration Binding Instantiation, Step 5.e.iv, First condition is true
// 5. For each FunctionDeclaration f in code, in source text order do
// ...
// e. Else if env is the environment record component of the global environment then
// ...
// iii. If existingProp .[[Configurable]] is true, then
// ...
// iv. Else if IsAccessorDescriptor(existingProp) or ..., then
// 1. Throw a TypeError exception.
// A duplicated function declaration in a global scope throws TypeError,
// if the existing is not configurable and an accessor descriptor.
// In the below example, we put the duplicated function declaration in 'eval', in order to the declaration is evaluated after the 'Object.defineProperty' statement,
// otherwise the function declaration will be evaluated first before the first statement.
Object.defineProperty(this, "f", { "get" : undefined, "set" : undefined, "enumerable" : false, "configurable" : false });
try {
eval(" function f() { return 0; } "); // TypeError
throw "Not here!";
} catch (e) {
if (!(e instanceof TypeError)) {
$ERROR('Object.defineProperty(this, "f", { "get" : undefined, "set" : undefined, "enumerable" : false, "configurable" : false }); eval(" function f() { return 0; } "); throws TypeError. Actual: ' + e);
}
}
S5 throws an exception, while it should have succeeded:
$ ./s5-test262 /tmp/15.js
../envs/es5.env:6:0-5029:0
<unknown>:19:-1--4
<unknown>:19:-1--4
<unknown>:19:-1--4
<unknown>:23:-3-24:-206
<unknown>:24:-5--205
<unknown>:24:-5--11
../envs/es5.env:977:28-983:3
../envs/es5.env:980:11-982:5
../envs/es5.env:287:28-293:1
Uncaught exception: {[#proto: @9, #class: "Object", #extensible: true,]
'message' : {#value "Unbound identifier: $ERROR" ,
#writable true ,
#configurable false}}
Fatal error: exception Failure("Runtime error")
Is there anything that I'm missing?
This should not produce any exceptions when run from the test262 directory:
./single-test.sh test262/test/suite/sputnik_converted/08_Types/8.1_The_Undefined_Type/S8.1_A1_T1.js
(Currently it says "ForInVar NYI")
These things are currently interpreter errors, but should be throwing exceptions:
The following Javascript program returns 1 in S5, it should return 5.
a: for (var x = 1; x < 5; x+=1) { continue a }; x
For the current desugaring, continue
with a label behaves like a break
, which is wrong.
.. to /Users/arjun/Downloads/js-1.8.5/js/src/shell/js
In es5.env, in %defineOwnProperty, if %hasOwnProperty returns true, and then the field is not #configurable, the code refers to a "current-prop" object, which isn't defined anywhere. There's even a comment asking what current-prop is...and that comment comes 10 lines after the first use of current-prop :)
I think this one is failing due to something wrong with EqEq
./single-test.sh test262/test/suite/sputnik_converted/15_Native/15.2_Object_Objects/15.2.1_The_Object_Constructor_Called_as_a_Function/S15.2.1.1_A2_T2.js
but I could be wrong.
Ever since this commit:
single_test.sh will always report pass. It may not be worth bothering with, if we are moving to implement an improved test system, but I was using it.
Sputnik has a bunch of tests that seem like they should fail, but I'm not sure what they do with the harness, e.g.
test262/test/suite/sputnik_converted/08_Types/8.3_The_Boolean_Type/S8.3_A2.1.js
Which has as the body:
true = 1;
Which fails to parse.
When using something that is not a string a the #class
attribute of an object, I get a parse error.
I would understand if it was a runtime error, but why does the parser error? According to ljs/ljs_parser.mly
, #class
expects an expression (exactly as for #proto
, but in the case of #proto
, an expression works)
vlorentz@gommier:~/js/LambdaS5/tests(working)$ echo "{[#proto: 5]}" | ../obj/s5.d.byte -load init.heap /dev/stdin -continue-s5-eval
object
vlorentz@gommier:~/js/LambdaS5/tests(working)$ echo "{[#class: 'foo']}" | ../obj/s5.d.byte -load init.heap /dev/stdin -continue-s5-eval
object
vlorentz@gommier:~/js/LambdaS5/tests(working)$ echo "{[#class: 5]}" | ../obj/s5.d.byte -load init.heap /dev/stdin -continue-s5-eval
Fatal error: exception Failure("parse error at /dev/stdin:1:11-11; unexpected token 5")
Doesn't happen on 3.12 and below
$ make
ocamlbuild -build-dir ../obj -libs unix,str,graph,oUnit -lflags -I,../lib -Is analyses/cfg,analyses/cps,analyses/sym,analyses/ses,js,exprjs,ljs,util,experimental,test -cflags -annot -cflags -I,../lib -Is analyses/cfg,analyses/cps,analyses/sym,analyses/ses,js,exprjs,ljs,util,experimental,test s5.d.byte
It seems to me that S5 does not conform to Section 8.7.1 GetValue (V), [[Get]], Step 6 in ES5.1.
For the following test program:
// 8.7.1 GetValue (V), [[Get]], Step 6
// 6. If getter is undefined, return undefined.
// For [[Get]] for a reference with a primitive base,
// if its value is an accessor descriptor, and its getter is undefined, then it returns undefined.
"use strict";
var r;
var n;
Object.defineProperty(Number.prototype, "x", { "set" : function (v) { n = v; }, "enumerable" : true, "configurable" : true });
r = 1["x"]; // undefined
if (!(r === undefined)) {
$ERROR('Object.defineProperty(Number.prototype, "x", { "enumerable" : true, "configurable" : true, "set" : function (v) { n = v; } }); 1["x"] is undefined. Actual: ' + r);
}
S5 throws an exception, while it should have succeeded:
$ ./s5-test262 /tmp/01.js
../envs/es5.env:6:0-5029:0
<unknown>:11:-1--2
<unknown>:11:-5--11
Uncaught error: "[interp] (<unknown>:11:-5--11) Applied non-function, was actually undefined"
Fatal error: exception Failure("Runtime error")
Is there anything that I'm missing?
When used on a field with undefined
as #getter
, an explicit error is displayed:
$ echo "{[] 'foo': {#getter undefined, #setter undefined}}['foo']" | ../obj/s5.d.byte -load init.heap /dev/stdin -continue-s5-eval
Uncaught error: "[interp] (/dev/stdin:1:0-57) Applied non-function, was actually undefined"
Fatal error: exception Failure("Runtime error")
But, when setting the field instead of getting it, does not show an error at all:
$ echo "{[] 'foo': {#getter undefined, #setter undefined}}['foo' = 'bar']" | ../obj/s5.d.byte -load init.heap /dev/stdin -continue-s5-eval
Fatal error: exception Failure("Runtime error")
When reading the source code (at https://github.com/brownplt/LambdaS5/blob/master/src/ljs/ljs_eval.ml#L529), I noticed that it should display an error message, but the eprintf
calls seem not to do anything (replacing them with print_string
shows Uncaught exception: "unwritable-field"
), but I have no idea why…
js_to_exprjs currently uses specially-named identifiers to transform surface JS into an intermediate form (ExprJS). The transformation looks like:
function f(x) {
var y = 5;
}
f = func(this, args) {
let %%x = undefined
let %%y = undefined
%%y = 5
}}
Then the next step looks for %% variables and turns them into context objects. We should have a special let form that binds JS-ids specifically, and not use the %%-hack.
Make them happen.
It seems to me that S5 does not conform to ES5.1, Section 8.12.4 [[CanPut]] (P)
, Step 8.a.
For the following test program:
// 8.12.4 [[CanPut]] (P), Step 8.a
// 8. Else, inherited must be a DataDescriptor
// a. If the [[Extensible]] internal property of O is false, return false.
// b. ...
// If O inherits P, which is data descriptor, but O is not extensible, then CanPut is false.
// In this example, the assignment is ignored, since CanPut is false.
var o = Object.create( { x : 0 } );
Object.freeze(o); // Set o's [[Extensible]] false
o.x = 1; // [[CanPut]] is false, thus Nop
if (!(o.x === 0)) {
$ERROR('var o = Object.create( { x : 0 } ); Object.freeze(o); o.x = 1; o.x is 0. Actual: ' + o.x);
}
S5 throws an exception, while it should have succeeded:
$ ./s5-test262 /tmp/08.js
../envs/es5.env:6:0-5029:0
<unknown>:13:-1--8
../envs/es5.env:108:44-117:1
../envs/es5.env:109:34-58
Uncaught exception: {[#proto: @7, #class: "Object", #extensible: true,]
'message' : {#value "set-property failed" ,
#writable false ,
#configurable false}}
Fatal error: exception Failure("Runtime error")
Is there anything that I'm missing?
In the case corresponding to E-ShadowField in the semantics ("A Tested Semantics..."), the object is not checked for extensibility; the check is there in the semantics. The check is also in EcmaScript specification (8.12.4 step 8a).
"foo".length === 3
The following program returns 120 in S5, should throw an exception (because the f variable should shadow the recursive binding):
var x = function f (a) { var f; if (a == 0) return 1; else return a * f(a-1) }; x(5)
Reason: ES5 chapter 13 says that a new scope should be introduced for the recursive binding, but S5's desugaring puts the recursive binding directly in the function's scope.
The following test consumes an unreasonable amount of memory, eventually causing ocamlrun to halt with an out of memory error:
test262/test262/test/suite/sputnik_converted/13_Function_Definition/13.2_Creating_Function_Objects/S13.2.1_A1_T1.js
The test invokes a nested anonymous function expression of depth 32.
Desugaring does a lot of dumb stuff and I'm looking into it now.
LambdaS5's implementation of prim("strlen", str)
(which is used in the desugared version of str.length
) uses Caml's String.length
, which counts the number of bytes of the string.
However, String.length
is supposed to count the number of characters.
The two values are the same for pure ASCII strings, but not for other unicode characters.
For instance:
$ echo "'é'.length" > /tmp/test.js
$ ./obj/s5.d.byte -desugar /tmp/test.js -env ./envs/es5.env -apply -eval
2.
$ nodejs
> 'é'.length
1
Our test script removes the whole line if it detects a comment. So if there's a line with a trailing comment, it will cause a problem. For example this one:
test262/test/suite/sputnik_converted/15_Native/15.8_The_Math_Object/15.8.2_Function_Properties_of_the_Math_Object/15.8.2.13_pow/S15.8.2.13_A14.js
It fails, unless you remove the comment on line 31.
Just writing this down here so I don't forget to fix it later.
This demonstrates flaws in our handling of scope & closures:
var makeCounter = function(init) {
var count = init;
var counter = function() {
var rtn = count;
count +=1;
return rtn;
}
return counter;
}
var c1 = makeCounter(0),
c2 = makeCounter(0);
print(c1());
print(c1());
print(c1());
print(c2());
print(c2());
print(c2());
Direct execution, works as expected:
vlorentz@gommier:~/js/LambdaS5/tests$ echo "print('foo\nbar')" > /tmp/tmp.js && ../obj/s5.d.byte -desugar /tmp/tmp.js -env ../envs/es5.env -apply -eval
foo
bar
undefined
However, if I write desugared code to a temporary file, and then execute that temporary file, it does not display the same value:
vlorentz@gommier:~/js/LambdaS5/tests$ echo "print('foo\nbar')" > /tmp/tmp.js && ./s5-desugar /tmp/tmp.js > /tmp/tmp.ljs
vlorentz@gommier:~/js/LambdaS5/tests$ ../obj/s5.d.byte /tmp/tmp.ljs -env ../envs/es5.env -apply -eval
foo\nbar
undefined
For lambdaS5 syntax, the pretty printed code should parse as well. It is currently a bizarre mix of s-exps and lambdaS5 syntax.
Is it me or https://github.com/brownplt/LambdaS5/blob/master/tests/unit-tests/delete-regexp-full.js is mostly dead code?
Only the last 13 lines seem to be run
S5 desugars compound assignment (e1 += e2 etc.) to e1 = e1 + e2, which is invalid when the evaluation of e1 has side effects. Here is an example program that exhibits the problem:
var o = {x: 0};
function f() { o.x++; return o };
(f()).x += 1
Complying implementations should give o.x == 2. S5 gives 3, because under the current desugaring, f() is called twice.
Lots of labels and whiles. Appears to be in an infinite loop. Code:
test: function testcase() {
do_out : while(1===1) {
if (__in__do__before__break) break;
var __in__do__before__break="black";
do_in : while (1) {
var __in__do__IN__before__break="hole";
break do_in;
var __in__do__IN__after__break="sun";
} ;
var __in__do__after__break="won't you come";
};
It seems to me that S5 does not conform to ES5.1, Section 10.2.1.1.3 SetMutableBinding (N,V,S), Step 4, if-condition is true.
For the following test program:
// 10.2.1.1.3 SetMutableBinding (N,V,S), Step 4, if-condition is true
// 4. Else this must be an attempt to change the value of an immutable binding so if S if true throw a TypeError exception.
// In a strict mode, assigning an immutable binding throws TypeError.
// There are only two ways to create an immutable binding:
// 1. 'arguments' is an immutable binding in a strict mode function.
// 2. name of a recursive function expression (it should be a function 'expression', not a function 'declaration') is an immutable binding of the function body's environment.
// In the first case, assigning such binding raises a syntax error, in advance, in a strict mode code, thus it cannot reach here.
// Thus, assigning the second kind of binding is the only case that can reach here, and the below example represents this case.
// In the example below, 'g' is a name of recursive function expression, thus inside the function body, 'g' is a immutable binding.
// Note that 'g' is not visible outside of the function body, that is, it is not visible in a global scope.
"use strict";
var f = function g() {
g = 0;
};
try {
f(); // TypeError
throw "Not here!";
} catch (e) {
if (!(e instanceof TypeError)) {
$ERROR('"use strict"; var f = function g() { g = 0; }; f(); throws TypeError. Actual: ' + e);
}
}
S5 throws an exception, while it should have succeeded:
$ ./s5-test262 /tmp/09.js
../envs/es5.env:6:0-5029:0
<unknown>:20:-1--4
<unknown>:20:-1--4
<unknown>:20:-1--4
<unknown>:24:-3-25:-98
<unknown>:25:-5--97
<unknown>:25:-5--11
../envs/es5.env:977:28-983:3
../envs/es5.env:980:11-982:5
../envs/es5.env:287:28-293:1
Uncaught exception: {[#proto: @9, #class: "Object", #extensible: true,]
'message' : {#value "Unbound identifier: $ERROR" ,
#writable true ,
#configurable false}}
Fatal error: exception Failure("Runtime error")
Is there anything that I'm missing?
It seems to me that S5 does not conform to ES5.1, Section 8.7.2 PutValue (V, W), [[Put]], Step 7.a.
For the following test program:
// 8.7.2 PutValue (V, W), [[Put]], Step 7.a
// 7. Else, this is a request to create an own property on the transient object O
// a. If Throw is true, then throw a TypeError exception.
// For [[Put]] for a reference with a primitive base,
// if it does not have its own value, but a inherited data descriptor,
// then this assignment will create its own data descriptor which cannot be used later at all, because this object will immediately disappear after this assignment
// (at least there is no reference pointing to this object, so it's not accessible).
// Thus, if throw is true, then it throws TypeError.
"use strict";
try {
1["x"] = 10; // TypeError
throw "Not here!";
} catch (e) {
if (!(e instanceof TypeError)) {
$ERROR('"use strict"; Object.defineProperty(Number.prototype, "x", { "value" : 0, "writable" : false, "enumerable" : true, "configurable" : true }); 1["x"] = 10; throws TypeError. Actual: ' + e);
}
}
S5 throws an exception, while it should have succeeded:
$ ./s5-test262 /tmp/07.js
../envs/es5.env:6:0-5029:0
<unknown>:13:-1--4
<unknown>:13:-1--4
<unknown>:13:-1--4
<unknown>:17:-3-18:-200
<unknown>:18:-5--199
<unknown>:18:-5--11
../envs/es5.env:977:28-983:3
../envs/es5.env:980:11-982:5
../envs/es5.env:287:28-293:1
Uncaught exception: {[#proto: @9, #class: "Object", #extensible: true,]
'message' : {#value "Unbound identifier: $ERROR" ,
#writable true ,
#configurable false}}
Fatal error: exception Failure("Runtime error")
Is there anything that I'm missing?
When using a setter (eg. {[] 'foo': {#getter undefined, #setter (func (a, b) { b })}}['foo' = 'bar']
), b
is not 'bar'
as expected, but is an object.
The setter has no way to know what the “assigned” value is.
Indeed, looking at this code: https://github.com/brownplt/LambdaS5/blob/master/src/ljs/ljs_eval.ml#L272, the value to be “assigned” is stored in v_value
, but this variable is only used for Data
fields, and never for Accessor
ones…
In the "A Tested Semantics" paper, the try-finally expression always gives the same outcome as its left subexpression if the finalizer does not fail - in particular, try v1 finally v2 results in v1. In the interpreter, this expression returns v2.
It seems to me that S5 does not conform to ES5.1, Section 10.2.1.1.5 DeleteBinding (N), Step 4 & 5.
For the following test program:
// 10.2.1.1.5 DeleteBinding (N), Step 4 & 5
// 4. Remove the binding for N from envRec.
// 5. Return true.
// If a binding of a declarative environment record (i.e., not in a global scope nor an 'with' construct) is deletable, then remove it and return true.
// The only way to create a deletable binding is to call CreateMutableBinding with the second argument 'D' of true,
// while the only time to call CreateMutableBinding with 'D' of true is when 'configurableBindings' is true in "10.5 Declaration Binding Instantiation",
// while 'configurableBindings' is true only when 'code' is eval code.
// Thus, a binding of a declarative environment record is deletable only when
// - a function or a variable name is declared in a eval code
// - a formal parameter of a function or an argument object of a function in a eval code (although, in this case, it is not specified whether 'configurableBindings' is used or not)
// a variable declaration in an eval code
function f11() {
eval(" var x11 = 1; delete x11; ");
return x11; // ReferenceError
}
try {
f11();
throw "Not here!";
} catch (e) {
if (!(e instanceof ReferenceError)) {
$ERROR('function f11() { eval(" var x11 = 1; delete x11; "); return x11; } f11(); throws ReferenceError. Actual: ' + e);
}
}
S5 throws an exception, while it should have succeeded:
$ ./s5-test262 /tmp/12.js
../envs/es5.env:6:0-5029:0
<unknown>:20:-1--4
<unknown>:20:-1--4
<unknown>:20:-1--4
<unknown>:24:-3-25:-125
<unknown>:25:-5--124
<unknown>:25:-5--11
../envs/es5.env:977:28-983:3
../envs/es5.env:980:11-982:5
../envs/es5.env:287:28-293:1
Uncaught exception: {[#proto: @9, #class: "Object", #extensible: true,]
'message' : {#value "Unbound identifier: $ERROR" ,
#writable true ,
#configurable false}}
Fatal error: exception Failure("Runtime error")
Is there anything that I'm missing?
The code in cases after the default case is duplicated, which can lead to exponential blowup. For example, in this code:
switch(1) {
default:
case 1:
switch(1) {
default:
case 1:
x = 1
}
}
The x = 1
statement is replicated four times in the desugared code.
This is a bad test --- "prototype" is not enumerable.
It seems to me that S5 does not conform to ES5.1, Section 8.7.2 PutValue (V, W), [[Put]], Step 2.b.
For the following test program:
// 8.7.2 PutValue (V, W), [[Put]], Step 2.b
// 2. If the result of calling the [[CanPut]] internal method of O with argument P is false, then
// a. ...
// b. Else return.
// For [[Put]] for a reference with a primitive base,
// if [[CanPut]] returns false, and Throw is false, then it does nothing.
// NOTE: In this example, [[CanPut]] returns false, because 'writable' is false.
Object.defineProperty(Number.prototype, "x", { "value" : 0, "writable" : false, "enumerable" : true, "configurable" : true });
try {
1["x"] = 10; // Nop
} catch (e) {
$ERROR('Object.defineProperty(Number.prototype, "x", { "value" : 0, "writable" : false, "enumerable" : true, "configurable" : true }); 1["x"] = 10; does nothing. Actual: ' + e);
}
S5 throws an exception, while it should have succeeded:
$ ./s5-test262 /tmp/03.js
../envs/es5.env:6:0-5029:0
<unknown>:13:-1--4
<unknown>:13:-1--4
<unknown>:13:-1--4
<unknown>:16:-3--179
<unknown>:16:-3--9
../envs/es5.env:977:28-983:3
../envs/es5.env:980:11-982:5
../envs/es5.env:287:28-293:1
Uncaught exception: {[#proto: @9, #class: "Object", #extensible: true,]
'message' : {#value "Unbound identifier: $ERROR" ,
#writable true ,
#configurable false}}
Fatal error: exception Failure("Runtime error")
Is there anything that I'm missing?
If you look at efa5c4f, you'll see I made a weird looking change to %set-property.
But it actually needs to be that way to work right. I think something's weird with seq exprs having if-exprs as their "first" sub-expression. This wasn't the first place I noticed the problem - in a lot of the prior Array code I had to write strange stuff to avoid this issue (for example in Array splice, there are seemingly pointless "step1" and "step2" functions).
Also the above commit fixed the regression in unit-tests/arraytostring.js
Causes a match failure in es5_delta.ml
Also:
./test262/test/suite/sputnik_converted/11_Expressions/11.5_Multiplicative_Operators/11.5.3_Applying_the_percent_Operator/S11.5.3_A3_T1.3.js
./test262/test/suite/sputnik_converted/11_Expressions/11.7_Bitwise_Shift_Operators/11.7.2_The_Sign_Left_shift_Operator/S11.7.2_A3_T2.2.js
We started off using this pattern: the internal #proto property of global builtin objects is the prototype. For example, %ArrayGlobalFuncObj's #proto is %ArrayProto.
This is wrong in many cases: these global function objects should have %FunctionProto as #proto.
Based on some tests I'm seeing, there seems to be an expectation that 'Array' have all the properties of 'Array.prototype', and the same for other built-ins. Perhaps our initial pattern was trying to approximate that. I haven't found any basis for this in the spec, but that doesn't mean it's not there.
In trying to pass tests, I changed the #proto of some builtins to %FunctionProto as is specified. That change causes the builtins to lose properties they previously inherited from the old #proto. We might have to manually re-set some of these, as I did for Array.concat.
If I'm missing something, please let me know. Because right now I don't understand this (spidermonkey):
js> Array.concat === Array.prototype.concat
false
Even though these two functions appear to do the same thing.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.