var behaves like let
This commit is contained in:
@@ -7,6 +7,7 @@ var SYSYM = '__SYSTEM__'
|
||||
var hidden = _cell.hidden
|
||||
|
||||
var os = hidden.os;
|
||||
|
||||
_cell.os = null
|
||||
|
||||
var dylib_ext
|
||||
@@ -412,6 +413,8 @@ globalThis.parallel = pronto.parallel
|
||||
globalThis.race = pronto.race
|
||||
globalThis.sequence = pronto.sequence
|
||||
|
||||
|
||||
|
||||
$_.time_limit = function(requestor, seconds)
|
||||
{
|
||||
if (!pronto.is_requestor(requestor))
|
||||
@@ -486,6 +489,8 @@ _cell.config = config
|
||||
ENETSERVICE = config.net_service
|
||||
REPLYTIMEOUT = config.reply_timeout
|
||||
|
||||
|
||||
|
||||
/*
|
||||
When handling a message, the message appears like this:
|
||||
{
|
||||
@@ -516,8 +521,6 @@ function guid(bits = 256)
|
||||
return text(guid,'h')
|
||||
}
|
||||
|
||||
var _Symbol = Symbol
|
||||
|
||||
var HEADER = _Symbol()
|
||||
|
||||
// takes a function input value that will eventually be called with the current time in number form.
|
||||
@@ -891,12 +894,13 @@ function handle_actor_disconnect(id) {
|
||||
|
||||
function handle_sysym(msg)
|
||||
{
|
||||
var from
|
||||
switch(msg.kind) {
|
||||
case 'stop':
|
||||
disrupt("got stop message")
|
||||
break
|
||||
case 'underling':
|
||||
var from = msg.from
|
||||
from = msg.from
|
||||
var greeter = greeters[from[ACTORDATA].id]
|
||||
if (greeter) greeter(msg.message)
|
||||
if (msg.message.type == 'disrupt')
|
||||
@@ -911,7 +915,7 @@ function handle_sysym(msg)
|
||||
} else throw new Error('Got a contact message, but no portal is established.')
|
||||
break
|
||||
case 'couple': // from must be notified when we die
|
||||
var from = msg.from
|
||||
from = msg.from
|
||||
underlings.add(from[ACTORDATA].id)
|
||||
log.system(`actor ${from} is coupled to me`)
|
||||
break
|
||||
@@ -977,7 +981,6 @@ if (!locator)
|
||||
|
||||
// Hide JavaScript built-ins - make them inaccessible
|
||||
// Store references we need internally before deleting
|
||||
var _Object = Object
|
||||
var _Array = Array
|
||||
var _String = String
|
||||
var _Number = Number
|
||||
@@ -1046,7 +1049,7 @@ $_.clock(_ => {
|
||||
// Get capabilities for the main program
|
||||
var file_info = shop.file_info ? shop.file_info(locator.path) : null
|
||||
var inject = shop.script_inject_for ? shop.script_inject_for(file_info) : []
|
||||
|
||||
|
||||
// Build values array for injection
|
||||
var vals = []
|
||||
for (var i = 0; i < inject.length; i++) {
|
||||
@@ -1055,15 +1058,15 @@ $_.clock(_ => {
|
||||
if (key == 'fd') vals.push(fd)
|
||||
else vals.push($_[key])
|
||||
}
|
||||
|
||||
|
||||
// Create use function bound to the program's package
|
||||
var pkg = file_info ? file_info.package : null
|
||||
var use_fn = function(path) { return shop.use(path, pkg) }
|
||||
|
||||
|
||||
// Call with signature: setup_module(args, use, ...capabilities)
|
||||
// The script wrapper builds $_ from the injected capabilities for backward compatibility
|
||||
var val = locator.symbol.call(null, _cell.args.arg, use_fn, ...vals)
|
||||
|
||||
|
||||
if (val)
|
||||
throw new Error('Program must not return anything');
|
||||
})
|
||||
|
||||
@@ -63,7 +63,7 @@ var dylib_ext = '.dylib' // Default extension
|
||||
|
||||
var use_cache = os.use_cache
|
||||
var global_shop_path = os.global_shop_path
|
||||
var $_ = os.$_
|
||||
var my$_ = os.$_
|
||||
|
||||
Shop.get_package_dir = function(name) {
|
||||
return global_shop_path + '/packages/' + name
|
||||
@@ -385,7 +385,7 @@ function inject_values(inject) {
|
||||
for (var i = 0; i < inject.length; i++) {
|
||||
var key = strip_dollar(inject[i])
|
||||
if (key == 'fd') vals.push(fd)
|
||||
else vals.push($_[key])
|
||||
else vals.push(my$_[key])
|
||||
}
|
||||
return vals
|
||||
}
|
||||
@@ -400,23 +400,7 @@ var script_form = function(path, script, pkg, inject) {
|
||||
var pkg_arg = pkg ? `'${pkg}'` : 'null'
|
||||
var params = inject_params(inject)
|
||||
|
||||
// Build $_ object from injected capabilities for backward compatibility
|
||||
var build_compat = ''
|
||||
if (inject && inject.length) {
|
||||
var compat_props = []
|
||||
for (var i = 0; i < inject.length; i++) {
|
||||
var name = inject[i]
|
||||
var key = name
|
||||
if (key && key[0] == '$') key = key.substring(1)
|
||||
compat_props.push(key + ': ' + name)
|
||||
}
|
||||
build_compat = 'var $_ = {' + compat_props.join(', ') + '};'
|
||||
}
|
||||
|
||||
// use is passed as a parameter, not on globalThis for the script
|
||||
// $fd is injected as a capability, but we still allow use('fd') for now
|
||||
// $_ is built from injected capabilities for backward compatibility
|
||||
var fn = `(function setup_module(args, use${params}){ def arg = args; def PACKAGE = ${pkg_arg}; ${build_compat} ${script}})`
|
||||
var fn = `(function setup_module(args, use${params}){ def arg = args; def PACKAGE = ${pkg_arg}; ${script}})`
|
||||
return fn
|
||||
}
|
||||
|
||||
@@ -808,7 +792,7 @@ function execute_module(info)
|
||||
used = mod_resolve.symbol.call(context, null, use_fn, ...vals)
|
||||
} else if (c_resolve.scope < 900) {
|
||||
// C only
|
||||
used = c_resolve.symbol(null, $_)
|
||||
used = c_resolve.symbol(null, my$_)
|
||||
} else {
|
||||
throw new Error(`Module ${info.path} could not be found`)
|
||||
} if (!used)
|
||||
|
||||
32
pronto.cm
32
pronto.cm
@@ -33,9 +33,9 @@ function fallback(requestor_array) {
|
||||
|
||||
return function fallback_requestor(callback, value) {
|
||||
check_callback(callback, factory)
|
||||
let index = 0
|
||||
let current_cancel = null
|
||||
let cancelled = false
|
||||
var index = 0
|
||||
var current_cancel = null
|
||||
var cancelled = false
|
||||
|
||||
function cancel(reason) {
|
||||
cancelled = true
|
||||
@@ -98,10 +98,10 @@ function parallel(requestor_array, throttle, need) {
|
||||
check_callback(callback, factory)
|
||||
def results = new Array(length)
|
||||
def cancel_list = new Array(length)
|
||||
let next_index = 0
|
||||
let successes = 0
|
||||
let failures = 0
|
||||
let finished = false
|
||||
var next_index = 0
|
||||
var successes = 0
|
||||
var failures = 0
|
||||
var finished = false
|
||||
|
||||
function cancel(reason) {
|
||||
if (finished) return
|
||||
@@ -154,7 +154,7 @@ function parallel(requestor_array, throttle, need) {
|
||||
}
|
||||
|
||||
def concurrent = throttle ? number.min(throttle, length) : length
|
||||
for (let i = 0; i < concurrent; i++) start_one()
|
||||
for (var i = 0; i < concurrent; i++) start_one()
|
||||
|
||||
return cancel
|
||||
}
|
||||
@@ -180,10 +180,10 @@ function race(requestor_array, throttle, need) {
|
||||
check_callback(callback, factory)
|
||||
def results = new Array(length)
|
||||
def cancel_list = new Array(length)
|
||||
let next_index = 0
|
||||
let successes = 0
|
||||
let failures = 0
|
||||
let finished = false
|
||||
var next_index = 0
|
||||
var successes = 0
|
||||
var failures = 0
|
||||
var finished = false
|
||||
|
||||
function cancel(reason) {
|
||||
if (finished) return
|
||||
@@ -239,7 +239,7 @@ function race(requestor_array, throttle, need) {
|
||||
}
|
||||
|
||||
def concurrent = throttle ? number.min(throttle, length) : length
|
||||
for (let i = 0; i < concurrent; i++) start_one()
|
||||
for (var i = 0; i < concurrent; i++) start_one()
|
||||
|
||||
return cancel
|
||||
}
|
||||
@@ -258,9 +258,9 @@ function sequence(requestor_array) {
|
||||
|
||||
return function sequence_requestor(callback, value) {
|
||||
check_callback(callback, factory)
|
||||
let index = 0
|
||||
let current_cancel = null
|
||||
let cancelled = false
|
||||
var index = 0
|
||||
var current_cancel = null
|
||||
var cancelled = false
|
||||
|
||||
function cancel(reason) {
|
||||
cancelled = true
|
||||
|
||||
@@ -15384,7 +15384,6 @@ enum {
|
||||
/* FutureReservedWords when parsing strict mode code */
|
||||
TOK_IMPLEMENTS,
|
||||
TOK_INTERFACE,
|
||||
TOK_LET,
|
||||
TOK_PRIVATE,
|
||||
TOK_PROTECTED,
|
||||
TOK_PUBLIC,
|
||||
@@ -18680,18 +18679,15 @@ static __exception int js_define_var(JSParseState *s, JSAtom name, int tok)
|
||||
return js_parse_error(s, "invalid variable name in strict mode");
|
||||
}
|
||||
if (name == JS_ATOM_let
|
||||
&& (tok == TOK_LET || tok == TOK_DEF)) {
|
||||
&& tok == TOK_DEF) {
|
||||
return js_parse_error(s, "invalid lexical variable name");
|
||||
}
|
||||
switch(tok) {
|
||||
case TOK_LET:
|
||||
var_def_type = JS_VAR_DEF_LET;
|
||||
break;
|
||||
case TOK_DEF:
|
||||
var_def_type = JS_VAR_DEF_CONST;
|
||||
break;
|
||||
case TOK_VAR:
|
||||
var_def_type = JS_VAR_DEF_VAR;
|
||||
var_def_type = JS_VAR_DEF_LET;
|
||||
break;
|
||||
case TOK_CATCH:
|
||||
var_def_type = JS_VAR_DEF_CATCH;
|
||||
@@ -18749,7 +18745,7 @@ duplicate:
|
||||
return js_parse_error(s, "duplicate parameter names not allowed in this context");
|
||||
}
|
||||
|
||||
/* tok = TOK_VAR, TOK_LET or TOK_DEF. Return whether a reference
|
||||
/* tok = TOK_VAR or TOK_DEF. Return whether a reference
|
||||
must be taken to the variable for proper 'with' or global variable
|
||||
evaluation */
|
||||
/* Note: this function is needed only because variable references are
|
||||
@@ -18757,12 +18753,8 @@ duplicate:
|
||||
static BOOL need_var_reference(JSParseState *s, int tok)
|
||||
{
|
||||
JSFunctionDef *fd = s->cur_func;
|
||||
if (tok != TOK_VAR)
|
||||
return FALSE; /* no reference for let/const */
|
||||
|
||||
if (!fd->is_global_var)
|
||||
return FALSE; /* local definitions in strict mode in function or direct eval */
|
||||
return TRUE;
|
||||
/* var now behaves like let - no reference needed */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg)
|
||||
@@ -19075,7 +19067,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
|
||||
/* store value into lvalue object */
|
||||
put_lvalue(s, opcode, scope, var_name, label_lvalue,
|
||||
PUT_LVALUE_NOKEEP_DEPTH,
|
||||
(tok == TOK_DEF || tok == TOK_LET));
|
||||
(tok == TOK_DEF || tok == TOK_VAR));
|
||||
if (s->token.val == '}')
|
||||
break;
|
||||
/* accept a trailing comma before the '}' */
|
||||
@@ -19189,7 +19181,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
|
||||
/* store value into lvalue object */
|
||||
put_lvalue(s, opcode, scope, var_name,
|
||||
label_lvalue, PUT_LVALUE_NOKEEP_DEPTH,
|
||||
(tok == TOK_DEF || tok == TOK_LET));
|
||||
(tok == TOK_DEF || tok == TOK_VAR));
|
||||
}
|
||||
if (s->token.val == ']')
|
||||
break;
|
||||
@@ -20516,7 +20508,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
|
||||
return js_parse_error_reserved_identifier(s);
|
||||
}
|
||||
name = JS_DupAtom(ctx, s->token.u.ident.atom);
|
||||
if (name == JS_ATOM_let && (tok == TOK_LET || tok == TOK_DEF)) {
|
||||
if (name == JS_ATOM_let && tok == TOK_DEF) {
|
||||
js_parse_error(s, "'let' is not a valid lexical identifier");
|
||||
goto var_error;
|
||||
}
|
||||
@@ -20549,7 +20541,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
|
||||
if (js_parse_assign_expr2(s, parse_flags))
|
||||
goto var_error;
|
||||
set_object_name(s, name);
|
||||
emit_op(s, (tok == TOK_DEF || tok == TOK_LET) ?
|
||||
emit_op(s, (tok == TOK_DEF || tok == TOK_VAR) ?
|
||||
OP_scope_put_var_init : OP_scope_put_var);
|
||||
emit_atom(s, name);
|
||||
emit_u16(s, fd->scope_level);
|
||||
@@ -20559,7 +20551,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
|
||||
js_parse_error(s, "missing initializer for const variable");
|
||||
goto var_error;
|
||||
}
|
||||
if (tok == TOK_LET) {
|
||||
if (tok == TOK_VAR) {
|
||||
/* initialize lexical variable upon entering its scope */
|
||||
emit_op(s, OP_null);
|
||||
emit_op(s, OP_scope_put_var_init);
|
||||
@@ -20621,7 +20613,6 @@ static int is_let(JSParseState *s, int decl_mask)
|
||||
}
|
||||
if (s->token.val == '{' ||
|
||||
(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved) ||
|
||||
s->token.val == TOK_LET ||
|
||||
s->token.val == TOK_YIELD ||
|
||||
s->token.val == TOK_AWAIT) {
|
||||
/* Check for possible ASI if not scanning for Declaration */
|
||||
@@ -20682,16 +20673,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name)
|
||||
emit_label(s, label_next);
|
||||
|
||||
tok = s->token.val;
|
||||
switch (is_let(s, DECL_MASK_OTHER)) {
|
||||
case TRUE:
|
||||
tok = TOK_LET;
|
||||
break;
|
||||
case FALSE:
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_DEF) {
|
||||
if (tok == TOK_VAR || tok == TOK_DEF) {
|
||||
if (next_token(s))
|
||||
return -1;
|
||||
|
||||
@@ -20714,7 +20696,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name)
|
||||
JS_FreeAtom(s->ctx, var_name);
|
||||
return -1;
|
||||
}
|
||||
emit_op(s, (tok == TOK_DEF || tok == TOK_LET) ?
|
||||
emit_op(s, (tok == TOK_DEF || tok == TOK_VAR) ?
|
||||
OP_scope_put_var_init : OP_scope_put_var);
|
||||
emit_atom(s, var_name);
|
||||
emit_u16(s, fd->scope_level);
|
||||
@@ -20948,7 +20930,6 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case TOK_LET:
|
||||
case TOK_DEF:
|
||||
haslet:
|
||||
if (!(decl_mask & DECL_MASK_OTHER)) {
|
||||
@@ -20957,6 +20938,10 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
|
||||
}
|
||||
/* fall thru */
|
||||
case TOK_VAR:
|
||||
if (!(decl_mask & DECL_MASK_OTHER)) {
|
||||
js_parse_error(s, "lexical declarations can't appear in single-statement context");
|
||||
goto fail;
|
||||
}
|
||||
if (next_token(s))
|
||||
goto fail;
|
||||
if (js_parse_var(s, TRUE, tok, FALSE))
|
||||
@@ -21096,16 +21081,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
|
||||
/* initial expression */
|
||||
tok = s->token.val;
|
||||
if (tok != ';') {
|
||||
switch (is_let(s, DECL_MASK_OTHER)) {
|
||||
case TRUE:
|
||||
tok = TOK_LET;
|
||||
break;
|
||||
case FALSE:
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_DEF) {
|
||||
if (tok == TOK_VAR || tok == TOK_DEF) {
|
||||
if (next_token(s))
|
||||
goto fail;
|
||||
if (js_parse_var(s, FALSE, tok, FALSE))
|
||||
@@ -21369,8 +21345,8 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
|
||||
goto fail;
|
||||
if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {
|
||||
if (s->token.val == '[' || s->token.val == '{') {
|
||||
/* XXX: TOK_LET is not completely correct */
|
||||
if (js_parse_destructuring_element(s, TOK_LET, 0, TRUE, -1, TRUE, FALSE) < 0)
|
||||
/* catch variables behave like var (block scoped) */
|
||||
if (js_parse_destructuring_element(s, TOK_VAR, 0, TRUE, -1, TRUE, FALSE) < 0)
|
||||
goto fail;
|
||||
} else {
|
||||
js_parse_error(s, "identifier expected");
|
||||
@@ -21490,16 +21466,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
|
||||
js_parse_error_reserved_identifier(s);
|
||||
goto fail;
|
||||
}
|
||||
/* Determine if `let` introduces a Declaration or an ExpressionStatement */
|
||||
switch (is_let(s, decl_mask)) {
|
||||
case TRUE:
|
||||
tok = TOK_LET;
|
||||
goto haslet;
|
||||
case FALSE:
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
/* let keyword is no longer supported */
|
||||
if (token_is_pseudo_keyword(s, JS_ATOM_async) &&
|
||||
peek_token(s, TRUE) == TOK_FUNCTION) {
|
||||
if (!(decl_mask & DECL_MASK_OTHER)) {
|
||||
@@ -25359,7 +25326,6 @@ static __exception int js_parse_directives(JSParseState *s)
|
||||
case TOK_EXPORT:
|
||||
case TOK_IMPORT:
|
||||
case TOK_INTERFACE:
|
||||
case TOK_LET:
|
||||
/* automatic insertion of ';' */
|
||||
if (s->got_lf)
|
||||
has_semi = TRUE;
|
||||
@@ -25581,7 +25547,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
|
||||
emit_op(s, OP_get_arg);
|
||||
emit_u16(s, idx);
|
||||
}
|
||||
has_initializer = js_parse_destructuring_element(s, fd->has_parameter_expressions ? TOK_LET : TOK_VAR, 1, TRUE, -1, TRUE, FALSE);
|
||||
has_initializer = js_parse_destructuring_element(s, TOK_VAR, 1, TRUE, -1, TRUE, FALSE);
|
||||
if (has_initializer < 0)
|
||||
goto fail;
|
||||
if (has_initializer)
|
||||
|
||||
4
test.ce
4
test.ce
@@ -550,8 +550,9 @@ function finalize_results() {
|
||||
}
|
||||
|
||||
// If no actor tests, finalize immediately
|
||||
var totals
|
||||
if (all_actor_tests.length == 0) {
|
||||
var totals = { total: 0, passed: 0, failed: 0 }
|
||||
totals = { total: 0, passed: 0, failed: 0 }
|
||||
for (var i = 0; i < all_results.length; i++) {
|
||||
totals.total += all_results[i].total
|
||||
totals.passed += all_results[i].passed
|
||||
@@ -564,7 +565,6 @@ if (all_actor_tests.length == 0) {
|
||||
$delay(check_timeouts, 1000)
|
||||
}
|
||||
|
||||
|
||||
// Generate Reports function
|
||||
function generate_reports(totals) {
|
||||
var timestamp = number.floor(time.number()).toString()
|
||||
|
||||
@@ -314,10 +314,100 @@ return {
|
||||
if (x != 10) throw "var reassignment failed"
|
||||
},
|
||||
|
||||
test_var_hoisting: function() {
|
||||
var result = x
|
||||
var x = 5
|
||||
if (result != null) throw "var hoisting should initialize to null"
|
||||
// ============================================================================
|
||||
// VAR BLOCK SCOPING (var now behaves like let)
|
||||
// ============================================================================
|
||||
|
||||
test_var_block_scope_basic: function() {
|
||||
var x = 1
|
||||
{
|
||||
var x = 2
|
||||
if (x != 2) throw "var should be block scoped - inner scope failed"
|
||||
}
|
||||
if (x != 1) throw "var should be block scoped - outer scope affected"
|
||||
},
|
||||
|
||||
test_var_block_scope_if: function() {
|
||||
var x = 1
|
||||
if (true) {
|
||||
var x = 2
|
||||
if (x != 2) throw "var in if block should be scoped"
|
||||
}
|
||||
if (x != 1) throw "var in if block should not affect outer scope"
|
||||
},
|
||||
|
||||
test_var_block_scope_for: function() {
|
||||
var x = 1
|
||||
for (var i = 0; i < 1; i = i + 1) {
|
||||
var x = 2
|
||||
if (x != 2) throw "var in for block should be scoped"
|
||||
}
|
||||
if (x != 1) throw "var in for block should not affect outer scope"
|
||||
},
|
||||
|
||||
test_var_for_loop_iterator_scope: function() {
|
||||
var sum = 0
|
||||
for (var i = 0; i < 3; i = i + 1) {
|
||||
sum = sum + i
|
||||
}
|
||||
if (sum != 3) throw "for loop should work with block scoped var"
|
||||
var caught = false
|
||||
try {
|
||||
var y = i
|
||||
} catch (e) {
|
||||
caught = true
|
||||
}
|
||||
if (!caught) throw "for loop iterator should not leak to outer scope"
|
||||
},
|
||||
|
||||
test_var_nested_blocks: function() {
|
||||
var x = 1
|
||||
{
|
||||
var x = 2
|
||||
{
|
||||
var x = 3
|
||||
if (x != 3) throw "var in nested block level 2 failed"
|
||||
}
|
||||
if (x != 2) throw "var in nested block level 1 failed"
|
||||
}
|
||||
if (x != 1) throw "var in nested blocks outer scope failed"
|
||||
},
|
||||
|
||||
test_var_redeclaration_different_scope: function() {
|
||||
var x = 1
|
||||
{
|
||||
var x = 2
|
||||
}
|
||||
if (x != 1) throw "var in different scope should not affect outer"
|
||||
},
|
||||
|
||||
test_var_switch_scope: function() {
|
||||
var x = 1
|
||||
switch (1) {
|
||||
case 1:
|
||||
var x = 2
|
||||
if (x != 2) throw "var in switch should be block scoped"
|
||||
break
|
||||
}
|
||||
if (x != 1) throw "var in switch should not affect outer scope"
|
||||
},
|
||||
|
||||
test_var_while_scope: function() {
|
||||
var x = 1
|
||||
var count = 0
|
||||
while (count < 1) {
|
||||
var x = 2
|
||||
if (x != 2) throw "var in while should be block scoped"
|
||||
count = count + 1
|
||||
}
|
||||
if (x != 1) throw "var in while should not affect outer scope"
|
||||
},
|
||||
|
||||
test_var_no_initialization: function() {
|
||||
{
|
||||
var x
|
||||
if (x != null) throw "uninitialized var should be null"
|
||||
}
|
||||
},
|
||||
|
||||
test_multiple_var_declaration: function() {
|
||||
|
||||
Reference in New Issue
Block a user