Skip to content

Commit 0e63e79

Browse files
New object and classes system. Replaces the prototype-based object system by a classical class-based system.
Tests have been modified for conformance.
1 parent 55f6cc0 commit 0e63e79

33 files changed

+2450
-1452
lines changed

Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ mvmFunctions.cpp \
1919
semanticCheck.cpp \
2020
actorRuntime.cpp \
2121
asVars.cpp \
22-
executionScope.cpp
22+
executionScope.cpp \
23+
asObjects.cpp \
24+
asString.cpp
2325

2426
OBJECTS=$(SOURCES:.cpp=.o)
2527

TinyJS_Functions.cpp

Lines changed: 10 additions & 276 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include "TinyJS_Functions.h"
3232
#include "scriptMain.h"
3333
#include "mvmFunctions.h"
34+
#include "asObjects.h"
35+
#include "asString.h"
3436

3537
#include <math.h>
3638
#include <cstdlib>
@@ -55,43 +57,6 @@ void scObjectClone(FunctionScope* pScope) {
5557
c->getReturnVar()->copyValue(obj);
5658
}*/
5759

58-
Ref<JSValue> scObjectFreeze(FunctionScope* pScope)
59-
{
60-
auto obj = pScope->getThis();
61-
62-
return obj->freeze();
63-
}
64-
65-
Ref<JSValue> scObjectDeepFreeze(FunctionScope* pScope)
66-
{
67-
auto obj = pScope->getThis();
68-
69-
JSValuesMap transformed;
70-
return deepFreeze(obj, transformed);
71-
}
72-
73-
Ref<JSValue> scObjectUnfreeze(FunctionScope* pScope)
74-
{
75-
auto obj = pScope->getThis();
76-
auto forceClone = pScope->getParam("forceClone");
77-
78-
return obj->unFreeze(forceClone->toBoolean());
79-
}
80-
81-
Ref<JSValue> scObjectIsFrozen(FunctionScope* pScope)
82-
{
83-
auto obj = pScope->getThis();
84-
85-
return jsBool (!obj->isMutable());
86-
}
87-
88-
Ref<JSValue> scObjectIsDeepFrozen(FunctionScope* pScope)
89-
{
90-
auto obj = pScope->getThis();
91-
92-
return jsBool (obj->getMutability() == MT_DEEPFROZEN);
93-
}
94-
9560
Ref<JSValue> scMathRand(FunctionScope* pScope)
9661
{
9762
return jsDouble(double(rand()) / RAND_MAX);
@@ -114,74 +79,6 @@ Ref<JSValue> scCharToInt(FunctionScope* pScope)
11479
return jsInt(val);
11580
}
11681

117-
Ref<JSValue> scStringIndexOf(FunctionScope* pScope)
118-
{
119-
string str = pScope->getThis()->toString();
120-
string search = pScope->getParam("search")->toString();
121-
size_t p = str.find(search);
122-
int val = (p == string::npos) ? -1 : p;
123-
return jsInt(val);
124-
}
125-
126-
Ref<JSValue> scStringSubstring(FunctionScope* pScope)
127-
{
128-
string str = pScope->getThis()->toString();
129-
const size_t lo = toSizeT(pScope->getParam("lo"));
130-
const size_t hi = toSizeT(pScope->getParam("hi"));
131-
132-
size_t l = hi - lo;
133-
if (l > 0 && lo >= 0 && lo + l <= str.length())
134-
return jsString(str.substr(lo, l));
135-
else
136-
return jsString("");
137-
}
138-
139-
Ref<JSValue> scStringCharAt(FunctionScope* pScope)
140-
{
141-
Ref<JSString> str = pScope->getThis().staticCast<JSString>();
142-
143-
size_t pos = toSizeT( pScope->getParam("pos") );
144-
145-
return str->readField (jsDouble(pos));
146-
}
147-
148-
Ref<JSValue> scStringCharCodeAt(FunctionScope* pScope)
149-
{
150-
string str = scStringCharAt(pScope)->toString();
151-
if (!str.empty())
152-
return jsInt(str[0]);
153-
else
154-
return jsInt(0);
155-
}
156-
157-
Ref<JSValue> scStringSplit(FunctionScope* pScope)
158-
{
159-
string str = pScope->getThis()->toString();
160-
string sep = pScope->getParam("separator")->toString();
161-
Ref<JSArray> result = JSArray::create();
162-
163-
size_t pos = str.find(sep);
164-
while (pos != string::npos)
165-
{
166-
result->push(jsString(str.substr(0, pos)));
167-
str = str.substr(pos + 1);
168-
pos = str.find(sep);
169-
}
170-
171-
if (str.size() > 0)
172-
result->push(jsString(str));
173-
174-
return result;
175-
}
176-
177-
Ref<JSValue> scStringFromCharCode(FunctionScope* pScope)
178-
{
179-
char str[2];
180-
str[0] = (char)toInt32( pScope->getParam("char"));
181-
str[1] = 0;
182-
return jsString(str);
183-
}
184-
18582
Ref<JSValue> scIntegerParseInt(FunctionScope* pScope)
18683
{
18784
//TODO: Make it more standard compliant (octal support, return NaN if fails...)
@@ -215,197 +112,34 @@ Ref<JSValue> scEval(FunctionScope* pScope)
215112
return evaluate (str.c_str(), createDefaultGlobals());
216113
}
217114

