rm for ... in
This commit is contained in:
9
bench.ce
9
bench.ce
@@ -441,11 +441,10 @@ function run_benchmarks(package_name, specific_bench) {
|
|||||||
if (is_function(bench_mod)) {
|
if (is_function(bench_mod)) {
|
||||||
benches.push({name: 'main', fn: bench_mod})
|
benches.push({name: 'main', fn: bench_mod})
|
||||||
} else if (is_object(bench_mod)) {
|
} else if (is_object(bench_mod)) {
|
||||||
for (var k in bench_mod) {
|
arrfor(array(bench_mod), function(k) {
|
||||||
if (is_function(bench_mod[k])) {
|
if (is_function(bench_mod[k]))
|
||||||
benches.push({name: k, fn: bench_mod[k]})
|
benches.push({name: k, fn: bench_mod[k]})
|
||||||
}
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length(benches) > 0) {
|
if (length(benches) > 0) {
|
||||||
@@ -474,7 +473,7 @@ function run_benchmarks(package_name, specific_bench) {
|
|||||||
file_result.benchmarks.push(error_result)
|
file_result.benchmarks.push(error_result)
|
||||||
pkg_result.total++
|
pkg_result.total++
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.console(` Error loading ${f}: ${e}`)
|
log.console(` Error loading ${f}: ${e}`)
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ function fib(n) {
|
|||||||
|
|
||||||
var now = time.number()
|
var now = time.number()
|
||||||
var arr = [1,2,3,4,5]
|
var arr = [1,2,3,4,5]
|
||||||
for (var i in arr) {
|
arrfor(arr, function(i) {
|
||||||
log.console(fib(28))
|
log.console(fib(28))
|
||||||
}
|
})
|
||||||
|
|
||||||
log.console(`elapsed: ${time.number()-now}`)
|
log.console(`elapsed: ${time.number()-now}`)
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ function format_value(val) {
|
|||||||
|
|
||||||
// Print configuration tree recursively
|
// Print configuration tree recursively
|
||||||
function print_config(obj, prefix = '') {
|
function print_config(obj, prefix = '') {
|
||||||
for (var key in obj) {
|
arrfor(array(obj), function(key) {
|
||||||
var val = obj[key]
|
var val = obj[key]
|
||||||
var full_key = prefix ? prefix + '.' + key : key
|
var full_key = prefix ? prefix + '.' + key : key
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ function print_config(obj, prefix = '') {
|
|||||||
print_config(val, full_key)
|
print_config(val, full_key)
|
||||||
else
|
else
|
||||||
log.console(full_key + ' = ' + format_value(val))
|
log.console(full_key + ' = ' + format_value(val))
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main command handling
|
// Main command handling
|
||||||
|
|||||||
12
graph.ce
12
graph.ce
@@ -94,12 +94,12 @@ function gather_graph(locator, visited) {
|
|||||||
try {
|
try {
|
||||||
var deps = pkg.dependencies(locator)
|
var deps = pkg.dependencies(locator)
|
||||||
if (deps) {
|
if (deps) {
|
||||||
for (var alias in deps) {
|
arrfor(array(deps), function(alias) {
|
||||||
var dep_locator = deps[alias]
|
var dep_locator = deps[alias]
|
||||||
add_node(dep_locator)
|
add_node(dep_locator)
|
||||||
edges.push({ from: locator, to: dep_locator, alias: alias })
|
edges.push({ from: locator, to: dep_locator, alias: alias })
|
||||||
gather_graph(dep_locator, visited)
|
gather_graph(dep_locator, visited)
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Package might not have dependencies
|
// Package might not have dependencies
|
||||||
@@ -193,7 +193,7 @@ if (format == 'tree') {
|
|||||||
log.console("")
|
log.console("")
|
||||||
|
|
||||||
// Node definitions
|
// Node definitions
|
||||||
for (var id in nodes) {
|
arrfor(array(nodes), function(id) {
|
||||||
var node = nodes[id]
|
var node = nodes[id]
|
||||||
var label = id
|
var label = id
|
||||||
if (node.commit) label += "\\n@" + node.commit
|
if (node.commit) label += "\\n@" + node.commit
|
||||||
@@ -204,7 +204,7 @@ if (format == 'tree') {
|
|||||||
// Safe node ID for dot
|
// Safe node ID for dot
|
||||||
var safe_id = replace(id, /[^a-zA-Z0-9]/g, '_')
|
var safe_id = replace(id, /[^a-zA-Z0-9]/g, '_')
|
||||||
log.console(' ' + safe_id + ' [' + attrs + '];')
|
log.console(' ' + safe_id + ' [' + attrs + '];')
|
||||||
}
|
})
|
||||||
|
|
||||||
log.console("")
|
log.console("")
|
||||||
|
|
||||||
@@ -224,9 +224,9 @@ if (format == 'tree') {
|
|||||||
edges: []
|
edges: []
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var id in nodes) {
|
arrfor(array(nodes), function(id) {
|
||||||
output.nodes.push(nodes[id])
|
output.nodes.push(nodes[id])
|
||||||
}
|
})
|
||||||
|
|
||||||
output.edges = edges
|
output.edges = edges
|
||||||
|
|
||||||
|
|||||||
@@ -119,10 +119,10 @@ function gather_packages(pkg_locator) {
|
|||||||
|
|
||||||
var deps = pkg.dependencies(pkg_locator)
|
var deps = pkg.dependencies(pkg_locator)
|
||||||
if (deps) {
|
if (deps) {
|
||||||
for (var alias in deps) {
|
arrfor(array(deps), function(alias) {
|
||||||
var dep_locator = deps[alias]
|
var dep_locator = deps[alias]
|
||||||
gather_packages(dep_locator)
|
gather_packages(dep_locator)
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Package might not have dependencies or cell.toml issue
|
// Package might not have dependencies or cell.toml issue
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ globalThis.ends_with = function(str, suffix) {
|
|||||||
return search(str, suffix, -length(suffix)) != null
|
return search(str, suffix, -length(suffix)) != null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var js = use_embed('js')
|
var js = use_embed('js')
|
||||||
var fd = use_embed('fd')
|
var fd = use_embed('fd')
|
||||||
|
|
||||||
@@ -410,7 +412,9 @@ function handle_host(e) {
|
|||||||
break
|
break
|
||||||
case "disconnect":
|
case "disconnect":
|
||||||
peer_queue.delete(e.peer)
|
peer_queue.delete(e.peer)
|
||||||
for (var id in peers) if (peers[id] == e.peer) delete peers[id]
|
arrfor(array(peers), function(id) {
|
||||||
|
if (peers[id] == e.peer) delete peers[id]
|
||||||
|
})
|
||||||
log.system('portal got disconnect from ' + e.peer.address + ":" + e.peer.port)
|
log.system('portal got disconnect from ' + e.peer.address + ":" + e.peer.port)
|
||||||
break
|
break
|
||||||
case "receive":
|
case "receive":
|
||||||
@@ -425,11 +429,11 @@ function handle_host(e) {
|
|||||||
obj[ACTORDATA].address = e.peer.address
|
obj[ACTORDATA].address = e.peer.address
|
||||||
obj[ACTORDATA].port = e.peer.port
|
obj[ACTORDATA].port = e.peer.port
|
||||||
}
|
}
|
||||||
for (var key in obj) {
|
arrfor(array(obj), function(key) {
|
||||||
if (object.has(obj, key)) {
|
if (object.has(obj, key)) {
|
||||||
populate_actor_addresses(obj[key])
|
populate_actor_addresses(obj[key])
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
if (data.data) populate_actor_addresses(data.data)
|
if (data.data) populate_actor_addresses(data.data)
|
||||||
turn(data)
|
turn(data)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
var toml = use('toml')
|
var toml = use('toml')
|
||||||
|
|
||||||
var json = use('json')
|
var json = use('json')
|
||||||
var fd = use('fd')
|
var fd = use('fd')
|
||||||
var http = use('http')
|
var http = use('http')
|
||||||
@@ -7,6 +8,7 @@ var time = use('time')
|
|||||||
var js = use('js')
|
var js = use('js')
|
||||||
var crypto = use('crypto')
|
var crypto = use('crypto')
|
||||||
var blob = use('blob')
|
var blob = use('blob')
|
||||||
|
|
||||||
var pkg_tools = use('package')
|
var pkg_tools = use('package')
|
||||||
var os = use('os')
|
var os = use('os')
|
||||||
var link = use('link')
|
var link = use('link')
|
||||||
@@ -559,14 +561,14 @@ Shop.open_package_dylib = function(pkg) {
|
|||||||
var content = text(fd.slurp(toml_path))
|
var content = text(fd.slurp(toml_path))
|
||||||
var cfg = toml.decode(content)
|
var cfg = toml.decode(content)
|
||||||
if (cfg.dependencies) {
|
if (cfg.dependencies) {
|
||||||
for (var alias in cfg.dependencies) {
|
arrfor(array(cfg.dependencies), function(alias) {
|
||||||
var dep_pkg = cfg.dependencies[alias]
|
var dep_pkg = cfg.dependencies[alias]
|
||||||
try {
|
try {
|
||||||
Shop.open_package_dylib(dep_pkg)
|
Shop.open_package_dylib(dep_pkg)
|
||||||
} catch (dep_e) {
|
} catch (dep_e) {
|
||||||
// Dependency dylib load failed, continue with others
|
// Dependency dylib load failed, continue with others
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Error reading toml, continue
|
// Error reading toml, continue
|
||||||
@@ -1194,12 +1196,14 @@ Shop.module_reload = function(path, package) {
|
|||||||
var old = use_cache[cache_key]
|
var old = use_cache[cache_key]
|
||||||
var newmod = get_module(path, package)
|
var newmod = get_module(path, package)
|
||||||
|
|
||||||
for (var i in newmod)
|
arrfor(array(newmod), function(i) {
|
||||||
old[i] = newmod[i]
|
old[i] = newmod[i]
|
||||||
|
})
|
||||||
|
|
||||||
for (var i in old)
|
arrfor(array(old), function(i) {
|
||||||
if (!(i in newmod))
|
if (!(i in newmod))
|
||||||
old[i] = null
|
old[i] = null
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_package_scripts(package)
|
function get_package_scripts(package)
|
||||||
|
|||||||
4
link.ce
4
link.ce
@@ -35,10 +35,10 @@ var cmd = args[0]
|
|||||||
if (cmd == 'list') {
|
if (cmd == 'list') {
|
||||||
var links = link.load()
|
var links = link.load()
|
||||||
var count = 0
|
var count = 0
|
||||||
for (var k in links) {
|
arrfor(array(links), function(k) {
|
||||||
log.console(k + " -> " + links[k])
|
log.console(k + " -> " + links[k])
|
||||||
count++
|
count++
|
||||||
}
|
})
|
||||||
if (count == 0) log.console("No links.")
|
if (count == 0) log.console("No links.")
|
||||||
|
|
||||||
} else if (cmd == 'sync') {
|
} else if (cmd == 'sync') {
|
||||||
|
|||||||
35
link.cm
35
link.cm
@@ -120,12 +120,12 @@ Link.add = function(canonical, target, shop) {
|
|||||||
var content = text(fd.slurp(toml_path))
|
var content = text(fd.slurp(toml_path))
|
||||||
var cfg = toml.decode(content)
|
var cfg = toml.decode(content)
|
||||||
if (cfg.dependencies) {
|
if (cfg.dependencies) {
|
||||||
for (var alias in cfg.dependencies) {
|
arrfor(array(cfg.dependencies), function(alias) {
|
||||||
var dep_locator = cfg.dependencies[alias]
|
var dep_locator = cfg.dependencies[alias]
|
||||||
// Skip local dependencies that don't exist
|
// Skip local dependencies that don't exist
|
||||||
if (starts_with(dep_locator, '/') && !fd.is_dir(dep_locator)) {
|
if (starts_with(dep_locator, '/') && !fd.is_dir(dep_locator)) {
|
||||||
log.console(" Skipping missing local dependency: " + dep_locator)
|
log.console(" Skipping missing local dependency: " + dep_locator)
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
// Install the dependency if not already in shop
|
// Install the dependency if not already in shop
|
||||||
try {
|
try {
|
||||||
@@ -135,7 +135,7 @@ Link.add = function(canonical, target, shop) {
|
|||||||
log.console(` Warning: Could not install dependency ${dep_locator}: ${e.message}`)
|
log.console(` Warning: Could not install dependency ${dep_locator}: ${e.message}`)
|
||||||
log.error(e)
|
log.error(e)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.console(` Warning: Could not read dependencies from ${toml_path}`)
|
log.console(` Warning: Could not read dependencies from ${toml_path}`)
|
||||||
@@ -166,12 +166,12 @@ Link.remove = function(canonical) {
|
|||||||
Link.clear = function() {
|
Link.clear = function() {
|
||||||
// Remove all symlinks first
|
// Remove all symlinks first
|
||||||
var links = Link.load()
|
var links = Link.load()
|
||||||
for (var canonical in links) {
|
arrfor(array(links), function(canonical) {
|
||||||
var target_dir = get_package_abs_dir(canonical)
|
var target_dir = get_package_abs_dir(canonical)
|
||||||
if (fd.is_link(target_dir)) {
|
if (fd.is_link(target_dir)) {
|
||||||
fd.unlink(target_dir)
|
fd.unlink(target_dir)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
Link.save({})
|
Link.save({})
|
||||||
log.console("Cleared all links")
|
log.console("Cleared all links")
|
||||||
@@ -216,18 +216,18 @@ Link.sync_all = function(shop) {
|
|||||||
var count = 0
|
var count = 0
|
||||||
var errors = []
|
var errors = []
|
||||||
|
|
||||||
for (var canonical in links) {
|
arrfor(array(links), function(canonical) {
|
||||||
var target = links[canonical]
|
var target = links[canonical]
|
||||||
try {
|
try {
|
||||||
// Validate target exists
|
// Validate target exists
|
||||||
var link_target = resolve_link_target(target)
|
var link_target = resolve_link_target(target)
|
||||||
if (!fd.is_dir(link_target)) {
|
if (!fd.is_dir(link_target)) {
|
||||||
errors.push(canonical + ': target ' + link_target + ' does not exist')
|
errors.push(canonical + ': target ' + link_target + ' does not exist')
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
if (!fd.is_file(link_target + '/cell.toml')) {
|
if (!fd.is_file(link_target + '/cell.toml')) {
|
||||||
errors.push(canonical + ': target ' + link_target + ' is not a valid package')
|
errors.push(canonical + ': target ' + link_target + ' is not a valid package')
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Link.sync_one(canonical, target, shop)
|
Link.sync_one(canonical, target, shop)
|
||||||
@@ -238,11 +238,11 @@ Link.sync_all = function(shop) {
|
|||||||
var content = text(fd.slurp(toml_path))
|
var content = text(fd.slurp(toml_path))
|
||||||
var cfg = toml.decode(content)
|
var cfg = toml.decode(content)
|
||||||
if (cfg.dependencies) {
|
if (cfg.dependencies) {
|
||||||
for (var alias in cfg.dependencies) {
|
arrfor(array(cfg.dependencies), function(alias) {
|
||||||
var dep_locator = cfg.dependencies[alias]
|
var dep_locator = cfg.dependencies[alias]
|
||||||
// Skip local dependencies that don't exist
|
// Skip local dependencies that don't exist
|
||||||
if (starts_with(dep_locator, '/') && !fd.is_dir(dep_locator)) {
|
if (starts_with(dep_locator, '/') && !fd.is_dir(dep_locator)) {
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
// Install the dependency if not already in shop
|
// Install the dependency if not already in shop
|
||||||
try {
|
try {
|
||||||
@@ -251,7 +251,7 @@ Link.sync_all = function(shop) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Silently continue - dependency may already be installed
|
// Silently continue - dependency may already be installed
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Could not read dependencies - continue anyway
|
// Could not read dependencies - continue anyway
|
||||||
@@ -261,7 +261,7 @@ Link.sync_all = function(shop) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
errors.push(canonical + ': ' + e.message)
|
errors.push(canonical + ': ' + e.message)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
return { synced: count, errors: errors }
|
return { synced: count, errors: errors }
|
||||||
}
|
}
|
||||||
@@ -282,12 +282,11 @@ Link.get_target = function(canonical) {
|
|||||||
// Returns null if no package links to this target
|
// Returns null if no package links to this target
|
||||||
Link.get_origin = function(target) {
|
Link.get_origin = function(target) {
|
||||||
var links = Link.load()
|
var links = Link.load()
|
||||||
for (var origin in links) {
|
var found = null
|
||||||
if (links[origin] == target) {
|
arrfor(array(links), function(origin) {
|
||||||
return origin
|
if (links[origin] == target) found = origin
|
||||||
}
|
})
|
||||||
}
|
return found
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Link
|
return Link
|
||||||
|
|||||||
3
list.ce
3
list.ce
@@ -58,8 +58,7 @@ function print_deps(ctx, indent) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var aliases = []
|
var aliases = array(deps)
|
||||||
for (var k in deps) aliases.push(k)
|
|
||||||
aliases = sort(aliases)
|
aliases = sort(aliases)
|
||||||
|
|
||||||
if (length(aliases) == 0) {
|
if (length(aliases) == 0) {
|
||||||
|
|||||||
21
package.cm
21
package.cm
@@ -1,5 +1,4 @@
|
|||||||
var package = {}
|
var package = {}
|
||||||
|
|
||||||
var fd = use('fd')
|
var fd = use('fd')
|
||||||
var toml = use('toml')
|
var toml = use('toml')
|
||||||
var json = use('json')
|
var json = use('json')
|
||||||
@@ -76,11 +75,11 @@ package.find_alias = function(name, locator)
|
|||||||
var config = package.load_config(name)
|
var config = package.load_config(name)
|
||||||
if (!config.dependencies) return null
|
if (!config.dependencies) return null
|
||||||
|
|
||||||
for (var alias in config.dependencies)
|
var found = null
|
||||||
if (config.dependencies[alias] == locator)
|
arrfor(array(config.dependencies), function(alias) {
|
||||||
return alias
|
if (config.dependencies[alias] == locator) found = alias
|
||||||
|
})
|
||||||
return null
|
return found
|
||||||
}
|
}
|
||||||
|
|
||||||
package.alias_to_package = function(name, alias)
|
package.alias_to_package = function(name, alias)
|
||||||
@@ -177,13 +176,13 @@ package.gather_dependencies = function(name)
|
|||||||
var deps = package.dependencies(pkg_name)
|
var deps = package.dependencies(pkg_name)
|
||||||
if (!deps) return
|
if (!deps) return
|
||||||
|
|
||||||
for (var alias in deps) {
|
arrfor(array(deps), function(alias) {
|
||||||
var locator = deps[alias]
|
var locator = deps[alias]
|
||||||
if (!all_deps[locator]) {
|
if (!all_deps[locator]) {
|
||||||
all_deps[locator] = true
|
all_deps[locator] = true
|
||||||
gather_recursive(locator)
|
gather_recursive(locator)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
gather_recursive(name)
|
gather_recursive(name)
|
||||||
@@ -319,7 +318,7 @@ package.get_c_files = function(name, target, exclude_main) {
|
|||||||
|
|
||||||
// Select appropriate file from each group
|
// Select appropriate file from each group
|
||||||
var result = []
|
var result = []
|
||||||
for (var key in groups) {
|
arrfor(array(groups), function(key) {
|
||||||
var group = groups[key]
|
var group = groups[key]
|
||||||
var selected = null
|
var selected = null
|
||||||
|
|
||||||
@@ -334,11 +333,11 @@ package.get_c_files = function(name, target, exclude_main) {
|
|||||||
// Skip main.c if requested
|
// Skip main.c if requested
|
||||||
if (exclude_main) {
|
if (exclude_main) {
|
||||||
var basename = fd.basename(selected)
|
var basename = fd.basename(selected)
|
||||||
if (basename == 'main.c' || starts_with(basename, 'main_')) continue
|
if (basename == 'main.c' || starts_with(basename, 'main_')) return
|
||||||
}
|
}
|
||||||
result.push(selected)
|
result.push(selected)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
10
resolve.ce
10
resolve.ce
@@ -92,10 +92,10 @@ function gather_deps(locator, depth) {
|
|||||||
try {
|
try {
|
||||||
var deps = pkg.dependencies(locator)
|
var deps = pkg.dependencies(locator)
|
||||||
if (deps) {
|
if (deps) {
|
||||||
for (var alias in deps) {
|
arrfor(array(deps), function(alias) {
|
||||||
var dep_locator = deps[alias]
|
var dep_locator = deps[alias]
|
||||||
gather_deps(dep_locator, depth + 1)
|
gather_deps(dep_locator, depth + 1)
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Package might not have dependencies
|
// Package might not have dependencies
|
||||||
@@ -110,11 +110,7 @@ log.console("Target: " + target_triple)
|
|||||||
log.console("")
|
log.console("")
|
||||||
|
|
||||||
// Sort by depth then alphabetically
|
// Sort by depth then alphabetically
|
||||||
var sorted = []
|
var sorted = array(array(all_deps), function(locator) { return { locator: locator, depth: all_deps[locator].depth } })
|
||||||
for (var locator in all_deps) {
|
|
||||||
sorted.push({ locator: locator, depth: all_deps[locator].depth })
|
|
||||||
}
|
|
||||||
|
|
||||||
sorted = sort(sorted, "locator")
|
sorted = sort(sorted, "locator")
|
||||||
sorted = sort(sorted, "depth")
|
sorted = sort(sorted, "depth")
|
||||||
|
|
||||||
|
|||||||
@@ -179,9 +179,6 @@ DEF( make_arg_ref, 7, 0, 2, atom_u16)
|
|||||||
DEF(make_var_ref_ref, 7, 0, 2, atom_u16)
|
DEF(make_var_ref_ref, 7, 0, 2, atom_u16)
|
||||||
DEF( make_var_ref, 5, 0, 2, atom)
|
DEF( make_var_ref, 5, 0, 2, atom)
|
||||||
|
|
||||||
DEF( for_in_start, 1, 1, 1, none)
|
|
||||||
DEF( for_in_next, 1, 1, 3, none)
|
|
||||||
|
|
||||||
/* arithmetic/logic operations */
|
/* arithmetic/logic operations */
|
||||||
DEF( neg, 1, 1, 1, none)
|
DEF( neg, 1, 1, 1, none)
|
||||||
DEF( plus, 1, 1, 1, none)
|
DEF( plus, 1, 1, 1, none)
|
||||||
|
|||||||
456
source/quickjs.c
456
source/quickjs.c
@@ -168,7 +168,6 @@ enum {
|
|||||||
JS_CLASS_BYTECODE_FUNCTION, /* u.func */
|
JS_CLASS_BYTECODE_FUNCTION, /* u.func */
|
||||||
JS_CLASS_BOUND_FUNCTION, /* u.bound_function */
|
JS_CLASS_BOUND_FUNCTION, /* u.bound_function */
|
||||||
JS_CLASS_C_FUNCTION_DATA, /* u.c_function_data_record */
|
JS_CLASS_C_FUNCTION_DATA, /* u.c_function_data_record */
|
||||||
JS_CLASS_FOR_IN_ITERATOR, /* u.for_in_iterator */
|
|
||||||
JS_CLASS_REGEXP, /* u.regexp */
|
JS_CLASS_REGEXP, /* u.regexp */
|
||||||
JS_CLASS_FINALIZATION_REGISTRY,
|
JS_CLASS_FINALIZATION_REGISTRY,
|
||||||
JS_CLASS_BLOB, /* u.opaque (blob *) */
|
JS_CLASS_BLOB, /* u.opaque (blob *) */
|
||||||
@@ -682,15 +681,6 @@ typedef struct JSBoundFunction {
|
|||||||
JSValue argv[0];
|
JSValue argv[0];
|
||||||
} JSBoundFunction;
|
} JSBoundFunction;
|
||||||
|
|
||||||
typedef struct JSForInIterator {
|
|
||||||
JSValue obj;
|
|
||||||
uint32_t idx;
|
|
||||||
uint32_t atom_count;
|
|
||||||
uint8_t in_prototype_chain;
|
|
||||||
uint8_t is_array;
|
|
||||||
JSPropertyEnum *tab_atom; /* is_array = FALSE */
|
|
||||||
} JSForInIterator;
|
|
||||||
|
|
||||||
/* Used by js_object_keys and related functions */
|
/* Used by js_object_keys and related functions */
|
||||||
typedef enum JSIteratorKindEnum {
|
typedef enum JSIteratorKindEnum {
|
||||||
JS_ITERATOR_KIND_KEY,
|
JS_ITERATOR_KIND_KEY,
|
||||||
@@ -823,7 +813,6 @@ struct JSObject {
|
|||||||
void *opaque;
|
void *opaque;
|
||||||
struct JSBoundFunction *bound_function; /* JS_CLASS_BOUND_FUNCTION */
|
struct JSBoundFunction *bound_function; /* JS_CLASS_BOUND_FUNCTION */
|
||||||
struct JSCFunctionDataRecord *c_function_data_record; /* JS_CLASS_C_FUNCTION_DATA */
|
struct JSCFunctionDataRecord *c_function_data_record; /* JS_CLASS_C_FUNCTION_DATA */
|
||||||
struct JSForInIterator *for_in_iterator; /* JS_CLASS_FOR_IN_ITERATOR */
|
|
||||||
struct { /* JS_CLASS_BYTECODE_FUNCTION: 12/24 bytes */
|
struct { /* JS_CLASS_BYTECODE_FUNCTION: 12/24 bytes */
|
||||||
struct JSFunctionBytecode *function_bytecode;
|
struct JSFunctionBytecode *function_bytecode;
|
||||||
JSVarRef **var_refs;
|
JSVarRef **var_refs;
|
||||||
@@ -949,9 +938,6 @@ static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,
|
|||||||
static void js_bound_function_finalizer(JSRuntime *rt, JSValue val);
|
static void js_bound_function_finalizer(JSRuntime *rt, JSValue val);
|
||||||
static void js_bound_function_mark(JSRuntime *rt, JSValueConst val,
|
static void js_bound_function_mark(JSRuntime *rt, JSValueConst val,
|
||||||
JS_MarkFunc *mark_func);
|
JS_MarkFunc *mark_func);
|
||||||
static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val);
|
|
||||||
static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val,
|
|
||||||
JS_MarkFunc *mark_func);
|
|
||||||
static void js_regexp_finalizer(JSRuntime *rt, JSValue val);
|
static void js_regexp_finalizer(JSRuntime *rt, JSValue val);
|
||||||
|
|
||||||
#define HINT_STRING 0
|
#define HINT_STRING 0
|
||||||
@@ -1240,7 +1226,6 @@ static JSClassShortDef const js_std_class_def[] = {
|
|||||||
{ JS_ATOM_Function, js_bytecode_function_finalizer, js_bytecode_function_mark }, /* JS_CLASS_BYTECODE_FUNCTION */
|
{ JS_ATOM_Function, js_bytecode_function_finalizer, js_bytecode_function_mark }, /* JS_CLASS_BYTECODE_FUNCTION */
|
||||||
{ JS_ATOM_Function, js_bound_function_finalizer, js_bound_function_mark }, /* JS_CLASS_BOUND_FUNCTION */
|
{ JS_ATOM_Function, js_bound_function_finalizer, js_bound_function_mark }, /* JS_CLASS_BOUND_FUNCTION */
|
||||||
{ JS_ATOM_Function, js_c_function_data_finalizer, js_c_function_data_mark }, /* JS_CLASS_C_FUNCTION_DATA */
|
{ JS_ATOM_Function, js_c_function_data_finalizer, js_c_function_data_mark }, /* JS_CLASS_C_FUNCTION_DATA */
|
||||||
{ JS_ATOM_ForInIterator, js_for_in_iterator_finalizer, js_for_in_iterator_mark }, /* JS_CLASS_FOR_IN_ITERATOR */
|
|
||||||
{ JS_ATOM_RegExp, js_regexp_finalizer, NULL }, /* JS_CLASS_REGEXP */
|
{ JS_ATOM_RegExp, js_regexp_finalizer, NULL }, /* JS_CLASS_REGEXP */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5316,30 +5301,6 @@ static void js_bound_function_mark(JSRuntime *rt, JSValueConst val,
|
|||||||
JS_MarkValue(rt, bf->argv[i], mark_func);
|
JS_MarkValue(rt, bf->argv[i], mark_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val)
|
|
||||||
{
|
|
||||||
JSObject *p = JS_VALUE_GET_OBJ(val);
|
|
||||||
JSForInIterator *it = p->u.for_in_iterator;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
JS_FreeValueRT(rt, it->obj);
|
|
||||||
if (!it->is_array) {
|
|
||||||
for(i = 0; i < it->atom_count; i++) {
|
|
||||||
JS_FreeAtomRT(rt, it->tab_atom[i].atom);
|
|
||||||
}
|
|
||||||
js_free_rt(rt, it->tab_atom);
|
|
||||||
}
|
|
||||||
js_free_rt(rt, it);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val,
|
|
||||||
JS_MarkFunc *mark_func)
|
|
||||||
{
|
|
||||||
JSObject *p = JS_VALUE_GET_OBJ(val);
|
|
||||||
JSForInIterator *it = p->u.for_in_iterator;
|
|
||||||
JS_MarkValue(rt, it->obj, mark_func);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_object(JSRuntime *rt, JSObject *p)
|
static void free_object(JSRuntime *rt, JSObject *p)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -5955,16 +5916,6 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case JS_CLASS_FOR_IN_ITERATOR: /* u.for_in_iterator */
|
|
||||||
{
|
|
||||||
JSForInIterator *it = p->u.for_in_iterator;
|
|
||||||
if (it) {
|
|
||||||
compute_value_size(it->obj, hp);
|
|
||||||
s->memory_used_count += 1;
|
|
||||||
s->memory_used_size += sizeof(*it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case JS_CLASS_REGEXP: /* u.regexp */
|
case JS_CLASS_REGEXP: /* u.regexp */
|
||||||
compute_jsstring_size(p->u.regexp.pattern, hp);
|
compute_jsstring_size(p->u.regexp.pattern, hp);
|
||||||
compute_jsstring_size(p->u.regexp.bytecode, hp);
|
compute_jsstring_size(p->u.regexp.bytecode, hp);
|
||||||
@@ -11534,236 +11485,6 @@ static JSValue js_build_rest(JSContext *ctx, int first, int argc, JSValueConst *
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
|
|
||||||
{
|
|
||||||
JSObject *p, *p1;
|
|
||||||
JSPropertyEnum *tab_atom;
|
|
||||||
int i;
|
|
||||||
JSValue enum_obj;
|
|
||||||
JSForInIterator *it;
|
|
||||||
uint32_t tag, tab_atom_count;
|
|
||||||
|
|
||||||
tag = JS_VALUE_GET_TAG(obj);
|
|
||||||
if (tag != JS_TAG_OBJECT && tag != JS_TAG_NULL) {
|
|
||||||
obj = JS_ToObjectFree(ctx, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
it = js_malloc(ctx, sizeof(*it));
|
|
||||||
if (!it) {
|
|
||||||
JS_FreeValue(ctx, obj);
|
|
||||||
return JS_EXCEPTION;
|
|
||||||
}
|
|
||||||
enum_obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_FOR_IN_ITERATOR);
|
|
||||||
if (JS_IsException(enum_obj)) {
|
|
||||||
js_free(ctx, it);
|
|
||||||
JS_FreeValue(ctx, obj);
|
|
||||||
return JS_EXCEPTION;
|
|
||||||
}
|
|
||||||
it->is_array = FALSE;
|
|
||||||
it->obj = obj;
|
|
||||||
it->idx = 0;
|
|
||||||
it->tab_atom = NULL;
|
|
||||||
it->atom_count = 0;
|
|
||||||
it->in_prototype_chain = FALSE;
|
|
||||||
p1 = JS_VALUE_GET_OBJ(enum_obj);
|
|
||||||
p1->u.for_in_iterator = it;
|
|
||||||
|
|
||||||
if (tag == JS_TAG_NULL)
|
|
||||||
return enum_obj;
|
|
||||||
|
|
||||||
p = JS_VALUE_GET_OBJ(obj);
|
|
||||||
if (p->fast_array) {
|
|
||||||
JSShape *sh;
|
|
||||||
JSShapeProperty *prs;
|
|
||||||
/* check that there are no enumerable normal fields */
|
|
||||||
sh = p->shape;
|
|
||||||
for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) {
|
|
||||||
if (prs->flags & JS_PROP_ENUMERABLE)
|
|
||||||
goto normal_case;
|
|
||||||
}
|
|
||||||
/* for fast arrays, we only store the number of elements */
|
|
||||||
it->is_array = TRUE;
|
|
||||||
it->atom_count = p->u.array.count;
|
|
||||||
} else {
|
|
||||||
normal_case:
|
|
||||||
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,
|
|
||||||
JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
|
|
||||||
JS_FreeValue(ctx, enum_obj);
|
|
||||||
return JS_EXCEPTION;
|
|
||||||
}
|
|
||||||
it->tab_atom = tab_atom;
|
|
||||||
it->atom_count = tab_atom_count;
|
|
||||||
}
|
|
||||||
return enum_obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* obj -> enum_obj */
|
|
||||||
static __exception int js_for_in_start(JSContext *ctx, JSValue *sp)
|
|
||||||
{
|
|
||||||
sp[-1] = build_for_in_iterator(ctx, sp[-1]);
|
|
||||||
if (JS_IsException(sp[-1]))
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return -1 if exception, 0 if slow case, 1 if the enumeration is finished */
|
|
||||||
static __exception int js_for_in_prepare_prototype_chain_enum(JSContext *ctx,
|
|
||||||
JSValueConst enum_obj)
|
|
||||||
{
|
|
||||||
JSObject *p;
|
|
||||||
JSForInIterator *it;
|
|
||||||
JSPropertyEnum *tab_atom;
|
|
||||||
uint32_t tab_atom_count, i;
|
|
||||||
JSValue obj1;
|
|
||||||
|
|
||||||
p = JS_VALUE_GET_OBJ(enum_obj);
|
|
||||||
it = p->u.for_in_iterator;
|
|
||||||
|
|
||||||
/* check if there are enumerable properties in the prototype chain (fast path) */
|
|
||||||
obj1 = JS_DupValue(ctx, it->obj);
|
|
||||||
for(;;) {
|
|
||||||
obj1 = JS_GetPrototypeFree(ctx, obj1);
|
|
||||||
if (JS_IsNull(obj1))
|
|
||||||
break;
|
|
||||||
if (JS_IsException(obj1))
|
|
||||||
goto fail;
|
|
||||||
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
|
|
||||||
JS_VALUE_GET_OBJ(obj1),
|
|
||||||
JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) {
|
|
||||||
JS_FreeValue(ctx, obj1);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
JS_FreePropertyEnum(ctx, tab_atom, tab_atom_count);
|
|
||||||
if (tab_atom_count != 0) {
|
|
||||||
JS_FreeValue(ctx, obj1);
|
|
||||||
goto slow_path;
|
|
||||||
}
|
|
||||||
/* must check for timeout to avoid infinite loop */
|
|
||||||
if (js_poll_interrupts(ctx)) {
|
|
||||||
JS_FreeValue(ctx, obj1);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JS_FreeValue(ctx, obj1);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
slow_path:
|
|
||||||
/* add the visited properties, even if they are not enumerable */
|
|
||||||
if (it->is_array) {
|
|
||||||
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
|
|
||||||
JS_VALUE_GET_OBJ(it->obj),
|
|
||||||
JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
it->is_array = FALSE;
|
|
||||||
it->tab_atom = tab_atom;
|
|
||||||
it->atom_count = tab_atom_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < it->atom_count; i++) {
|
|
||||||
if (JS_DefinePropertyValue(ctx, enum_obj, it->tab_atom[i].atom, JS_NULL, JS_PROP_ENUMERABLE) < 0)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
fail:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* enum_obj -> enum_obj value done */
|
|
||||||
static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)
|
|
||||||
{
|
|
||||||
JSValueConst enum_obj;
|
|
||||||
JSObject *p;
|
|
||||||
JSAtom prop;
|
|
||||||
JSForInIterator *it;
|
|
||||||
JSPropertyEnum *tab_atom;
|
|
||||||
uint32_t tab_atom_count;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
enum_obj = sp[-1];
|
|
||||||
/* fail safe */
|
|
||||||
if (JS_VALUE_GET_TAG(enum_obj) != JS_TAG_OBJECT)
|
|
||||||
goto done;
|
|
||||||
p = JS_VALUE_GET_OBJ(enum_obj);
|
|
||||||
if (p->class_id != JS_CLASS_FOR_IN_ITERATOR)
|
|
||||||
goto done;
|
|
||||||
it = p->u.for_in_iterator;
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
if (it->idx >= it->atom_count) {
|
|
||||||
if (JS_IsNull(it->obj) || JS_IsNull(it->obj))
|
|
||||||
goto done; /* not an object */
|
|
||||||
/* no more property in the current object: look in the prototype */
|
|
||||||
if (!it->in_prototype_chain) {
|
|
||||||
ret = js_for_in_prepare_prototype_chain_enum(ctx, enum_obj);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
if (ret)
|
|
||||||
goto done;
|
|
||||||
it->in_prototype_chain = TRUE;
|
|
||||||
}
|
|
||||||
it->obj = JS_GetPrototypeFree(ctx, it->obj);
|
|
||||||
if (JS_IsException(it->obj))
|
|
||||||
return -1;
|
|
||||||
if (JS_IsNull(it->obj))
|
|
||||||
goto done; /* no more prototype */
|
|
||||||
|
|
||||||
/* must check for timeout to avoid infinite loop */
|
|
||||||
if (js_poll_interrupts(ctx))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
|
|
||||||
JS_VALUE_GET_OBJ(it->obj),
|
|
||||||
JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
JS_FreePropertyEnum(ctx, it->tab_atom, it->atom_count);
|
|
||||||
it->tab_atom = tab_atom;
|
|
||||||
it->atom_count = tab_atom_count;
|
|
||||||
it->idx = 0;
|
|
||||||
} else {
|
|
||||||
if (it->is_array) {
|
|
||||||
prop = __JS_AtomFromUInt32(it->idx);
|
|
||||||
it->idx++;
|
|
||||||
} else {
|
|
||||||
BOOL is_enumerable;
|
|
||||||
prop = it->tab_atom[it->idx].atom;
|
|
||||||
is_enumerable = it->tab_atom[it->idx].is_enumerable;
|
|
||||||
it->idx++;
|
|
||||||
if (it->in_prototype_chain) {
|
|
||||||
/* slow case: we are in the prototype chain */
|
|
||||||
ret = JS_GetOwnPropertyInternal(ctx, NULL, JS_VALUE_GET_OBJ(enum_obj), prop);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
if (ret)
|
|
||||||
continue; /* already visited */
|
|
||||||
/* add to the visited property list */
|
|
||||||
if (JS_DefinePropertyValue(ctx, enum_obj, prop, JS_NULL,
|
|
||||||
JS_PROP_ENUMERABLE) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!is_enumerable)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* check if the property was deleted */
|
|
||||||
ret = JS_GetOwnPropertyInternal(ctx, NULL, JS_VALUE_GET_OBJ(it->obj), prop);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
if (ret)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* return the property */
|
|
||||||
sp[0] = JS_AtomToValue(ctx, prop);
|
|
||||||
sp[1] = JS_FALSE;
|
|
||||||
return 0;
|
|
||||||
done:
|
|
||||||
/* return the end */
|
|
||||||
sp[0] = JS_NULL;
|
|
||||||
sp[1] = JS_TRUE;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL js_is_fast_array(JSContext *ctx, JSValueConst obj)
|
static BOOL js_is_fast_array(JSContext *ctx, JSValueConst obj)
|
||||||
{
|
{
|
||||||
/* Try and handle fast arrays explicitly */
|
/* Try and handle fast arrays explicitly */
|
||||||
@@ -13820,17 +13541,6 @@ static JSValue JS_CallInternal_OLD(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
}
|
}
|
||||||
BREAK;
|
BREAK;
|
||||||
|
|
||||||
CASE(OP_for_in_start):
|
|
||||||
sf->cur_pc = pc;
|
|
||||||
if (js_for_in_start(ctx, sp))
|
|
||||||
goto exception;
|
|
||||||
BREAK;
|
|
||||||
CASE(OP_for_in_next):
|
|
||||||
sf->cur_pc = pc;
|
|
||||||
if (js_for_in_next(ctx, sp))
|
|
||||||
goto exception;
|
|
||||||
sp += 2;
|
|
||||||
BREAK;
|
|
||||||
CASE(OP_nip_catch):
|
CASE(OP_nip_catch):
|
||||||
{
|
{
|
||||||
JSValue ret_val;
|
JSValue ret_val;
|
||||||
@@ -20293,172 +20003,10 @@ static int is_let(JSParseState *s, int decl_mask)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for-in loop parsing (for-of is not supported) */
|
/* for-in and for-of loops are not supported */
|
||||||
static __exception int js_parse_for_in_of(JSParseState *s, int label_name)
|
static __exception int js_parse_for_in_of(JSParseState *s, int label_name)
|
||||||
{
|
{
|
||||||
JSContext *ctx = s->ctx;
|
return js_parse_error(s, "'for in' and 'for of' loops are not supported");
|
||||||
JSFunctionDef *fd = s->cur_func;
|
|
||||||
JSAtom var_name;
|
|
||||||
BOOL has_initializer, has_destructuring;
|
|
||||||
int tok, tok1, opcode, scope, block_scope_level;
|
|
||||||
int label_next, label_expr, label_cont, label_body, label_break;
|
|
||||||
int pos_next, pos_expr;
|
|
||||||
BlockEnv break_entry;
|
|
||||||
|
|
||||||
has_initializer = FALSE;
|
|
||||||
has_destructuring = FALSE;
|
|
||||||
block_scope_level = fd->scope_level;
|
|
||||||
label_cont = new_label(s);
|
|
||||||
label_body = new_label(s);
|
|
||||||
label_break = new_label(s);
|
|
||||||
label_next = new_label(s);
|
|
||||||
|
|
||||||
/* create scope for the lexical variables declared in the enumeration
|
|
||||||
expressions. XXX: Not completely correct because of weird capturing
|
|
||||||
semantics in `for (i of o) a.push(function(){return i})` */
|
|
||||||
push_scope(s);
|
|
||||||
|
|
||||||
/* local for_in scope starts here so individual elements
|
|
||||||
can be closed in statement. */
|
|
||||||
push_break_entry(s->cur_func, &break_entry,
|
|
||||||
label_name, label_break, label_cont, 1);
|
|
||||||
break_entry.scope_level = block_scope_level;
|
|
||||||
|
|
||||||
label_expr = emit_goto(s, OP_goto, -1);
|
|
||||||
|
|
||||||
pos_next = s->cur_func->byte_code.size;
|
|
||||||
emit_label(s, label_next);
|
|
||||||
|
|
||||||
tok = s->token.val;
|
|
||||||
if (tok == TOK_VAR || tok == TOK_DEF) {
|
|
||||||
if (next_token(s))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {
|
|
||||||
if (s->token.val == '[' || s->token.val == '{') {
|
|
||||||
if (js_parse_destructuring_element(s, tok, 0, TRUE, -1, FALSE, FALSE) < 0)
|
|
||||||
return -1;
|
|
||||||
has_destructuring = TRUE;
|
|
||||||
} else {
|
|
||||||
return js_parse_error(s, "variable name expected");
|
|
||||||
}
|
|
||||||
var_name = JS_ATOM_NULL;
|
|
||||||
} else {
|
|
||||||
var_name = JS_DupAtom(ctx, s->token.u.ident.atom);
|
|
||||||
if (next_token(s)) {
|
|
||||||
JS_FreeAtom(s->ctx, var_name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (js_define_var(s, var_name, tok)) {
|
|
||||||
JS_FreeAtom(s->ctx, var_name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int skip_bits;
|
|
||||||
if ((s->token.val == '[' || s->token.val == '{')
|
|
||||||
&& ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == TOK_IN || tok1 == TOK_OF)) {
|
|
||||||
if (js_parse_destructuring_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE, FALSE) < 0)
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
int lvalue_label;
|
|
||||||
if (js_parse_left_hand_side_expr(s))
|
|
||||||
return -1;
|
|
||||||
if (get_lvalue(s, &opcode, &scope, &var_name, &lvalue_label,
|
|
||||||
NULL, FALSE, TOK_FOR))
|
|
||||||
return -1;
|
|
||||||
put_lvalue(s, opcode, scope, var_name, lvalue_label,
|
|
||||||
PUT_LVALUE_NOKEEP_BOTTOM, FALSE);
|
|
||||||
}
|
|
||||||
var_name = JS_ATOM_NULL;
|
|
||||||
}
|
|
||||||
emit_goto(s, OP_goto, label_body);
|
|
||||||
|
|
||||||
pos_expr = s->cur_func->byte_code.size;
|
|
||||||
emit_label(s, label_expr);
|
|
||||||
if (s->token.val == '=') {
|
|
||||||
/* XXX: potential scoping issue if inside `with` statement */
|
|
||||||
has_initializer = TRUE;
|
|
||||||
/* parse and evaluate initializer prior to evaluating the
|
|
||||||
object (only used with "for in" with a non lexical variable
|
|
||||||
in non strict mode */
|
|
||||||
if (next_token(s) || js_parse_assign_expr2(s, 0)) {
|
|
||||||
JS_FreeAtom(ctx, var_name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (var_name != JS_ATOM_NULL) {
|
|
||||||
emit_op(s, OP_scope_put_var);
|
|
||||||
emit_atom(s, var_name);
|
|
||||||
emit_u16(s, fd->scope_level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JS_FreeAtom(ctx, var_name);
|
|
||||||
|
|
||||||
if (token_is_pseudo_keyword(s, JS_ATOM_of)) {
|
|
||||||
return js_parse_error(s, "'for of' loops are not supported");
|
|
||||||
} else if (s->token.val == TOK_IN) {
|
|
||||||
if (has_initializer &&
|
|
||||||
(tok != TOK_VAR || has_destructuring)) {
|
|
||||||
return js_parse_error(s, "a declaration in the head of a for-in loop can't have an initializer");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return js_parse_error(s, "expected 'in' in for control expression");
|
|
||||||
}
|
|
||||||
if (next_token(s))
|
|
||||||
return -1;
|
|
||||||
if (js_parse_expr(s))
|
|
||||||
return -1;
|
|
||||||
/* close the scope after having evaluated the expression so that
|
|
||||||
the TDZ values are in the closures */
|
|
||||||
close_scopes(s, s->cur_func->scope_level, block_scope_level);
|
|
||||||
emit_op(s, OP_for_in_start);
|
|
||||||
/* on stack: enum_obj */
|
|
||||||
emit_goto(s, OP_goto, label_cont);
|
|
||||||
|
|
||||||
if (js_parse_expect(s, ')'))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (OPTIMIZE) {
|
|
||||||
/* move the `next` code here */
|
|
||||||
DynBuf *bc = &s->cur_func->byte_code;
|
|
||||||
int chunk_size = pos_expr - pos_next;
|
|
||||||
int offset = bc->size - pos_next;
|
|
||||||
int i;
|
|
||||||
dbuf_realloc(bc, bc->size + chunk_size);
|
|
||||||
dbuf_put(bc, bc->buf + pos_next, chunk_size);
|
|
||||||
memset(bc->buf + pos_next, OP_nop, chunk_size);
|
|
||||||
/* `next` part ends with a goto */
|
|
||||||
s->cur_func->last_opcode_pos = bc->size - 5;
|
|
||||||
/* relocate labels */
|
|
||||||
for (i = label_cont; i < s->cur_func->label_count; i++) {
|
|
||||||
LabelSlot *ls = &s->cur_func->label_slots[i];
|
|
||||||
if (ls->pos >= pos_next && ls->pos < pos_expr)
|
|
||||||
ls->pos += offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit_label(s, label_body);
|
|
||||||
if (js_parse_statement(s))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
close_scopes(s, s->cur_func->scope_level, block_scope_level);
|
|
||||||
|
|
||||||
emit_label(s, label_cont);
|
|
||||||
emit_op(s, OP_for_in_next);
|
|
||||||
/* on stack: enum_obj value bool */
|
|
||||||
emit_goto(s, OP_if_false, label_next);
|
|
||||||
/* drop the undefined value from for_in_next */
|
|
||||||
emit_op(s, OP_drop);
|
|
||||||
|
|
||||||
emit_label(s, label_break);
|
|
||||||
emit_op(s, OP_drop);
|
|
||||||
pop_break_entry(s->cur_func);
|
|
||||||
pop_scope(s);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_eval_ret_undefined(JSParseState *s)
|
static void set_eval_ret_undefined(JSParseState *s)
|
||||||
|
|||||||
4
test.ce
4
test.ce
@@ -289,11 +289,11 @@ function run_tests(package_name, specific_test) {
|
|||||||
if (is_function(test_mod)) {
|
if (is_function(test_mod)) {
|
||||||
tests.push({name: 'main', fn: test_mod})
|
tests.push({name: 'main', fn: test_mod})
|
||||||
} else if (is_object(test_mod)) {
|
} else if (is_object(test_mod)) {
|
||||||
for (var k in test_mod) {
|
arrfor(array(test_mod), function(k) {
|
||||||
if (is_function(test_mod[k])) {
|
if (is_function(test_mod[k])) {
|
||||||
tests.push({name: k, fn: test_mod[k]})
|
tests.push({name: k, fn: test_mod[k]})
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length(tests) > 0) {
|
if (length(tests) > 0) {
|
||||||
|
|||||||
@@ -781,24 +781,6 @@ return {
|
|||||||
if (sum != 25) throw "for loop continue failed"
|
if (sum != 25) throw "for loop continue failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_for_in_array: function() {
|
|
||||||
var arr = [10, 20, 30]
|
|
||||||
var sum = 0
|
|
||||||
for (var i in arr) {
|
|
||||||
sum = sum + arr[i]
|
|
||||||
}
|
|
||||||
if (sum != 60) throw "for in array failed"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_for_in_object: function() {
|
|
||||||
var obj = {a: 1, b: 2, c: 3}
|
|
||||||
var sum = 0
|
|
||||||
for (var key in obj) {
|
|
||||||
sum = sum + obj[key]
|
|
||||||
}
|
|
||||||
if (sum != 6) throw "for in object failed"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_nested_for_loops: function() {
|
test_nested_for_loops: function() {
|
||||||
var sum = 0
|
var sum = 0
|
||||||
for (var i = 0; i < 3; i = i + 1) {
|
for (var i = 0; i < 3; i = i + 1) {
|
||||||
@@ -1658,18 +1640,6 @@ return {
|
|||||||
if (o[k] != 200) throw "same object should be same key"
|
if (o[k] != 200) throw "same object should be same key"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_object_key_not_in_for_in: function() {
|
|
||||||
var k = {}
|
|
||||||
var o = {a: 1, b: 2}
|
|
||||||
o[k] = 999
|
|
||||||
var count = 0
|
|
||||||
for (var key in o) {
|
|
||||||
count = count + 1
|
|
||||||
if (key == k) throw "object key should not appear in for-in"
|
|
||||||
}
|
|
||||||
if (count != 2) throw "for-in should only see string keys"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_object_key_computed_property: function() {
|
test_object_key_computed_property: function() {
|
||||||
var k = {}
|
var k = {}
|
||||||
var o = {}
|
var o = {}
|
||||||
@@ -3462,24 +3432,6 @@ return {
|
|||||||
if (data.users[1].name != "Bob") throw "mixed nested access failed"
|
if (data.users[1].name != "Bob") throw "mixed nested access failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_empty_object_iteration: function() {
|
|
||||||
var obj = {}
|
|
||||||
var count = 0
|
|
||||||
for (var k in obj) {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
if (count != 0) throw "empty object iteration failed"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_empty_array_iteration: function() {
|
|
||||||
var arr = []
|
|
||||||
var count = 0
|
|
||||||
for (var i in arr) {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
if (count != 0) throw "empty array iteration failed"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_object_with_null_value: function() {
|
test_object_with_null_value: function() {
|
||||||
var obj = {a: null, b: 2}
|
var obj = {a: null, b: 2}
|
||||||
if (obj.a != null) throw "object null value failed"
|
if (obj.a != null) throw "object null value failed"
|
||||||
|
|||||||
@@ -166,26 +166,26 @@ function check_link_cycles() {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var origin in links) {
|
arrfor(links, function(origin) {
|
||||||
var cycle_start = follow_chain(origin, {})
|
var cycle_start = follow_chain(origin, {})
|
||||||
if (cycle_start) {
|
if (cycle_start) {
|
||||||
add_error("Link cycle detected starting from: " + origin)
|
add_error("Link cycle detected starting from: " + origin)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for dangling links
|
// Check for dangling links
|
||||||
function check_dangling_links() {
|
function check_dangling_links() {
|
||||||
var links = link.load()
|
var links = link.load()
|
||||||
|
|
||||||
for (var origin in links) {
|
arrfor(array(links), function(origin) {
|
||||||
var target = links[origin]
|
var target = links[origin]
|
||||||
if (starts_with(target, '/')) {
|
if (starts_with(target, '/')) {
|
||||||
if (!fd.is_dir(target)) {
|
if (!fd.is_dir(target)) {
|
||||||
add_error("Dangling link: " + origin + " -> " + target + " (target does not exist)")
|
add_error("Dangling link: " + origin + " -> " + target + " (target does not exist)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gather packages to verify
|
// Gather packages to verify
|
||||||
|
|||||||
Reference in New Issue
Block a user