Integration
SDK 5.01x Errata
Fixes Affecting Users of the ScriptEase
ISDKs
API Errata, version 5.01b
New, December 2, 2004
API Errata, version 5.01a
New, March 18, 2004
The
Details
for
5.01b -- (may
apply to earlier version)
- Clib method configuration compiler error
(for ISDK/C 5.01b)
Bug:
When the JSE_CLIB_ALL flag is turned off in a jseopt.h file, and just the JSE_CLIB_SPRINTF, JSE_CLIB_RSPRINTF, and JSE_CLIB_SSCANF flags are turned on, the compiler complains that vsscanf_sechar is undefined.
Fix
n src/lib/clib/sestdio.c, near line 1075, there is a comment an an #if statement that looks like this:
/* Disgusting kludge to get a vscanf-type function on platforms that don't support it */
#if defined(JSE_CLIB_FSCANF) || \
defined(JSE_CLIB_VFSCANF) || \
defined(JSE_CLIB_SCANF) || \
defined(JSE_CLIB_VSCANF)
Add line to that #if statement, so that it looks like this:
/* Disgusting kludge to get a vscanf-type function on platforms that don't support it */
#if defined(JSE_CLIB_FSCANF) || \
defined(JSE_CLIB_VFSCANF) || \
defined(JSE_CLIB_SCANF) || \
defined(JSE_CLIB_VSCANF) || \
defined(JSE_CLIB_SSCANF)
Then, in src/lib/clib/sefile.h, around line 59, there is a #define statement that looks like this:
# define DEFAULT_FGETS_BUFSIZE 1000 /* used if none supplied */
Just above that #define statement, there is a large #if statement. Add a line to the end of it so that instead of having the last few lines look like this:
...
|| defined(JSE_CLIB_GETCHAR) \
|| defined(JSE_CLIB_PUTCHAR) \
|| defined(JSE_CLIB_PERROR) \
|| defined(JSE_CLIB_PUTS)
...it should look like this:
...
|| defined(JSE_CLIB_GETCHAR) \
|| defined(JSE_CLIB_PUTCHAR) \
|| defined(JSE_CLIB_PERROR) \
|| defined(JSE_CLIB_PUTS) \
|| defined(JSE_CLIB_SSCANF)
- seLockString() returns garbage
(for ISDK/C 5.01b)
Bug:
seLockString() does not return a valid string value.
Fix
Around line 787, change this line:
struct seapiLockItem *str = (struct seapiLockItem *)data;
to
this:
struct seapiLockItem *str = find_seTempLockString(call,data);
- seEval() does not follow correct function scoping rules when executing a function literal object
(for ISDK/C 5.01b)
Bug:
When calling a function literal, that function is supposed to remember the values of the variables it had access to at the time of its creation. This works in ScriptEase as long as the funciton literal is being called from within a script. However, before applying this erratum, this won't work in ScriptEase when calling the function literal from a wrapper function using seEval().
Fix
Replace se501/src/core/analyze.c, se501/src/core/call.h, se501/src/core/garbage.c, and se501/src/core/se501.c with the ones found in this zip file: scope.tar.gz
- Dynamic
get callback is not receiving call_hint when
applied to the global variable
(for ISDK/C 5.01b)
Bug:
If the global variable has a get() callback
assigned through seSetCallbacks,
then the get callback may not be receiving the
call_hint
variable set as True
when a property is retrieved as a method (e.g.
global.foo(),
or just foo()).
Fix
: In se501/src/core/varutil.c, function
seobjHasProperty(), at around line 2733 change
this statement:
if( seobjCallDynamicProperty(call,hobj,SE_GET_CALLBACK,propname,False,rhs) )
to
this statement:
if( seobjCallDynamicProperty(call,hobj,SE_GET_CALLBACK,propname,
(rSEVar)( NULL != FUNCPTR
&& FUNCTION_IS_LOCAL(FUNCPTR)
&& ( (seThisAndValue == IPTR[0] && ( seToCallFunc==IPTR[1]
|| seToNewFunc==IPTR[1]))
|| seToNewFunc==IPTR[0] ) ),
rhs) )
- The
Math constants (Math.PI, Math.LOG2E, ect) are
defined as strings, not numbers
(for ISDK/C 5.01b)
Bug:
The Math constants (Math.PI, Math.E, Math.LN10,
Math.LN2, Math.LOG2E, Math.LOG10E, Math.SQRT1_2,
Math.SQRT2) are incorrectly defined as strings,
not numbers. For most math operations, that
is acceptable (although ineffecient) because
the string values are converted to numbers.
But addition fails, because any addition involving
strings turns into a concatenation operation.
That means 5 + Math.PI results in the string
"53.14159265358979323846".
Fix : In se501/src/lib/ecma/mathobj.c
locate the Math library table, identified by
SE_BEGIN_LIB_TABLE, around line 1751. In the
library table, each of the Math constants listed
above is declared with the SE_STRING() macro.
Change each Math constant entry to use the SE_NUMLITERAL()
macro. This is what the Math.E entry looks like
after applying the fix:
SE_NUMLITERAL(UNISTR("E"), E_VALUE, SE_DONTENUM|SE_DONTDELETE|SE_READONLY)
Also,
in se501/src/core/se501.c, function seAddLibTable()
around line 6224, add a 'break' statement at
the end of the 'case SE_NUMLITERAL_TYPE:' block.
The block should look like this after applying
the fix:
case SE_NUMLITERAL_TYPE:
SEVAR_COPY(tmp,place);
str_name = PALMTABLE_STR_DEREF(table->name);
GetDotNamedVar(call,tmp,str_name,SE_DEFAULT);
str_value = PALMTABLE_STR_DEREF(table->value);
SEVAR_INIT_NUMBER(tmp2,convertStringToNumber(call,str_value,strlen_sechar(str_value)));
/* We must turn off flags for this variable so put succeeds */
SEASSERT( SEVAR_GET_TYPE(tmp)==VReference );
seobjSetAttributes(call,tmp->data.ref_val.hBase,
tmp->data.ref_val.reference,0);
SEVAR_DO_PUT(call,tmp,tmp2);
/* Now restore flags with the user-supplied var attribs */
seobjSetAttributes(call,tmp->data.ref_val.hBase,
tmp->data.ref_val.reference,
table->varFlags);
break;
- comobj
library passing wrong Boolean values to COM
object functions
(for ISDK/C 5.01b)
Bug:
When calling a method of a COM object, the comobj
library passes its native values for True and
False, which are 1 and 0, respectively. This
can cause Visual Basic 6 methods to behave strangely,
for instance interpreting the value as Boolean
True, but then interpreting the logical Not
value of the argument as also being True.
Fix : In se501/src/lib/comobj/comobj.cpp,
in the function convertFromJSBoolean(), around
line 1855, there is the VT_BOOL case statement.
Change the code in that statement from this:
V_VT(varg) = (VARTYPE)(VT_BOOL | byRefModifier);
if ( byRefModifier != 0 )
{
short * temp = comobjMustMalloc(short,sizeof(*temp));
*temp = JSVal;
V_BOOLREF(varg) = temp;
}
else
{
V_BOOL(varg) = JSVal;
}
break;
to
this:
short result;
hr = VarBoolFromR8(JSVal, &result);
V_VT(varg) = (VARTYPE)(VT_BOOL | byRefModifier);
if ( byRefModifier != 0 )
{
short * temp = comobjMustMalloc(short,sizeof(*temp));
*temp = result;
V_BOOLREF(varg) = temp;
}
else
{
V_BOOL(varg) = result;
}
break;
Doing so uses the system's VarBoolFromR8() COM
API function to obtain the numeric values for
True and False that are expected by other applications.
- comobj
library handling Bools as numbers, causing heap
to be overwritten
(for ISDK/C 5.01b)
Bug:
When calling a method of a COM object, the comobj
library passes boolean arguments as numbers,
which can cause the heap to be overwritten when
used in conjunction with .NET COM objects.
Fix : In se501/src/lib/comobj/comobj.cpp,
around line 2372, in the SE_TYPE_BOOLEAN case
statement, there is a statement that looks like
this:
V_VT(pCurVar) = VT_R8 | passByRefValue;
Replace
that statement with this one:
V_VT(pCurVar) = VT_BOOL | passByRefValue;
Approximately ten lines below, within that same
case statement, there is a line that looks like
this:
V_R8(pCurVar) = lVar;
Replace
that statement with this one:
V_BOOL(pCurVar) = (short)lVar;
- COM
object methods returning an array may cause
an assertion
(for ISDK/C 5.01b)
Bug:
Calling a method of a COM object that returns
an array may cause an assertion around line
900 in src/lib/comobj/comobj.cpp, function CreateReturnedVariant().
Fix : In se501/src/lib/comobj/comobj.cpp,
around line 959, there is an else statement
containing a for loop that looks like this:
for( i = lowerBound; i <= upperBound; i++ )
{
VARIANT v;
indicies[dim] = i;
/* Get the element from the safe array */
/* I'm making an assumption here, which is the elements of the
* array will be VARIANTS.
*/
hr = SafeArrayGetElement(psa,indicies,&v);
if(FAILED(hr))
{
ReportComError( se, hr, &excepInfo );
}
CreateReturnedVariant(se,v,wName);
seAssign(se, seRet, SE_NUM(i), SE_RETURN, SE_VALUE);
sePutUndefined(se, SE_RETURN, SE_VALUE);
}
Replace
that entire for loop with this one:
for( i = lowerBound; i <= upperBound; i++ )
{
VARIANT v;
VARTYPE vt;
VariantInit(&v);
indicies[dim] = i;
/* Get the element from the safe array */
/* I'm making an assumption here, which is the elements of the
* array will be VARIANTS.
*/
hr = SafeArrayGetVartype(psa, &vt);
if(FAILED(hr))
{
ReportComError( se, hr, &excepInfo );
}
V_VT(&v) = vt;
switch (vt) /* default to original assumption of variant */
{
case VT_BOOL:
hr = SafeArrayGetElement(psa,indicies,&(V_BOOL(&v)));
break;
case VT_BSTR:
hr = SafeArrayGetElement(psa,indicies,&(V_BSTR(&v)));
break;
case VT_I4:
hr = SafeArrayGetElement(psa,indicies,&(V_I4(&v)));
break;
case VT_UI4:
hr = SafeArrayGetElement(psa,indicies,&(V_UI4(&v)));
break;
case VT_UI2:
hr = SafeArrayGetElement(psa,indicies,&(V_UI2(&v)));
break;
case VT_I2:
hr = SafeArrayGetElement(psa,indicies,&(V_I2(&v)));
break;
case VT_I1:
hr = SafeArrayGetElement(psa,indicies,&(V_I1(&v)));
break;
case VT_UI1:
hr = SafeArrayGetElement(psa,indicies,&(V_UI1(&v)));
break;
case VT_R4:
hr = SafeArrayGetElement(psa,indicies,&(V_R4(&v)));
break;
case VT_R8:
hr = SafeArrayGetElement(psa,indicies,&(V_R8(&v)));
break;
case VT_DECIMAL:
hr = SafeArrayGetElement(psa,indicies,&(V_DECIMAL(&v)));
break;
case VT_DATE:
hr = SafeArrayGetElement(psa,indicies,&(V_DATE(&v)));
break;
default:
hr = SafeArrayGetElement(psa,indicies,&v);
}
if(FAILED(hr))
{
ReportComError( se, hr, &excepInfo );
}
CreateReturnedVariant(se,v,wName);
seAssign(se, seRet, SE_NUM(i), SE_RETURN, SE_VALUE);
sePutUndefined(se, SE_RETURN, SE_VALUE);
}
- seGetSourceFunc()
being called an extra time for empty include
files
(for ISDK/C 5.01b)
Bug:
If a script uses the #include preprocessor directive
to include an empty file, the seGetSourceFunc()
gets called with the seSourceGetLine flag an
extra time after it returns False.
Fix : In se501/src/core/source.c, around
line 1069, there is a comment that says "/*
nothing was read at all */". It's in an
if statement that looks like this:
if( success )
{
if ( !sourceNextLine(*source,call,False,&success,True) )
{
/* nothing was read at all */
(*source)->MemoryPtr = UNISTR("");
}
}
Deleting
that whole "if( !success )" statement
and its contents fixes this bug.
- XML
object not trimming whitespace from tail of
incoming text elements
(for ISDK/C 5.01b)
Bug:
According to standard treatment of whitespace
in XML text elements, the whitespace at the
beginning and end of them should be discarded,
but the XML object was only discarding the leading
whitespace. This resulted in extra whitespace
at the end of text elements that were converted
to native objects from XML.
Fix : In se501/src/lib/xml/sexml.c,
around line 1070, just before a break statement,
add the following line of code:
RemoveWhitespaceFromHeadAndTail(text_elem);
- XML
object mistreating special 'tag' and 'attribute'
properties
(for ISDK/C 5.01b)
Bug:
The XML object is supposed recognize tag and
attribute properties as being special properties,
but the current implementation was not. This
resulted in extra elements in outputted XML,
and no attributes inside the tag itself.
Fix : First, be sure to apply previous
XML errata items. At line 1625 of se501/src/lib/xml/sexml.c,
in function obj_to_xml(), between the following
two lines of code:
concatenate_return_string(se,seGetString(se,obj,SEXML_TAG_MEMBER,NULL),True);
concatenate_return_string(se,UNISTR(">\n"),False);
..insert the following block of code:
if ( seExists(se,obj,SEXML_ATTRIBUTE_MEMBER) )
{
sememcount attrIndex;
seobject attrs = seGetObject(se,obj,SEXML_ATTRIBUTE_MEMBER);
sememcount lim = (sememcount)seGetLong(se,attrs,SE_STOCK(length));
for( attrIndex=0;attrIndex< lim;attrIndex++ )
{
seobject attr = seGetObject(se,attrs,SE_NUM(attrIndex));
concatenate_return_string(se,UNISTR(" "),False);
concatenate_return_string(se,seGetString(se,attr,SEXML_TAG_MEMBER,NULL),True);
concatenate_return_string(se,UNISTR("='"),False);
concatenate_return_string(se,seGetString(se,attr,SEXML_CONTENT_MEMBER,NULL),True);
concatenate_return_string(se,UNISTR("'"),False);
}
}
Also, at line 1668 of the same file and function,
replace the following line of code:
if( strcmp_sechar(name,UNISTR("tag"))==0 ) continue;
with this line of code:
if( stricmp_sechar(name,UNISTR("tag"))==0 || stricmp_sechar(name,UNISTR("attribute"))==0 ) continue;
- stricmp
not defined for sexml when built as dynamic
library on Unix platforms
(for ISDK/C 5.01b)
Bug:
The stricmp() function is not being defined
for Unix platform extlibs. Since the SEXML library
requires that function, compilation of the SEXML
library as an extlib dynamic library fails.
Fix : In src/misc/utilstr.c, at about
line 956 rename the stricmp_sechar() function
to be stricmp(). Then, in se501/lib/makefile,
around line 172, append the following line to
the end of the definition of SRCEXTLIB:
\
$(SEISDKC_HOME)/src/misc/utilstr.c
Also, append the following line to the end of
the definition of OBJEXTLIB around line 179:
\
seextlib/release/utilstr.o
Finally, append the following line to the end
of the definition of OBJEXTLIB.DBG around line
187:
\
seextlib/debug/utilstr.o
- seEval()
does not honor SE_INFREQUENT_CONT flag when
interpreting a function object
(for ISDK/C 5.01b)
Bug:
When calling seEval() to interpret a function
object (using the SE_FUNC interp_type flag)
in combination with the SE_INFREQUENT_CONT flag,
the SE_INFREQUENT_CONT flag will be ignored.
This results in the application's seContinueFunc
to get called far more frequently than would
be expected.
Fix : In src/core/se501.c, function
seEvalFunc(), at about line 5911 replace the
following statement:
call->resetContinueCount = ( (flags & JSE_INTERPRET_INFREQUENT_CONT) != 0 ) ?
(uword32)JSE_INFREQUENT_COUNT : 1 ;
with this one:
call->resetContinueCount = ( (flags & SE_INFREQUENT_CONT) != 0 ) ? (uword32)JSE_INFREQUENT_COUNT : 1 ;
- XML
object creates faulty output sometimes
(for ISDK/C 5.01b)
Bug:
The output generation code in the SEXML library
doesn't output the correct XML markup when an
object has a property that is an Array, or if
the object has the special .tag and .element
properties
Fix : Replace se501/src/lib/xml/sexml.c
with the one located here: ftp://ftp.nombas.com/pub/isdkeval/se501/sexml.c
- XML.toText(),
XML.toFile() including SE_DONTENUM properties
in output
(for ISDK/C 5.01b)
Bug:
The output generation code in the SEXML library
includes object properties marked as SE_DONTENUM
in the text it outputs. This results in incorrect
XML output, and can sometimes result in an infinite
recursion.
Fix : In src/lib/xml/sexml.c, function
obj_to_xml(), at about line 1637 (below the
statement "seconstcharptr name = seObjectMemberName(se,obj,SE_INDEX(i),NULL);")
add the following statement:
if ( seGetAttribs(se, obj, SE_INDEX(i)) & SE_DONTENUM )
{
continue;
}
- string.replace
can crash or return incorrect results when \b
is used at the beginning of a regular expression
(for ISDK/C 5.01b)
Bug:
String.prototype.replace() can crash when built
in MBCS mode, or give incorrect results when
built in ASCII or UNICODE modes, when a regular
expression starting with \b is passed as the
first argument. Here is an example of what can
cause a crash:
"foo car".replace(/\bc/g, "b")
Fix : In src/lib/ecma/seregex.c, function
seregex_match(), at about line 1398 (below the
comment "/* match word boundary */") change
this statement
a = IsWordCharAtPosition(stringStart,stringEnd,PREVIOUS_SECHARPTR(execute.str,stringStart));
to
be
a = ( execute.str == stringStart ) ? False :
IsWordCharAtPosition(stringStart,stringEnd,PREVIOUS_SECHARPTR(execute.str,stringStart));
- string.split
is not ignoring the global flag on regular expressions
(for ISDK/C 5.01b)
Bug:
String.prototype.split() should ignore the global
flag if it is set on the matching regular expression,
according to the final note in section 15.5.4.14
of the EcmaScript. The ScriptEase engine is
not ignoring that flag.
Fix : In src/lib/ecma/seobject.c, function
SplitMatch(), at about line 2830 change this
block
struct seEvalParams params;
seobject tmpObj;
memset(¶m,0,sizeof(params));
params.default_this = R
to
be
struct seEvalParams params;
seobject tmpObj;
sebool restore_global_flag = seGetBool(se,R,SE_STOCK(global));
/* split should ignore the global flag */
if ( restore_global_flag )
seMustPutBool(se,R,SE_STOCK(global),False);
memset(¶ms,0,sizeof(params));
params.default_this = R;
and
near the end of that block, around line 2850,
change this block
else { ret = NULL; } seFreeObject(se,tmpObj); } seFreeObject(se,stack);
to
be
else { ret = NULL; } seFreeObject(se,tmpObj); if ( restore_global_flag ) seMustPutBool(se,R,SE_STOCK(global),True); } seFreeObject(se,stack);
- assert
or invalid global pop on seExec() if params
supplied to seStart()
(for ISDK/C 5.01b)
Bug:
If seEval(...SE_START...,params) is called with
params!=NULL, then an ASSERT may be triggered
or an invalid global may be restored at the
end of seExec() or seEnd().
Fix : In src/core/call.h, change both
instances (around lines 1132 and 1324) of
struct seEvalParams *params
with
uword8 pop_global_on_seEnd
and
in src/core/se501.c, function seEvalFunc(),
replace (near line 5981)
start_info->params = params;
with
start_info->pop_global_on_seEnd = params!=NULL && params->global!=NULL;
and
in function seEval(), replace (near line 6519)
newc->params = params;
with
newc->pop_global_on_seEnd = params!=NULL && params->global!=NULL;
and
in function seExec() replace (near line 6678)
if( call->start_info->params!=NULL && call->start_info->params->global!=NULL )
with
if( call->start_info->pop_global_on_seEnd )
and
replace (near line 6703)
sebool need_to_restore = call->params!=NULL && call->params->global!=NULL;
with
sebool need_to_restore = call->pop_global_on_seEnd;
and
in function seEnd() replace (near line 6737)
sebool need_to_restore = call->params!=NULL && call->params->global!=NULL;
with
sebool need_to_restore = call->pop_global_on_seEnd;
and
finally replace (near line 6763)
if( call->start_info->params!=NULL && call->start_info->params->global!=NULL )
with
if( call->start_info->pop_global_on_seEnd )
- internal
function may cause assertion in call.c
(for ISDK/C 5.01b)
Issue:
A function containing an inner function may
cause an assertion to be thrown around line
774 (`SEVAR_GET_TYPE(wv)>=VReference').
Fix : In src/core/se501.c around line
5916 there is a block of code like this:
if( flags&SE_START )
{
struct evalFuncStart *start_info;
start_info = (struct evalFuncStart *)secoreAlloc(call,NULL,sizeof(struct evalFuncStart),SE_DEFAULT);
On
the line just above that if statement, add this
statement:
SEVAR_INIT_UNDEFINED(CALL_NEWSCOPE(call));
- string.replace()
may get caught in near-infinite loop
(for ISDK/C 5.01b)
Issue:
If string.replace() is called using the global
flag and such that the result of the search
expression replaces the null-patch at the end
of the line, then replace may run for a long
long while (until a memory object is returned).
This is an example of a problem script.
"a".replace( /a*/g, "stuff" );
Fix : In src/lib/ecma/seobject.c make
the following changes:
1)
near line 3492 replace the definition of the
replace_string() function from this:
static void JSE_NEAR_CALL replace_string(...
to
this
static sememcount JSE_NEAR_CALL replace_string(...
2)
replace the last line of the replace_string()
function (around line 3686) from this:
return;
to this
return replace_len;
3)
in function string_which_search_helper(), near
line 3762, follow this line:
seobject eval_ret = seGetObject(se,SE_RETURN,SE_VALUE);
with
this additional line
sememcount replace_len = 0;
and
about seven lines below that replace
replace_string(se,temp = ...
with
replace_len = replace_string(se,temp = ...
4)
around line 3788 of the same function replace
this block
if( new_index==last_index )
{
new_index++;
with
this
if( new_index == (slong)(last_index+replace_len) )
{
new_index = 1 + (last_index+replace_len);
-
Variable scoping incorrect
within nested functions
(for ISDK/C 5.01b)
Issue:
This issue is best described by the following
script:
function foo()
{
var a = 7;
function foo1()
{
function foo2()
{
return a;
}
return foo2();
}
return foo1();
}
var x = foo();
Currently,
the nested function foo2() cannot find the variable
"a", resulting in an error being thrown.
Fix : In src/core/call.c, function
callFunction(), around line 747 there is a comment
that starts
/* Build the saved scope chain ...
A
few lines below that is a for( ; ; ) loop. After
that for loop add this block of code:
/* Now add the current function's saved scope chain to the new scope
* chain we are creating.
*/
if ( funcvar->data.object_val.hSavedScopeChain != NULL )
{
sememcount lookin;
sememcount used;
hSEObject cur_chain;
HSEOBJECT_BRUTE_ASSIGN(cur_chain,funcvar->data.object_val.hSavedScopeChain);
used = SEOBJECT_GET(call,cur_chain,used);
for ( lookin = 0; lookin<used; lookin++ )
{
hSEMembers mems;
wSEVar tmp;
mems = SEOBJECT_GET(call,cur_chain,hsemembers);
LOCK_READ_MEMBERS(call,mems);
tmp = STACK_PUSH;
SEVAR_COPY(tmp,SEMEMBERS_GET_sevar(call,mems,lookin));
SEASSERT( SEVAR_GET_TYPE(SEMEMBERS_GET_sevar(call,mems,lookin))==VObject );
seobjCreateMemberCopy(call,new_chain,SE_NO_VARNAME,tmp,SE_DEFAULT);
STACK_POP;
}
}
-
string.replace()
incorrect if first arguments is not a RegExp
object
(for ISDK/C 5.01b)
Bug: If the first parameter to String.prototype.replace()
is not a RegExp object then it will be compiled
into a RegExp object. This is incorrect behavior
and based on an incomplete version of the EcmaScript
specification. Instead, if the first arguments
is not a RegExp object then it should be converted
into a string and a direct string replacement
should follow.
Fix : In src/lib/ecma/seobject.c, replace
the function Ecma_String_replace() at about
line 4022 with the code at ecma_string_replace.c
-
invalid
debug assertion if seContinueFunc() sets SE_RETURN,SE_ERROR
during script return statement
(for ISDK/C 5.01b)
Problem: If a script happens to be executing
a return statement when seContinueFunc() is
called and sets the SE_RETURN,SE_ERROR flag,
then an SE_ASSERT() statement will be triggered.
That SE_ASSERT should not be triggered.
Fix : In src/core/secode.c, function
secodeInterpret(), within "case seReturnExpr:"
around line 2639, change this code:
if ( !run_iterative )
callMayIContinue(call);
to
this
if ( !run_iterative && !callMayIContinue(call) )
{
callError(call,textcoreMAYICONTINUE);
return False;
}
for
5.01a --
-
seGetSourceFunc() callback being called
an extra time when script is missing a closing
brace
(for ISDK/C 5.01a)
Issue: When a script that is missing a closing
brace ('}') is being compiled by the ScriptEase
engine, the seGetSourceFunc() callback of the
seContextParams structure gets called by the
engine with the seSourceGetLine flag one time
too many. That is to say, after the seGetSourceFunc()
has been called with the seSourceGetLine flag
and has returned False once, on the next call
to seGetSourceFunc() the ScriptEase engine should
pass it the seSourceClose flag, but instead
the engine calls it one more time passing it
the seSourceGetLine flag before calling it a
final time passing it the seSourceClose flag.
This can be a source of error if the seGetSourceFunc()'s
seSourceGetLine handler does not expect to be
called anymore once it has returned False to
the ScriptEase engine.
Fix : To fix this issue, go to the
secompileStatement() function in src/core/statemnt.c.
Within the switch statement, there is a case
statement for the character '{'. In that case
statement (at approx. line 975), add the following
code inside the while() loop, before the code
already in that loop:
if ( tokType(This->token)==seTokEOF )
{
success = False;
callQuit(call, textcoreBAD_PRIMARY);
break;
}
So
now your while() loop should look like this:
while( tokType(This->token)!='}' )
{
if ( tokType(This->token)==seTokEOF )
{
success = False;
callQuit(call, textcoreBAD_PRIMARY);
break;
}
if( !secompileStatement(This) )
{
success = False;
break;
}
}
-
seExec() returning prematurely when SE_INFREQUENT_CONT
flag used to initialize secontext
(for ISDK/C 5.01a)
Bug: seExec() returns on any throw statement
(caught or uncaught), regardless of the SE_INFREQUENT_CONT
flag being used to initialize the context
Fix : To fix the source code in src/core/secode.c,
function secodeInterpret(), at about line 744
replace:
return secode_reasonToQuit(call,False);
with
if ( !(ret = secode_ReasonToQuit(call,False,return_immediate_from_any_seReturn)) ||
return_immediate_from_any_seReturn )
{
return ret;
}
-
seMustPutXXX() and seMustPutDirectXXX()
unsetting most variable attributes
(for ISDK/C 5.01a)
Bug: The seMustPutXXX() and seMustPutDirectXXX()
functions strip variable attributes, such as
SE_DONTENUM and SE_READONLY, from the variable
on which they are called.
Fix : A simple workaround is to call
seSetAttribs after calling seMustPutXXX() and
seMustPutDirectXXX(). Or to fix the source code
in src/core/se501.c, function sePutMember(),
at about line 3225 replace:
seobjNewMember(call,obj,name,tmp,SE_DEFAULT,SE_NM_UPDATE);
with
seobjNewMember(call,obj,name,tmp,attr,SE_NM_UPDATE);
Also, at about line 3292 replace:
seobjNewMember(call,obj,name,tmp,SE_DEFAULT,SE_NM_UPDATE);
with
seobjNewMember(call,obj,name,tmp,attrib,SE_NM_UPDATE);
- sePutWrapper()
ignoring the varFlags (variable attributes)
parameters
(for ISDK/C 5.01a)
Bug:
The sePutWrapper() varFlags parameter (used
to set variable attributes such as SE_DONTENUM)
is being ignored.
Fix:
A simple workaround is to call seSetAttribs
after calling sePutWrapper(). Or to fix the
source code in src/core/se501.c, function sePutWrapperEx(),
at about line 5073 replace:
sePutMember(call,obj,type,memdata,flags,temp_put);
with
if ( !sePutMember(call,obj,type,memdata,flags,temp_put)
|| SE_DEFAULT != varFlags )
{
if ( !IS_STOCK_OBJ(obj) )
seSetAttribs(se,obj,type,memdata,(seAttributes)varFlags);
}
- SEDBC
library sometimes references uninitialized variables
(for ISDK/C 5.01a)
Problem:
In src/lib/sedbc/jse_rs_s.c, some variables
can be referenced before they are initialized
due to two continue statements
preceeding their initializations.
Fix:
In src/lib/sedbc/jse_rs_s.c, function FindSQLToken(),
initialize the variables bInLiteral, bInBrackets,
nLeftBrackets, and nRightBrackets before the
continue statements; for instance,
at line 45 instead of line 69.
- SEDBC
library allocates unnecessary memory on stack
(for ISDK/C 5.01a)
Problem:
In src/lib/sedbc/jse_db.c, a few buffers were
being allocated on the stack instead of on the
heap, which caused some embedded platforms to
run out of stack space.
Fix:
In src/lib/sedbc/jse_db.c, function BuildErrorString(),
declare the variables named lpszMsg, lpszState,
and lpszNative as sedbccharptr's instead of
sedbcchar arrays. Next allocate memory to those
variables as shown below:
lpszMsg = (sedbccharptr)seGCMalloc(sedbc->se, \
(sememcount)((SQL_MAX_MESSAGE_LENGTH + 1) * sizeof(sedbcchar)));
lpszState = (sedbccharptr)seGCMalloc(sedbc->se, \
(sememcount)((SQL_SQLSTATE_SIZE + 1) * sizeof(sedbcchar)));
lpszNative = (sedbccharptr)seGCMalloc(sedbc->se, \
(sememcount)(50 * sizeof(sedbcchar)));
Then
at the end of the function, below the func_exit
label, free that memory using seGCFree().
- Math.random()
is not very random on systems with 16-bit integers
(for ISDK/C 5.01a)
Bug:
On systems compiled with 16-bit integers, Math.random()
always generates numbers very close to 0.0 or
1.0 (e.g. 0.0545345 or 0.992322), and not well-spread
between 0 and 1.
Fix:
In src/lib/ecma/mathobj.c, function Ecma_Math_random(),
change this line:
int r[5];
to
this:
uword32 r[5];
- Date
parser not recognizing 12 AM or "UTC"
(for ISDK/C 5.01a)
Problem:
When parsing a date/time with "12:00 AM
UTC" the date parser is not recognizing
this as midnight, but is instead registering
that time as noon. Also, although the ECMAScript
specification sets "GMT" as the tag
for declaring universal time, it has become
common to also use "UTC".
Change:
In src/lib/ecma/sedate.c, function do_parse(),
at around line 852, just before the comment
that begins "/* if there is a PM anywhere..."
add this code:
/* if it is 12, but 12 AM, then that time is really 0 */
if ( time[0] == 12 && strstr_sechar(DateBuf,UNISTR("am")) )
time[0] = 0;
and
then at about line 974 change this code
gmt = strstr_sechar(DateBuf,UNISTR("gmt"));
if ( gmt == NULL )
to
this
if ( NULL == (gmt = strstr_sechar(DateBuf,UNISTR("gmt")))
&& NULL == (gmt = strstr_sechar(DateBuf,UNISTR("utc"))) )
Function
constructor causes swapping for created functions
(for ISDK/C 5.01a)
Problem:
When JSE_MULTIPLE_GLOBAL is defined (the default),
any anonymous function created at runtime with
the Function constructor will preserve the global
from when the Function library was loaded (usually
at program initialization). This will cause
the global to change to the original global
whenever that anonymous function is later called.
Change:
To keep the Function constructor from restoring
its own global replace add the SE_KEEP_GLOBAL
line 2296 of src/lib/ecma/seobject.c so it becomes:
SE_CLASS( JseStr(se,Function), Ecma_Function_construct, 0, -1, \
SE_SECURE|SE_KEEP_GLOBAL, SE_DONTENUM )
- String
match function should return null on no match
(for ISDK/C 5.01a)
Issue:
According to the commonly recognized ECMAScript
Edition 3 Errata, string.match should return
NULL if there are no items matched. This differs
from the ECMAScript document, and from our 5.01a
code, which would return a zero-length array.
Change:
To get the return-null behavior, In src/lib/ecma/seobject.c,
near the end of string_which_search_helper()
(at about line 3839) replace this code:
if( mode==SE_MATCH_MODE )
{
sePutObject(se,SE_RETURN,SE_VALUE,ret);
}
with
if( mode==SE_MATCH_MODE )
{
#if 1 /* this part of the code is a result of the ECMA-262 errata */
if ( array_index == 0 )
sePutNull(se,SE_RETURN,SE_VALUE);
else
#endif
sePutObject(se,SE_RETURN,SE_VALUE,ret);
}
- seGetSourceFunc(...seSourceGetLine...)
called twice if first call returns False
(for ISDK/C 5.01a)
Bug:
If seGetSourceFunc(...seSourceGetLine...) (aka
seGetSourceFunc(...SE_SOURCE_GETLINE...)) returns
False the first time it is called, it will be
called again a second time.
Fix:
In src/core/source.c, function sourceNewFromFile(),
change the code after !sourceNextLine() (around
line 545) from:
This->MemoryPtr = UNISTR("");
to
*Success = False;
- SE_GF_NOCALLBACKS
errata fix causes SE_GF_DIRECT failure on strings
(for ISDK/C 5.01a)
Bug:
After apply the SE_GF_NOCALLBACKS errata posted
below, calls to sePutDirectString() or sePutStringEx(...SE_GF_DIRECT)
will cause memory allocation errors.
Fix:
After applying the errata posted
below, edit src/include/se501.h and change
(near line 632):
#define SE_PS_USEPOINTER 0x004
#define SE_PS_BORROWPOINTER 0x008
to
#define SE_PS_USEPOINTER 0x020
#define SE_PS_BORROWPOINTER 0x040
- memory
leak with array.toSource
(for ISDK/C 5.01a)
Bug:
A memory buffer remains unreleased for each
call to Array.prototype.toSource. This would
happen any time ToSource is applied to an instance
of an Array, or to any object containing an
instance of an Array.
Fix:
In src/lib/ecma/seobject.c, function Ecma_Array_toSource,
the following should be added as the last line
of the function at about line 1465:
dynamicBufferTerm(&buffer);
- string.split
returns undefined element 0 if no match
(for ISDK/C 5.01a)
Bug:
If String.prototype.split(delimeter) is called,
but there is no delimeter matched, then this
function should return a 1-element array with
the original string as element 0. Instead it
is wrongly returning and undefined type as element
0.
Fix:
In src/lib/ecma/seobject.c, function Ecma_String_split,
at about line 2945 this statement:
seAssign(se,ret,SE_NUM((sememcount)seGetLong(se,ret,SE_STOCK(length))),
SE_WRAPPER_TEMP, SE_MEM("temp"));
should
be changed to:
sePutString(se,ret,SE_NUM((sememcount)seGetLong(se,ret,SE_STOCK(length))),str,s);
- converting
a recursive array to a string can crash
(for ISDK/C 5.01a)
Bug:
In an array contains a recursive element that
recursively refers back to the array, and if
the array is then converted to a string, then
the scriptease engine will crash. The following
script demonstrates the problem:
var a = new Array( "a", "b", "c" );
a[1] = new Array( a, 2, 3 );
var foo = "" + a; // will crash here from recursion
Fix:
In src/lib/ecma/seobject.c, function Ecma_Array_join,
after the declaration of variables (around line
662) add this block:
#define PREVENT_RECURSION_NAME "join recursed"
/* if this object was already visited, then just return a blank string */
if ( seExists(se,SE_THIS,SE_HIDDEN_MEM(PREVENT_RECURSION_NAME)) )
{
sePutString(se,SE_RETURN,SE_VALUE,UNISTR(""),0);
return;
}
sePutBool(se,SE_THIS,SE_HIDDEN_MEM(PREVENT_RECURSION_NAME),True);
and
add the following as the final line of function
Ecma_Array_join:
seDelete(se,SE_THIS,SE_HIDDEN_MEM(PREVENT_RECURSION_NAME));
- no
flag provided to bypass dynamic callbacks, but
allow for prototype chain
(for ISDK/C 5.01a)
Bug:
SE_GF_DIRECT (as used by the seGetDirect and
seGetEx calls) bypasses the dynamic callbacks
and the prototype chain. SE_GF_NOPROTOTYPE bypasses
the prototype chain but not the callbacks. There
is no corresponding call to skip dynamic callbacks
but still allow access via the prototype chain.
Fix:
Add a new SE_GF_NOCALLBACKS option to bypass
callbacks but still allow access via the prototype
chain. This fix assumes that the
HP_DIRECTCHECK errata has already been applied.
In src\include\se501.h
at about line 617 replace this line:
#define SE_GF_DIRECT 0x001
with
these two lines:
#define SE_GF_NOCALLBACKS 0x001
#define SE_GF_DIRECT (SE_GF_NOPROTOTYPE|SE_GF_NOCALLBACKS)
and
in src/core/var.h, near line 363 change
#define GV_NO_PROTOTYPE 1
#define GV_NO_DYNAMIC 2
to
#define GV_NO_PROTOTYPE SE_GF_NOPROTOTYPE
#define GV_NO_DYNAMIC SE_GF_NOCALLBACKS
and
then in src/core/se501.c change every reference
from
SE_GF_DIRECT
to
SE_GF_NOCALLBACKS
and
also in src/core/se501.c, function seGetMember(),
at around line 2574 change
direct = TRUE;
to
flags |= SE_GF_NOCALLBACKS;
finally,
about 17 lines later, replace this block:
int f = ( (flags & SE_GF_DIRECT) || direct )
? ( GV_NO_PROTOTYPE | GV_NO_DYNAMIC )
: ( ( flags & SE_GF_NOPROTOTYPE ) ? GV_NO_PROTOTYPE : GV_DEFAULT );
SEVAR_INIT_OBJECT(tmpobj,obj);
ret = sevarGetValue(call,tmpobj,name,temp_get,f);
with
this
SEVAR_INIT_OBJECT(tmpobj,obj);
ret = sevarGetValue(call,tmpobj,name,temp_get,flags);
After
applying this fix be sure to also apply the
SE_GF_DIRECT failure on strings fix posted
above.
- calling
byref function turns all local variables into
references
(for ISDK/C 5.01a)
Bug:
If a byref function is called from within another
function, all of the local variables in the
outer function will be turned into references.
Fix:
In src/core/secode.c, function secodeInterpret(),
near line 829 this block of code:
#if JSE_PASSBYREF==1
if ( FUNCTION_PASSBYREF(function)
|| ( FUNCTION_IS_LOCAL(function)
&& with_tmp < ((struct LocalFunction*)function)->localItems.InputParameterCount
&& ((struct LocalFunction*)function)->localItems.items[with_tmp].passByRef ) )
{
/* In this case we have pass-by-reference */
SEVAR_INIT_UNDEFINED(w_lhs);
if( CALL_VAROBJ(call)==hSEObjectNull )
callCreateVariableObject(call,NULL,0);
}
#endif
SEVAR_COPY(w_lhs,w_rhs);
should
be changed to this code:
#if JSE_PASSBYREF==1
if ( FUNCTION_PASSBYREF(function)
|| ( FUNCTION_IS_LOCAL(function)
&& with_tmp < ((struct LocalFunction*)function)->localItems.InputParameterCount
&& ((struct LocalFunction*)function)->localItems.items[with_tmp].passByRef ) )
{
/* In this case we have pass-by-reference */
SEVAR_INIT_UNDEFINED(w_lhs);
if( CALL_VAROBJ(call)==hSEObjectNull )
callCreateVariableObject(call,NULL,0);
SEVAR_COPY(w_lhs,w_rhs);
}
else
{
/* The local variable could be a reference into the variable object.
* If this is true, it will be passed by reference even though it
* should not be. To avoid this, we now copy the variable to the stack
* and dereference it.
*/
SEVAR_COPY(w_lhs,w_rhs);
SEVAR_DEREFERENCE(call,w_lhs);
}
#else
/* No pass by reference, so just copy the variable to the stack */
SEVAR_COPY(w_lhs,w_rhs);
#endif
- too
many callbacks for global get and for hasprop
returning HP_DIRECTCHECK
(for ISDK/C 5.01a)
Bug:
If the global object has a get callback, then
get is called too often while initializing code.
Also, if any hasProp callback is returning HP_DIRECTCHECK
then the get callback is being called, although
it shouldn't.
Fix:
In src/core/call.c, function callFunction(),
near line 768 this block of code:
wSEVar wLoc = STACK_PUSH;
wSEVar wTmp = STACK_PUSH;
SEVAR_INIT_UNDEFINED(wTmp);
SEVAR_INIT_OBJECT(wLoc,CALL_VAROBJ(call));
GetDotNamedVar(call,wLoc,GetSEStringTableEntry(call,ourname,NULL),GDNV_DONT_DELETE);
if( hif_func!=hSEObjectNull )
{
SEVAR_INIT_OBJECT(wTmp,hif_func);
if ( VObject == SEVAR_GET_TYPE(CALL_NEWSCOPE(call)) )
{
hSEObject hobj;
HSEOBJECT_BRUTE_ASSIGN(hobj,SEVAR_GET_OBJECT(CALL_NEWSCOPE(call)));
SEASSERT( hSEObjectNull != hobj );
if( 0data.object_val.hSavedScopeChain,hobj);
}
}
}
else
{
SEVAR_INIT_UNDEFINED(wTmp);
}
should
be changed to this code:
wSEVar wLoc = STACK_PUSH;
wSEVar wTmp = STACK_PUSH;
if( hif_func != hSEObjectNull )
{
SEVAR_INIT_OBJECT(wTmp,hif_func);
SEVAR_INIT_OBJECT(wLoc,CALL_VAROBJ(call));
GetDotNamedVar(call,wLoc,GetSEStringTableEntry(call,ourname,NULL),GDNV_DONT_DELETE);
if ( VObject == SEVAR_GET_TYPE(CALL_NEWSCOPE(call)) )
{
hSEObject hobj;
HSEOBJECT_BRUTE_ASSIGN(hobj,SEVAR_GET_OBJECT(CALL_NEWSCOPE(call)));
SEASSERT( hSEObjectNull != hobj );
if( 0<SEOBJECT_GET(call,hobj,used) )
{
HSEOBJECT_INIT_ASSIGN(wTmp->data.object_val.hSavedScopeChain,hobj);
}
}
}
else
{
SEVAR_INIT_UNDEFINED(wTmp);
SEVAR_INIT_REFERENCE(wLoc,CALL_VAROBJ(call),ourname);
}
Then
in src/core/se501.c function seGetMember(),
near line 2547 (about 22 lines below the "not_there:"
target), replace the else block that begins
with this line:
wSEVar tmpobj = STACK_PUSH;
with
this block
wSEVar tmpobj = STACK_PUSH;
sebool direct = FALSE;
#if JSE_DYNAMIC_CALLBACKS==1
ret = TRUE;
SEVAR_INIT_UNDEFINED(tmpobj);
/* If the object says it does not have the property,
* believe it. Return FALSE with the undefined value.
*/
if( (flags&SE_GF_DIRECT)==0
&& SEOBJ_IS_DYNAMIC_PROP(call,obj,hasProp)
&& !IS_HIDDEN_PROP(name) )
{
if( seobjCallDynamicProperty(call,obj,SE_HASPROP_CALLBACK,name,NULL,tmpobj) )
{
if ( HP_HASNOT == SEVAR_GET_SLONG(tmpobj) )
{
ret = FALSE;
SEVAR_INIT_UNDEFINED(temp_get);
}
}
else
{
if ( VNumber == SEVAR_GET_TYPE(tmpobj) )
{
if ( HP_DIRECTCHECK == SEVAR_GET_SLONG(tmpobj) )
direct = TRUE;
}
}
}
ELSE_ALWAYS_COLLECT(call)
if( ret )
#else
/* above calldyna would have caused GC */
ALWAYS_COLLECT(call)
#endif
{
int f = ( (flags & SE_GF_DIRECT) || direct )
? ( GV_NO_PROTOTYPE | GV_NO_DYNAMIC )
: ( ( flags & SE_GF_NOPROTOTYPE ) ? GV_NO_PROTOTYPE : GV_DEFAULT );
SEVAR_INIT_OBJECT(tmpobj,obj);
ret = sevarGetValue(call,tmpobj,name,temp_get,f);
}
STACK_POP;
And
in src/core/varutil.c, function seobjCallDynamicProperty(),
replace "case SE_HASPROP_CALLBACK:" around line
2300 with this code:
case SE_HASPROP_CALLBACK:
{
int cp = DYNA_CALLBACK1(callbacks->hasProp,prop_name);
if ( cp < 0 )
{
SEASSERT( cp==HP_CHECK || cp==HP_DIRECTCHECK );
done = False;
}
else
{
SEASSERT( cp==HP_HAS || cp==HP_HASNOT );
}
SEASSERT( result!=NULL );
SEVAR_INIT_SLONG(result,cp);
break;
}
then
around line 2665 replace these lines:
STACK_POP;
/* Call the 'get' to get the property */
with
this block
else
{
if ( VNumber == SEVAR_GET_TYPE(value) )
{
if ( HP_DIRECTCHECK == SEVAR_GET_SLONG(value) )
{
STACK_POP; /* value */
goto standard_directcheck;
}
}
}
STACK_POP; /* value */
/* Call the 'get' to get the property */
finally,
around line 2719 replace this code
# else
/* on some occasions calldyna will happen and GC may happen, so force it always */
with
this (only a label is added)
standard_directcheck:
# else
/* on some occasions calldyna will happen and GC may happen, so force it always */
- hang
on assigning to undefined variable if global
object is SE_DYNA_UNDEF
(for ISDK/C 5.01a)
Bug:
If the global object is dynamic (i.e. setSetCallbacks
has been called on SE_GLOBAL), and if jseopt.h
defines JSE_CACHE_GLOBAL_VARS, and if a property
of the global is of type undefined, then assigning
to that property will result in an assertion
being raised (if a debug build) or in the engine
haning in an infinite loop.
Fix:
In src/core/call.c, function secoreFindAnyVar(),
at about line 1899, change this code:
# if JSE_DYNAMIC_CALLBACKS==1
if ( obj_flag==0 || VUndefined != SEVAR_GET_TYPE(wslot) )
# endif
to
this
# if JSE_DYNAMIC_CALLBACKS==1
if ( !(obj_flag==0 || VUndefined != SEVAR_GET_TYPE(wslot)) )
wslot = STACK0;
else
# endif
- Clib.fread()
leaves unread parts of buffers uninitialized
(for ISDK/C 5.01a)
Bug:
If Clib.fread(...buffer_size...) reads less
than buffer_size bytes, then the buffer size
will be created large enough for buffer_size
bytes and the parts of the buffer beyond what
are read will be uninitialized and may contain
random data. Instead, the buffer should not
be expanded beyond the number of bytes that
are read.
Fix:
Replace the Clib_fread() function in src/lib/clib/sestdio.c
with the code at clib_fread.c
- Alignment
errors with Clib *printf and *scanf floating-point
on HP-UX
(for ISDK/C 5.01a)
Bug:
If a call to the Clib *printf or *scanf methods
(e.g. Clib.sprintf) contains non-floating-point
data types following a floating-point type,
data alignment may be incorrect and invalid
data or crashes will result. This problem appears
only on HPUX systems.
Fix:
Replace src/lib/clib/sefmtio.c with the file
at sefmtio.c
|