218-
Ref<JSValue> objectConstructor(FunctionScope* pScope)
219-
{
220-
//TODO: Not implemented
221-
return undefined();
222-
}
223-
224-
Ref<JSValue> arrayConstructor(FunctionScope* pScope)
225-
{
226-
//TODO: Not implemented
227-
return undefined();
228-
}
229-
230-
Ref<JSValue> functionConstructor(FunctionScope* pScope)
231-
{
232-
//TODO: Not implemented
233-
return undefined();
234-
}
235-
236-
Ref<JSValue> stringConstructor(FunctionScope* pScope)
115+
void registerDefaultClasses(Ref<IScope> scope)
237116
{
238-
Ref<JSValue> obj = pScope->getParam("obj");
239-
240-
return jsString (obj->toString());
241-
}
242-
243-
Ref<JSValue> scArrayPush(FunctionScope* pScope)
244-
{
245-
auto arr = pScope->getThis().staticCast<JSArray>();
246-
auto val = pScope->getParam("x");
247-
248-
arr->push(val);
249-
250-
return arr;
251-
}
252-
253-
Ref<JSValue> scArrayIndexOf(FunctionScope* pScope)
254-
{
255-
auto arrVal = pScope->getThis();
256-
auto arr = arrVal.staticCast<JSArray>();
257-
auto searchElement = pScope->getParam("searchElement");
258-
auto fromIndex = pScope->getParam("fromIndex");
259-
260-
if (arrVal->isNull())
261-
return jsInt(-1);
262-
263-
const size_t len = arr->length();
264-
265-
if (len <= 0)
266-
return jsInt(-1);
267-
268-
size_t n = 0;
269-
270-
if (!fromIndex->isNull())
271-
n = (size_t)floor(fromIndex->toDouble());
272-
273-
if (n >= len)
274-
return jsInt(-1);
275-
276-
for (; n < len; n++) {
277-
auto item = arr->getAt (n);
278-
279-
if (mvmAreTypeEqual (item, searchElement))
280-
return jsInt(n);
281-
}
282-
return jsInt(-1);
283-
}
284-
285-
std::string scArrayJoin(Ref<JSArray> arr, Ref<JSValue> sep)
286-
{
287-
string sepStr = ",";
288-
289-
if (!sep->isNull())
290-
sepStr = sep->toString();
291-
292-
ostringstream output;
293-
const size_t n = arr->length();
294-
for (size_t i = 0; i < n; i++)
295-
{
296-
if (i > 0)
297-
output << sepStr;
298-
output << arr->getAt(i)->toString();
299-
}
300-
301-
return output.str();
302-
}
303-
304-
Ref<JSValue>scArrayJoin(FunctionScope* pScope)
305-
{
306-
auto arr = pScope->getThis().staticCast<JSArray>();
307-
auto sep = pScope->getParam("separator");
308-
309-
return jsString( scArrayJoin(arr, sep) );
117+
scope->newVar("Object", JSObject::DefaultClass, true);
118+
scope->newVar("String", JSString::StringClass, true);
119+
scope->newVar("Array", JSArray::ArrayClass, true);
310120
}
311121

122+
// ----------------------------------------------- Register Functions
312123
/**
313-
* Creates a 'alice' of the array. A contiguous subset of array elements
314-
* defined by a initial index (included) and a final index (not included)
315-
* @param pScope
316-
* @return
124+
* Register default functions into the given scope.
125+
* @param scope
317126
*/
318-
Ref<JSValue>scArraySlice(FunctionScope* pScope)
319-
{
320-
Ref<JSArray> arr = pScope->getThis().staticCast<JSArray>();
321-
auto begin = pScope->getParam("begin");
322-
auto end = pScope->getParam("end");
323-
const size_t iBegin = toSizeT( begin );
324-
size_t iEnd = arr->length();
325-
326-
if (isUint(end))
327-
iEnd = toSizeT( end );
328-
329-
iEnd = max (iEnd, iBegin);
330-
331-
auto result = JSArray::create();
332-
333-
for (size_t i = iBegin; i < iEnd; ++i)
334-
result->push(arr->getAt(i));
335-
336-
return result;
337-
}
338-
339-
// ----------------------------------------------- Register Functions
340-
341-
Ref<JSObject> createClass(const char* className,
342-
Ref<JSObject> parentPrototype,
343-
JSNativeFn constructorFn,
344-
Ref<IScope> scope)
345-
{
346-
static const std::string fnHeader = "function ";
347-
Ref<JSObject> prototype = JSObject::create(parentPrototype);
348-
Ref<JSFunction> constructor = addNative(fnHeader + className, constructorFn, scope);
349-
350-
constructor->writeField(jsString("prototype"), prototype);
351-
return prototype;
352-
}
353-
354-
void fixPrototype (const char* objName, Ref<JSObject> prototype, Ref<IScope> scope)
355-
{
356-
Ref<JSValue> obj = scope->get(objName);
357-
358-
castTo<JSObject>(obj)->setPrototype(prototype);
359-
}
360-
361-
362-
void createDefaultPrototypes (Ref<IScope> scope)
363-
{
364-
Ref<JSObject> objProto = createClass("Object(obj)", Ref<JSObject>(), objectConstructor, scope);
365-
366-
JSObject::DefaultPrototype = objProto;
367-
JSFunction::DefaultPrototype = createClass("Function()", objProto, functionConstructor, scope);
368-
369-
fixPrototype ("Object", JSFunction::DefaultPrototype, scope);
370-
fixPrototype ("Function", JSFunction::DefaultPrototype, scope);
371-
372-
JSArray::DefaultPrototype = createClass("Array()", objProto, arrayConstructor, scope);
373-
JSString::DefaultPrototype = createClass("String(obj)", objProto, stringConstructor, scope);
374-
}
375-
376127
void registerFunctions(Ref<IScope> scope)
377128
{
378-
createDefaultPrototypes (scope);
129+
registerDefaultClasses(scope);
379130

380131
addNative("function eval(jsCode)", scEval, scope); // execute the given string (an expression) and return the result
381132
// addNative("function trace()", scTrace, scope);
382133
// addNative("function Object.dump()", scObjectDump, scope);
383134
// addNative("function Object.clone()", scObjectClone, scope);
384135

385-
addNative("function Object.prototype.freeze()", scObjectFreeze, scope);
386-
addNative("function Object.prototype.deepFreeze()", scObjectDeepFreeze, scope);
387-
addNative("function Object.prototype.unfreeze(forceClone)", scObjectUnfreeze, scope);
388-
addNative("function Object.prototype.isFrozen(forceClone)", scObjectIsFrozen, scope);
389-
addNative("function Object.prototype.isDeepFrozen(forceClone)", scObjectIsDeepFrozen, scope);
390-
391136
addNative("function Math.rand()", scMathRand, scope);
392137
addNative("function Math.randInt(min, max)", scMathRandInt, scope);
393138
addNative("function charToInt(ch)", scCharToInt, scope); // convert a character to an int - get its value
394139

395-
addNative("function String.prototype.indexOf(search)", scStringIndexOf, scope); // find the position of a string in a string, -1 if not
396-
addNative("function String.prototype.substring(lo,hi)", scStringSubstring, scope);
397-
addNative("function String.prototype.charAt(pos)", scStringCharAt, scope);
398-
addNative("function String.prototype.charCodeAt(pos)", scStringCharCodeAt, scope);
399-
addNative("function String.prototype.split(separator)", scStringSplit, scope);
400-
addNative("function String.fromCharCode(char)", scStringFromCharCode, scope);
401-
402140
addNative("function parseInt(str)", scIntegerParseInt, scope); // string to int
403141
addNative("function Integer.valueOf(str)", scIntegerValueOf, scope); // value of a single character
404142
addNative("function JSON.stringify(obj, replacer)", scJSONStringify, scope); // convert to JSON. replacer is ignored at the moment
405143
//TODO: Add JSON.parse()
406-
addNative("function Array.prototype.slice(begin, end)", scArraySlice, scope);
407-
addNative("function Array.prototype.join(separator)", scArrayJoin, scope);
408-
addNative("function Array.prototype.push(x)", scArrayPush, scope);
409-
addNative("function Array.prototype.indexOf(searchElement, fromIndex)", scArrayIndexOf, scope);
410144
}
411145

TinyJS_Functions.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,5 @@
3737
/// Register useful functions with the TinyJS interpreter
3838
void registerFunctions(Ref<IScope> scope);
3939

40-
std::string scArrayJoin(Ref<JSArray> arr, Ref<JSValue> sep);
41-
4240

4341
#endif

0 commit comments

Comments
 (0)